Matlab:给出4个点,拟合最近的菱形/正方形

时间:2014-06-17 10:57:00

标签: matlab image-processing

我需要一个"检查"如果4个给定点形成正方形或菱形。

我正在使用QR代码分段脚本,在该脚本中,我尝试通过查找按行和列遍历的二进制图像的非负值来定位顶点。

在某些情况下,检查不是必需的,如下图所示:

nice result

有点难以看到,但顶点被标记为绿色,品红色,青色和黄色的4个点。在这种情况下,脚本应该返回相同的输入点,因为不需要修改。

另一方面,有些情况下顶点标记为:

not nice

可以看出,品红色和青色标签依赖于图像的右上角。这显然不正确,但它满足指定的条件:遍历图像的每一行,直到找到满足sum(row)>1的行(大于1以避免单个噪声像素)。

如何找到错位的顶点并使用剩余的顶点坐标放置它?

修改

解决了这个问题。我发布了函数的代码,以防有人需要它:

function correctedCorners = square(corners)
    correctedCorners = corners;
    X = corners(:,1);
    Y = corners(:,2);
    sortedX = sort(corners(:,1));
    sortedY = sort(corners(:,2));
    %% DISTANCES BW POINTS
    for i=1:4
        for j=1:4
            distances(i,j) = sqrt((corners(i,1)-corners(j,1))^2+        (corners(i,2)-corners(j,2))^2);
        end
    end
    %% relationship bw distances
    % check corner 1
    d11 = distances(1,1);%0
    d12 = distances(1,2);%x
    d13 = distances(1,3);%sqrt(2)*x
    d14 = distances(1,4);%x
    bool1 = [(d12*0.8<=d14)&(d12*1.2>=d14) (d12*0.8*sqrt(2)<=d13)&                (d12*1.2*sqrt(2)>=d13) (d14*0.8<=d12)&(d14*1.2>=d12) (d14*0.8*sqrt(2)<=d13)&(d14*1.2*sqrt(2)>=d13)];
    % check corner 2
    d21 = distances(2,1);%x
    d22 = distances(2,2);%0
    d23 = distances(2,3);%x
    d24 = distances(2,4);%sqrt(2)*x
    bool2 = [(d21*0.8<=d23)&(d21*1.2>=d23) (d21*0.8*sqrt(2)<=d24)&(d21*1.2*sqrt(2)>=d24) (d23*0.8<=d21)&(d23*1.2>=d21) (d23*0.8*sqrt(2)<=d24)&(d23*1.2*sqrt(2)>=d24)];
    % check corner 3
    d31 = distances(3,1);%sqrt(2)*x
    d32 = distances(3,2);%x
    d33 = distances(3,3);%0
    d34 = distances(3,4);%x
    bool3 = [(d32*0.8<=d34)&(d32*1.2>=d34) (d32*0.8*sqrt(2)<=d31)&(d32*1.2*sqrt(2)>=d31) (d34*0.8<=d32)&(d34*1.2>=d32) (d34*0.8*sqrt(2)<=d31)&(d34*1.2*sqrt(2)>=d31)];
    % check corner 4
    d41 = distances(4,1);%x
    d42 = distances(4,2);%sqrt(2)*x
    d43 = distances(4,3);%x
    d44 = distances(4,4);%0
    bool4 = [(d41*0.8<=d43)&(d41*1.2>=d43) (d41*0.8*sqrt(2)<=d42)&(d41*1.2*sqrt(2)>=d42) (d43*0.8<=d41)&(d43*1.2>=d41) (d43*0.8*sqrt(2)<=d42)&(d43*1.2*sqrt(2)>=d42)];
    bool = [bool1; bool2;bool3;bool4];
    idx = 0;
    for i=1:4
        if (sum(bool(i,:))==0)
            idx = [idx i];
        end
    end
    if (length(idx)>=2)
        for i=2:length(idx)
            switch idx(i)
                case 1
                    correctedCorners(1,:) =         abs(corners(4,:)-(corners(3,:)-corners(2,:)));
                case 2
                    correctedCorners(2,:) = abs(corners(3,:)-(corners(4,:)-corners(1,:)));
                case 3
                    correctedCorners(3,:) = abs(corners(2,:)+(corners(1,:)-corners(1,:)));
                case 4
                    correctedCorners(4,:) = abs(corners(1,:)+(corners(3,:)-corners(2,:)));
            end
        end
    end

1 个答案:

答案 0 :(得分:1)

关于正方形的基本几何:

  • 距离BotLeft = x
  • 的TopLeft距离
  • TopLeft距离TopRight = x
  • TopLeft距离BotRight = sqrt(2)* x

将BotLeft的相同逻辑用于其他点等。

让自己承担10-20%的误差范围,以宣布错误的观点。也就是说,如果TopLeft距离范围之外的2个点(80%; 120%)* x,并且它到第三个点的距离超出了范围(80%; 120%)* sqrt(2)* x,您可以将该点声明为错误放置。

在您的情况下,TopLeft点在所有距离测试中失败:

  • 0而不是x到TopRight(约100%错误)
  • sqrt(2)* x vs x to BotLeft(约44%的错误)
  • x vs sqrt(2)* x to BotRight)(约31%的错误)

只要菱形非常类似于正方形,将其视为正方形时误差为20%仍应有效。