修剪图像片段的剩余部分

时间:2016-05-22 15:42:36

标签: matlab image-processing image-segmentation watershed pruning

正如您在下面的图片中看到的,在我的一些分割结果中(通过分水岭变换方法进行分割),剩下一些残羹剩饭。我想以某种方式裁剪图像,以便只保留矩形。此操作仅基于矩形,与强度级别无关。

enter image description here enter image description here enter image description here

enter image description here enter image description here enter image description here

1 个答案:

答案 0 :(得分:5)

解决方案说明

我建议采用以下方法:

  1. 根据几何属性生成形状的4个角的初始猜测(详见下面的代码)。

  2. 通过在每对相应角之间画一条线,在给定这4个角的情况下创建一个四边形。

  3. 找到优化边界图像的Jaccard系数和生成的四边形地图的角落。

  4. 为了节省时间,优化阶段将在本地完成。我们将尝试用某个社区中可实现的最佳角落替换每个角落。如果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的以下answer

    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. 请注意,此解决方案并未估算出最佳矩形 - 它估计最佳四边形。原因是输入图像不是矩形(线条不平行)。