0

下の画像でわかるように、私のセグメンテーション結果 (分水界変換法によるセグメンテーション) の一部には、いくつかの残り物が残っています。長方形だけが残るように、どういうわけか画像をトリミングしたいと思います。この操作は長方形の形状のみに基づいており、強度レベルには関係ありません。

ここに画像の説明を入力 ここに画像の説明を入力 ここに画像の説明を入力

ここに画像の説明を入力 ここに画像の説明を入力 ここに画像の説明を入力

4

1 に答える 1

5

解決策の説明

次のアプローチをお勧めします。

  1. ジオメトリ プロパティに従って、形状の 4 つのコーナーの初期推定を生成します (詳細については、以下のコードを参照してください)。

  2. 対応する角の各ペア間に線を引くことにより、これらの 4 つの角が与えられた四角形を作成します。

  3. 境界画像と生成された四角形マップの Jaccard 係数を最適化するコーナーを見つけます。

時間を割くために、最適化段階はローカルで行われます。各コーナーを、特定の近隣で達成可能な最高のコーナーに置き換えようとします。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

結果

最初の画像 (前後):

ここに画像の説明を入力

2番目の画像(前後):

ここに画像の説明を入力

ランタイム

Elapsed time is 0.033998 seconds.

可能な改善/提案

  1. エネルギー関数には、平行線が同様の​​勾配を持つようにする制約も含まれる場合があります(あなたの例では、同じ勾配を持っていません)。

  2. エネルギー関数には、各コーナー角度を 90 度に近づける制約が含まれる場合があります。

  3. 小さなアーティファクトを除去するために、このアプローチを実行する前にノイズ削減ステージ (imclose など) を実行できます。

  4. いくつかの初期推測でアルゴリズムを実行し、最適なものを選択することができます。

  5. このソリューションは、可能な限り最良の四角形を推定するのではなく、最良の四角形を推定することに注意してください。その理由は、入力画像が長方形ではない (線が平行でない) ためです。

于 2016-06-04T13:22:34.610 に答える