图像处理用于识别2D特征。

4
我创建了一个iPhone应用程序,可以扫描图纸页面的图像,并告诉我哪些方格被涂黑,哪些方格是空白的。
我从左到右进行扫描,并使用图纸上的线作为指南。当我遇到图纸线时,我开始寻找黑色,直到再次遇到图纸线。然后,我不再沿着扫描线继续,而是完全扫描该方格以寻找黑色。然后我继续下一个框。在行末,我跳过几个像素然后重新开始扫描新一行(因为我已经确定每个框有多高)。
这种方法有点有效,但存在问题。有时我会将图纸线误认为是“黑色”。有时,如果图像倾斜或页面照明不均匀,则无法获得良好的结果。
我想做的是指定几个“对齐”框,然后调整图片大小和旋转(和扭曲)以与这些框对齐。然后,我想,一旦我对齐了图像,我就知道所有方格的位置,就不必扫描方格,只需扫描方格位置内部以查看它们是否为黑色。这样应该更快,更可靠。如果我要操作来自相机的图像,我将更有灵活性,可以要求用户将图片对齐以匹配对齐标记,而不是必须自己对齐图像。
鉴于这是我的第一个图像处理项目,我感觉自己在重复造轮子。我希望得到关于如何做到这一点以及是否使用OpenCV等库的建议。
我附上了一个类似于我想要处理的图像。我正在寻找所有具有显着黑色标记的方格列表,即A8、C4、E7、G4、H1、J9。
注意以下问题:
  • 图像的光覆盖可能不是理想的,但应在整个图像中相对一致(即没有阴影)。
  • 所有方块都可以为空或全部为黑色,并且算法需要能够确定这一点。
  • 图像可能会倾斜或绕任何轴旋转。绕z轴的旋转可能很容易修复。可能会围绕x或y轴旋转,使图像的一侧比另一侧宽。然而,如果我实时扫描从相机接收的图像,我可以要求用户将对齐标记与屏幕上的标记对齐。如何最好地确保对齐以给用户适当的反馈?只检查4个角是否为黑色可能会产生误报,当相机指向黑色表面时。
  • 并不是每个方格都会被均匀或持续涂黑,但我认为会有足够的黑色,让人类眼睛毫无疑问。
  • 蓝色网格可能有用,但有些情况下黑色标记可能会重叠蓝色网格。我认为虚拟网格可能比依赖打印网格更好。我认为使用对齐标记来对齐图像,然后允许布置精确虚拟网格。然后可以对每个网格框的内容进行采样,以查看它是否主要为黑色,而不是从左到右扫描,对吧?这是另一张有更多网格标记的图像。在此图像中,除了先前标记的A8、C4、E7、G4、H1、J9、I之外,我还标记了E2、G8和G9、I4和J4,您可以看到蓝色网格被遮挡。

第二张图片

  • 这是我这个项目的第一阶段。最终,我希望将该算法扩展到能够处理至少几百个插槽和可能不同的颜色。

1
请发布几张实际的图片。 - Maurits
@Maurits 已添加。感谢您的提问。 - mahboudz
蓝色方格是否可以被算法使用? - Maurits
在第一次迭代中,是的。然而,为了使机制更加健壮,它可能应该创建自己的虚拟边界,而不是依赖于蓝色网格。我会发布另一张图片来展示标记如何重叠蓝色网格并可能导致问题。 - mahboudz
2个回答

6
首先,这个问题让我想起了一些演示文稿,可能对学习有用: 个人认为,最简单的方法是检测图像中的方块。
1)去除背景和小垃圾
f_makebw = @(I) im2bw(I.data, double(median(I.data(:)))/1.3);
bw = ~blockproc(im, [128 128], f_makebw);
bw = bwareaopen(bw, 30);

在此输入图片描述

2) 仅保留正方形和圆形。

se = strel('disk', 5);
bw = imerode(bw, se);

% Detect the squares and cricles via morphology
[B, L] = bwboundaries(bw, 'noholes');

3) 使用regionprops中的'extend'来检测正方形。 'Extent'指标衡量了边界框填充的比例。这使得它成为区分圆和正方形的好指标。

stats = regionprops(L, 'Extent'); 
extent = [stats.Extent];
idx1 = find(extent > 0.8);
bw = ismember(L, idx1);

输入图像描述

4) 这样,您就可以使用您的特征来进行图像同步或校正。 一种简单而强大的方法是通过自相关函数来实现。

输入图像描述

这会产生漂亮的峰值,很容易检测到。 可以使用匈牙利算法将这些峰值与模板图像中的ACF峰值进行匹配。 匹配后,您可以纠正旋转和缩放,因为现在您有一个线性系统可以解决:

x = Ax'

然后,可以使用跑通常的交叉相关来校正翻译。 对于相同预定义模板的交叉相关。

如果一切顺利,您现在已经拥有了对齐或同步的图像,这应该有助于确定点的位置。


谢谢。这让我有很多思考的地方。你的例子是MatLab代码,对吗?iPhone数独链接非常有帮助。我也会研究OpenCV。 - mahboudz
这是Matlab,如果你想的话我可以分享一个能做所有事情的函数。至于iPhone开发,我无法帮助你... - Maurits
如果有的话,我很想看一些C代码。但是像你给我的这些一般性的想法也很有帮助。我可以轻松地做出黑白和反色效果。我不确定bwareaopen、strele和imerode是做什么的,但我想我可以很容易地查找它们。我也很好奇OpenCV中有多少是这样完成的。然后,我有这个想法,一旦我把所有东西都关联起来,我就可以轻松地查看我可以期望找到圆形的位置,并检测它们——因为它们要么是白色的,要么是黑色的,不需要与周围环境对比才能识别。 - mahboudz
我想购买MatLab。你知道我是否需要计算机视觉工具箱来完成上述任务吗? - mahboudz
@mahboudz,不仅仅是图像处理工具箱。 - Maurits
显示剩余3条评论

4
我一直在使用我的GPUImage iOS框架开始做类似的事情,这可能是在OpenCV或其他东西中完成所有这些工作的替代方法。正如其名称所示,GPUImage完全基于GPU,因此它可以比基于CPU的处理具有巨大的性能优势(对于处理实时视频等任务,速度可提高180倍)。
首先,我将您的图像通过简单的亮度阈值过滤器进行了处理,阈值为0.5,得到了以下两个图像:

Threshold image 1 Threshold image 2

我刚刚添加了一种自适应阈值过滤器,它试图纠正局部光照差异,并且在挑选文本方面效果非常好。然而,在您的图像中,它使用的平均半径太小,无法很好地处理您的斑点。

Adaptive threshold image 1 Adaptive threshold image 2

并且似乎让您的网格线条更加清晰,而您似乎希望忽略这些线条。Maurits提供了更全面的描述,但可能有一种方法可以将这些处理操作实现为基于高性能GPU的滤波器,而不是依赖于较慢的OpenCV版本进行相同的计算。如果您可以从这个阈值图像中获取旋转和缩放信息,那么您可以构造一个变换,该变换也可以作为过滤器应用于您的阈值图像,以生成最终对齐的图像,然后可以通过您的应用程序对其进行降采样和读取,以确定哪些网格位置被填充。这些基于GPU的阈值操作在iPhone 4上的640x480帧上运行时间不到2毫秒,因此可能可以将滤波器链接在一起,以尽可能快地分析设备的视频摄像头提供的传入视频帧。

我现在看到了你提供的GPUImage链接。我会进行调查。 - mahboudz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接