обрезка остатков сегментов изображения

Как вы видите на изображениях ниже, в некоторых моих результатах сегментации (сегментация, выполненная методом преобразования водораздела) остались некоторые остатки. Я хочу как-то обрезать изображения, чтобы остались только прямоугольники. Эта операция основана только на форме прямоугольника и не связана с уровнем интенсивности.

введите здесь описание изображения введите здесь описание изображения введите здесь описание изображения

введите здесь описание изображения введите здесь описание изображения введите здесь описание изображения


person Woeitg    schedule 22.05.2016    source источник
comment
Я думаю, это интересный вопрос! если у вас нет четкой идеи, дайте мне подсказку, чтобы я мог использовать вашу идею, чтобы найти полное решение.   -  person Woeitg    schedule 22.05.2016
comment
Неясно. Является ли левое изображение источником? Если нет, не могли бы вы показать исходное изображение и объяснить, как вы делаете сегментацию. Потому что это может быть связано с вашей проблемой.   -  person kebs    schedule 22.05.2016
comment
А также покажите фрагмент кода того, что у вас есть. Это связано с Opencv? Если да, добавьте тег.   -  person kebs    schedule 22.05.2016
comment
Я применил сегментацию водораздела к моему изображению, и левое изображение представляет собой несколько сегментов. правильное изображение является желаемым выходом. вы можете рассматривать левое изображение как источник. это не связано с opencv. К сожалению, я не могу поделиться своим кодом или своим изображением, но я думаю, что это не обязательно, потому что я хочу обрезать эти сегменты только на основе их формы (которая всегда прямоугольная).   -  person Woeitg    schedule 22.05.2016
comment
моя идея состоит в том, чтобы использовать элемент структурирования для реконструкции каждого сегмента. он может двигаться только линейно сверху вниз, чтобы избежать остатков. Что вы думаете об этом?   -  person Woeitg    schedule 23.05.2016


Ответы (1)


Объяснение решения

Я предлагаю следующий подход:

  1. создать начальное предположение для 4 углов формы в соответствии с геометрическими свойствами (дополнительные сведения см. в коде ниже).

  2. создайте четырехугольник, учитывая эти 4 угла, нарисовав линию между каждой парой соответствующих углов.

  3. найти углы, которые оптимизируют коэффициент Жаккара граничного изображения и сгенерированной четырехугольной карты.

В целях экономии времени этап оптимизации будет выполняться локально. Мы постараемся заменить каждый угол лучшим из возможных углов в определенном районе. Останавливаем этап оптимизации, если по каждому из 4-х углов нет улучшения.

код

%reads image
gray = rgb2gray(imread('Bqx51.png'));
I = gray>0;

%extract boundries
B = bwboundaries(I,8);
B = B{1};
boundriesImage = zeros(size(I));
boundriesImage(sub2ind(size(I),B(:,1),B(:,2))) = 1;

%finds best 4 corners
[ corners ] = optimizeCorners(B);

%generate line mask
linesMask =  drawLines(size(I),corners,corners([2:4,1],:));

%fill holes
rectMask = imfill(linesMask,'holes');

%noise reduction
rectMask = I & rectMask;
rectMask = imopen(rectMask,strel('disk',2));

%calculate result 
result = gray;
result(~rectMask) = 0;

%display results
figure,imshow([gray, 255*ones(size(I,1),1),result]);

функция оптимизации угла

function [ corners] = optimizeCorners(pnts)
%OPTIMIZE4PTS Summary of this function goes here
%   Detailed explanation goes here

Y = pnts(:,1);
X = pnts(:,2);

corners = getInitialGuess(X,Y); 
boundriesIm = zeros(max(Y),max(X));
boundriesIm(sub2ind(size(boundriesIm),pnts(:,1),pnts(:,2))) = 1;

%R represents the search radius
R = 3;

%continue optimizing as long as there is no change in the final result
unchangedIterations = 0;
while unchangedIterations<4

    for ii=1:4
        %optimize corner ii
        currentCorner = corners(ii,:);
        bestCorner = currentCorner;
        bestRes = calcEnergy(boundriesIm,corners);
        cornersToEvaluate = corners;
        candidateInds = sum(((repmat(currentCorner,size(X,1),1)-[Y,X]).^2),2)<(R^2);
        candidateCorners = [Y(candidateInds),X(candidateInds)];
        for jj=length(candidateCorners)
            xx = candidateCorners(jj,2);
            yy = candidateCorners(jj,1);
            cornersToEvaluate(ii,:) = [yy,xx];
            res = calcEnergy(boundriesIm,cornersToEvaluate);
            if res > bestRes
                bestRes = res;
                bestCorner = [yy,xx];
            end
        end
        if isequal(bestCorner,currentCorner)
            unchangedIterations = unchangedIterations + 1;
        else
            unchangedIterations = 0;
            corners(ii,:) = bestCorner;

        end
    end
end

end

Рассчитать функцию энергии

function res = calcEnergy(boundriesIm,corners)
%calculates the score of the corners list, given the boundries image.
%the result is acutally the jaccard index of the boundries map and the
%lines map
linesMask =  drawLines(size(boundriesIm),corners,corners([2:4,1],:));
res = sum(sum(linesMask&boundriesIm)) / sum(sum(linesMask|boundriesIm));

end

нахождение начального предположения для функции углов

function corners = getInitialGuess(X,Y)
%calculates an initial guess for the 4 corners

corners = zeros(4,2);

%preprocessing stage
minYCoords = find(Y==min(Y));
maxYCoords = find(Y==max(Y));
minXCoords = find(X==min(X));
maxXCoords = find(X==max(X));
%top corners
topRightInd = find(X(minYCoords)==max(X(minYCoords)),1,'last');
topLeftInd = find(Y(minXCoords)==min(Y(minXCoords)),1,'last');
corners(1,:) = [Y(minYCoords(topRightInd)) X((minYCoords(topRightInd)))];
corners(2,:) = [Y(minXCoords(topLeftInd)) X((minXCoords(topLeftInd)))];
%bottom corners
bottomRightInd = find(Y(maxXCoords)==max(Y(maxXCoords)),1,'last');
bottomLeftInd = find(X(minYCoords)==min(X(minYCoords)),1,'last');
corners(4,:) = [Y(maxXCoords(bottomRightInd)) X((maxXCoords(bottomRightInd)))];
corners(3,:) = [Y(maxYCoords(bottomLeftInd)) X((maxYCoords(bottomLeftInd)))];


end

Функция drawLine (взято из следующего ответа от @Suever)

function mask = drawLines(imgSize, P1, P2)
%generates a mask with lines, determine by P1 and P2 points

mask = zeros(imgSize);

P1 = double(P1);
P2 = double(P2);

for ii=1:size(P1,1)
    x1 = P1(ii,2); y1 = P1(ii,1);
    x2 = P2(ii,2); y2 = P2(ii,1);

    % Distance (in pixels) between the two endpoints
    nPoints = ceil(sqrt((x2 - x1).^2 + (y2 - y1).^2));

    % Determine x and y locations along the line
    xvalues = round(linspace(x1, x2, nPoints));
    yvalues = round(linspace(y1, y2, nPoints));

    % Replace the relevant values within the mask
    mask(sub2ind(size(mask), yvalues, xvalues)) = 1;
end

Результаты

первое изображение (до и после):

введите здесь описание изображения

второе изображение (до и после):

введите здесь описание изображения

Время выполнения

Elapsed time is 0.033998 seconds.

Возможные улучшения/предложения

  1. Функция энергии может также включать ограничения, которые побуждают параллельные линии иметь одинаковые наклоны (в вашем примере они не имеют одинакового наклона).

  2. Энергетическая функция может включать ограничения, которые способствуют тому, чтобы углы каждого угла были близки к 90 градусам.

  3. этапы шумоподавления (такие как imclose) могут быть выполнены перед выполнением этого подхода для устранения небольших артефактов.

  4. Алгоритм можно запустить с несколькими начальными предположениями и выбрать наилучшее.

  5. Обратите внимание, что это решение не оценивает наилучший возможный прямоугольник — оно оценивает наилучший четырехугольник. Причина в том, что входные изображения не являются прямоугольниками (линии не параллельны).

person ibezito    schedule 04.06.2016