0

以下の画像に示されているように、私のセグメント化の結果(分水化法によって行われたセグメント化)の中には、残っているものがあります。私は何とか矩形だけが残るように画像を切り抜きたい。この操作は長方形の形状にのみ基づいており、強度レベルには関係しません。画像セグメントの残り物を枝刈りする

enter image description hereenter image description here enter image description here

enter image description hereenter image description here enter image description here

+0

興味深い質問だと思います!あなたが明確なアイデアを持っていない場合、私にいくつかのヒントを与えてください。そうすれば、あなたの考えを使って完全な解決策を見つけることができます。 – Woeitg

+0

不明です。左のイメージはソースですか?そうでない場合は、ソースイメージを表示し、セグメント化の仕方を説明できますか?それはあなたの問題に関連している可能性があるためです。 – kebs

+0

また、あなたが持っているもののいくつかのコードスニペットを示してください。これはOpenCV関連ですか?その場合は、タグを追加します。 – kebs

答えて

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 

(@Sueverにより、以下answerから採取された)drawLine関数

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 

結果

最初の画像(前後):

enter image description here

秒画像(前後):

enter image description here

ランタイム

Elapsed time is 0.033998 seconds. 

可能な改善/提案

  1. エネルギー関数も(で同様の傾きを持つように平行線を奨励制約を含んでいてもよいですあなたの例は同じ勾配を持っていません)。

  2. エネルギー関数には、各角が90度に近づくように促す制約が含まれている場合があります。

  3. 小さなアーチファクトを排除するためにこのアプローチを実行する前にノイズリダクション段階(imcloseなど)を行うことができます。

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

  5. この解決策は最良の四角形を推定するものではなく、最良の四角形を推定することに注意してください。その理由は、入力画像が長方形ではない(線が平行でない)ためです。

関連する問題