在图像中查找正方形

信息处理 Python matlab 图像处理 opencv 计算机视觉
2021-12-23 22:00:26

我需要使用 OpenCV 找到图像中的正方形(在 matlab 或其他任何方法中都没有问题,通常我期望的是一些想法)。

考虑下面的测试图像:

在此处输入图像描述

我需要准确地找到上图中的那些彩色方块(不是白色的长条)。

我做了什么 :

  • 我应用了常用方法(OpenCV 样本附带),即在所有颜色平面中找到轮廓,对其进行近似并检查元素数=4。它在某种程度上起作用,检测到的正方形很少,尤其是深色的。

  • 我做的下一步是预测这种安排是固定的因此,如果获得了一些,我可以预测剩余的。它还进一步发挥了作用。但是准确性非常差。

但我觉得预测在这里不是一个好方法,它并不总是提供第一步给出的准确答案。

我需要的 :

1)还有其他更好的方法可以更准确地检测这些正方形吗?还是多种方法?

重要的一点是,时间在这里不是问题算法可能很慢,没关系。但准确性是主要标准。

有时,图像可能会更加模糊。

我面临的一个主要问题是某些方块的颜色与背景颜色几乎相似(检查第 3 列的第一个和第二个方块)。

寻找想法,提前谢谢

更新 :

以下是我得到的最准确的结果:

在此处输入图像描述

当然,结果图像会稍微调整大小。

更新 2:

我在下面的回答中给出了更好的解决方案:https ://dsp.stackexchange.com/a/7526/818

4个回答

使用 Matlab 的第一次尝试:

im = imread('squares.jpg');
im2 = rgb2gray(im);

se = strel('disk', 15);

for i = 1:16;
    t = 60+i*5; % try out a range of bw thresholds to see what works best
    labelled = bwlabel(im2>t); % label regions in the BW image
    closed = imclose(labelled, se); % close small regions
    cleared = imclearborder(~closed,4); % clear regions touching the border
    subplot(4,4,i); 
    imshow(cleared); 
    title(['T = ' num2str(t)]);
end

结果在以下地区:

标记区域

如您所见,选择导致最多区域数(T=120)的阈值已经给出了 7 个正确位置、一些合并位置、一个误报和两个误报。

这是一个相当简单的尝试,但我认为它表明该方法有效。添加一些东西来分解拉长的区域,或者分别为每个颜色通道执行此操作只是您可以做的几件事来改进这一点。

如果您提供更多测试图像也会有所帮助。

我曾尝试过其他方法来改善我的问题。下面的解决方案是假设第一个正方形(橙色)总是在步骤 1 中被检测到。它是实用的,因为它与背景相比具有高对比度的颜色。即使我显示的结果也正确检测到它

第 1 步:找到尽可能多的正方形

我将图像拆分为 R、G、B、H、S、V 平面,并针对不同的阈值(例如 25 的倍数)对图像进行阈值处理。对于每个图像,我在其中找到了正方形,并将它们放在“蒙版图像”上。我还发现了正方形的平均高度和宽度。

掩码图像(检测到的总 7/12 方格):

蒙版图像

第 2 步:形成一个正方形网格

接下来,我在掩码图像中找到了这些正方形的质心。对它们进行排序并找到第一个正方形(橙色)的质心。仔细分析,我们可以看到两个正方形之间的差距在水平和垂直方向上都是一个正方形。所以通过这种方式,我制作了一个如下所示的正方形网格并将其命名为Ideal_squares(它只是一个名称,并不意味着这是我需要的输出):

理想平方:

理想形象

第 3 步:重新映射理想图像

现在我们有了 Ideal_squares 质心和原始质心。我从 Ideal_centroids 中找到了每个原始质心的正确匹配项(通过取它们之间的欧几里得距离)。然后我使用 Scipy interpolate.griddata 进行插值,并根据质心值重新映射 Ideal_image(这与这些问答中所做的扭曲几乎相同:如何在 OpenCV中去除数独平方和图像转换中的凸面缺陷)。所以下面是我得到的输出:

输出 :

输出图像

第 4 步:或使用第一步的掩码图像对输出进行操作

最终输出

现在你可以看到所有的方块都被检测到了,但是下面提到了一个问题:

问题 :

查看步骤 3 的输出,即重新映射的方形网格图像。除了两个中心方块外,所有其他方块都被剪裁掉。这是与此重新映射相关的问题。我不确定问题出在哪里,使用 scipy.interpolate.griddata() 或 cv2.remap()。我以为整个图像会变形,但事实并非如此。它只扭曲我们给定的质心内的图像。如果我能纠正它,输出就可以了。

所以如果有人知道一个好主意,欢迎!

第 1 步:无论您从 B、G、R、H、S、V 平面中分析得到的最终二进制图像是什么,都在该图像中执行 blob 计数算法。

第 2 步:根据面积或轮廓长度找到最大的斑点。由于您的斑点将主要是平行四边形类型,因此面积或轮廓,任何一个都可以。

第 3 步:使用最大的 blob(因为最大的 blob 是类似于现实世界正方形的最佳 blob)尝试找到 blob 的方向......这可以通过拟合最佳拟合矩形来获得,或者您可以获得角点...获取连接它们的线的斜率(在水平方向和垂直方向上)。

第4步:一旦你得到两个斜坡,画两条穿过斑点轴的线。对于轴,您可以平均角点,也可以使用质心(质心)...我会使用角点的平均值...

第5步:由于在每个水平和垂直方向上,间距都是相等的(理想的水平和垂直间距也相等,因为它来自您理想的方形图片,但我们不会假设它..)只需要找到另一个可能的质心平行四边形

底线:如果任何一个正方形被完美地检测到,您就可以制作整个网格。只需沿最大斑点的水平轴以 2H 的间隔(H = 最大斑点的水平宽度)保持标记中心,并沿斑点的垂直轴垂直保持 2V 的间隔(V = 最大斑点的垂直高度)。

一些图片支持 在此处输入图像描述

在此处输入图像描述

注意:这种方法会很慢。

生成一个看起来像理想对象轮廓的蒙版。与此类似:

对象的掩码

然后在图像上滑动(位置,缩放,旋转)蒙版并将其与真实图像的轮廓匹配(可能稍微模糊以获得更柔和的响应)以计算它们的相似程度,(位置,缩放,旋转)最高相似度响应应该是真实对象的(位置、比例、旋转)。

该方法不介意将正方形融入背景甚至对象的部分遮挡,因为它考虑了整个对象。

我个人已经成功地使用这种方法来跟踪鼠标的鼻子和胡须,但我有一些假设,比如它接近最后一个已知位置等。但我认为你可以通过应用一些假设来降低搜索空间:可能的大小相机中物体的距离,它可以离中心多远或旋转<10度等。