我创建了一个iPhone应用程序,可以扫描一张方格纸的图像,然后可以告诉我哪些方块已被涂黑,哪些方块是空白的。
我这样做是通过从左到右扫描并使用方格纸的线作为指南。当我遇到方格纸线时,我开始寻找黑色,直到我再次点击方格纸线。然后,我继续沿着扫描线继续前进,完全扫描方块为黑色。然后我继续下一个方框。在该行的最后,我在新行开始扫描之前跳过这么多像素(因为我已经弄清楚每个盒子有多高)。
这种作品,但有问题。有时我把图形线误认为是“黑色”。有时,如果图像歪斜,或者我的页面没有均匀的照明,那么我的效果不会很好。
我想要做的是指定一些“对齐”框,然后我调整大小并旋转(和倾斜)图片以与这些对齐。然后,我想,一旦我将图像对齐,我就会知道所有盒子的位置,并且不必扫描盒子,只需扫描盒子的位置,看看它们是否是黑色的。这应该更快,更可靠。如果我操作来自相机的图像,我可以更灵活地要求用户对齐图片以匹配对齐标记,而不是自己对齐图像。
鉴于这是我的第一个图像处理项目,我觉得我正在重新发明轮子。我想了解如何执行此操作以及是否使用OpenCV等库。
我附上的图像与我想要处理的图像类似。我正在寻找具有大量黑色标记的所有正方形的列表,即A8,C4,E7,G4,H1,J9。
需要注意的问题:
答案 0 :(得分:5)
首先,这个问题提醒了我一些可能有用的演示:
就个人而言,我认为最简单的方法是检测图像中的方块。
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'检测方块。 “范围”度量标准衡量填充边界框的比例。这使它成为一个
区分圆形和正方形的好方法
stats = regionprops(L, 'Extent');
extent = [stats.Extent];
idx1 = find(extent > 0.8);
bw = ismember(L, idx1);
4)这将为您提供功能,同步或纠正图像。一种简单而强大的方法是通过自相关函数。
这提供了很好的峰值,很容易检测到。可以通过匈牙利算法将这些峰与来自模板图像的ACF峰匹配。匹配后,您可以更正旋转和缩放,因为您现在拥有一个可以解决的线性系统:
x = Ax'
然后可以使用普通的交叉相关对相同的预定义模板进行翻译。
如果一切顺利,你知道有一个对齐或同步的图像,这应该有助于确定点的位置。
答案 1 :(得分:3)
我已经开始使用我的GPUImage iOS框架做类似的事情,所以这可能是在OpenCV或其他方面完成所有这些操作的替代方法。正如它的名字所示,GPUImage完全基于GPU,因此它可以比CPU绑定处理具有一些巨大的性能优势(处理实时视频的速度提高了180倍)。
作为第一阶段,我拍摄了你的图像并通过一个阈值为0.5的简单亮度阈值滤波器运行它们,并为你的两个图像得到以下信息:
我刚刚添加了一个自适应阈值滤波器,它试图校正局部照明方差,并且非常适合挑选文本。但是,在你的图像中,它使用太小的平均半径来很好地处理你的斑点:
并且似乎会显示出您想要忽略的网格线。
Maurits对您可以做的事情提供了更全面的描述,但可能有一种方法可以将这些处理操作实现为基于GPU的高性能过滤器,而不是依赖于相同计算的较慢的OpenCV版本。如果您可以从此阈值图像中获取旋转和缩放信息,则可以构建一个变换,该变换也可以作为过滤器应用于阈值图像,以生成最终对齐的图像,然后可以对您的应用程序进行下采样并读取以确定填写了哪些网格位置。
这些基于GPU的阈值处理操作在iPhone 4上的640x480帧上运行时间不到2毫秒,因此可以将滤波器链接在一起,以便像设备的摄像机一样快地分析输入视频帧。