如何对#34;矩形的角落进行平方"用matlab在bw图像中

时间:2016-06-13 06:32:22

标签: matlab image-processing

我有矩形图像或带圆角的变形矩形,如下所示: enter image description here

或者这个:

enter image description here

有没有办法让角落与matlab平方?

然后我怎样才能得到那些新角落的坐标?

谢谢

1 个答案:

答案 0 :(得分:0)

<强>解释

此问题与following question类似。我的答案将与我的答案类似,并进行相关修改。

我们希望找到最符合给定形状的平行四边形角。 可以通过优化找到解决方案,如下所示:

  1. 找到形状的4个角的初始猜测。这可以通过找到曲率最高的边界点来完成,并使用kmean聚类将它们聚类成4组。

  2. 通过在每对相应角之间画一条线,给出这4个角创建一个平行四边形。

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

  4. 优化将在每个角落进行,以便节省时间。

    <强>结果

    初始角落猜测(角落标记为蓝色)

    enter image description here

    最终结果:

    enter image description here

    <强>代码

    主脚本

    %reads image and binarize it
    I = rgb2gray(imread('eA4ci.jpg')) > 50;
    
    %finds boundry of largerst connected component
    boundries = bwboundaries(I,8);
    numPixels = cellfun(@length,boundries);
    [~,idx] = max(numPixels);
    B = boundries{idx};
    
    %finds best 4 corners
    [ corners ] = optimizeCorners(B);
    
    %generate line mask given these corners, fills the result
    linesMask = drawLines(size(I),corners,corners([2:4,1],:));
    rectMask = imfill(linesMask,'holes');
    
    %remove biggest CC from image, adds linesMask instead
    CC = bwconncomp(I,8);
    numPixels = cellfun(@numel,CC.PixelIdxList);
    [~,idx] = max(numPixels);
    res = I;
    res(CC.PixelIdxList{idx}) = 0;
    res = res | rectMask;
    

    优化角落功能:

    function [ corners] = optimizeCorners(xy)
    %finds the corners which fits the most for this set of points
    
    Y = xy(:,1);
    X = xy(:,2);
    
    %initial corners guess
    corners = getInitialCornersGuess(xy);
    boundriesIm = zeros(max(Y)+20,max(X)+20);
    boundriesIm(sub2ind(size(boundriesIm),xy(:,1),xy(:,2))) = 1;
    
    %R represents the search radius
    R = 7;
    
    %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;
    
            for yy=currentCorner(1)-R:currentCorner(1)+R
                for xx=currentCorner(2)-R:currentCorner(2)+R
    
                    cornersToEvaluate(ii,:) = [yy,xx];
                    res = calcEnergy(boundriesIm,cornersToEvaluate);
                    if res > bestRes
                        bestRes = res;
                        bestCorner = [yy,xx];
                    end
                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 = getInitialCornersGuess(boundryPnts)
    %calculates an initial guess for the 4 corners
    
    %finds corners by performing kmeans on largest curvature pixels
    [curvatureArr] = calcCurvature(boundryPnts, 5);
    highCurv = boundryPnts(curvatureArr>0.3,:);
    [~,C] = kmeans([highCurv(:,1),highCurv(:,2)],4);
    
    %sorts the corners from top to bottom - preprocessing stage
    C = int16(C);
    corners = zeros(size(C));
    
    %top left corners
    topLeftInd = find(sum(C,2)==min(sum(C,2)));
    corners(1,:) = C(topLeftInd,:);
    %bottom right corners
    bottomRightInd  = find(sum(C,2)==max(sum(C,2))); 
    corners(3,:) = C(bottomRightInd,:);
    %top right and bottom left corners
    C([topLeftInd,bottomRightInd],:) = [];
    topRightInd = find(C(:,2)==max(C(:,2)));
    corners(4,:) = C(topRightInd,:);
    bottomLeftInd = find(C(:,2)==min(C(:,2)));
    corners(2,:) = C(bottomLeftInd,:);
    
    
    
    end
    
    
    
    function [curvatureArr] = calcCurvature(xy, halfWinSize)
    %calculate the curvature of a list of points (xy) given a window size
    
    %curvature calculation
    curvatureArr = zeros(size(xy,1),1);
    for t=1:halfWinSize
        y = xy(t:halfWinSize:end,1);
        x = xy(t:halfWinSize:end,2);
        dx  = gradient(x);
        ddx = gradient(dx);
        dy  = gradient(y);
        ddy = gradient(dy);
        num   = abs(dx .* ddy - ddx .* dy)  + 0.000001;
        denom = dx .* dx + dy .* dy + 0.000001;
        denom = sqrt(denom);
        denom = denom .* denom .* denom;
        curvature = num ./ denom;
    
        %normalizing
        if(max(curvature) > 0)
            curvature = curvature / max(curvature);
        end
    
        curvatureArr(t:halfWinSize:end) = curvature;
    
    end
    
    end
    

    绘制线条功能:

    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