原文链接: http://codewenda.com/python%E4%BD%BF%E7%94%A8opencv%E5%A4%84%E7%90%86sudoku%E9%97%AE%E9%A2%98/
我正在做一个有趣的项目:使用OpenCV从输入图像中解决Sudoku(如在Google goggles等)。我已经完成了任务,但最后我发现我来到这里的一个小问题。
我使用OpenCV 2.3.1的Python API进行编程。
下面是我做的:


而且这个方法运作良好。
问题:
退房this image.
执行此图像上的步骤4给出以下结果:
绘制的红线是原始轮廓,是数独边界的真实轮廓。
绘制的绿线是近似的轮廓,这将是扭曲图像的轮廓。
当然,在数独顶端的绿线与红线之间有区别。所以在弯曲的时候,我没有得到数独的原始边界。
我的问题 :
如何将图像扭曲在数独的正确边界上,即红线或如何消除红线与绿线之间的差异?在OpenCV中有没有这样的方法?
我有一个解决方案,但您必须自己将其转换为OpenCV。它写在数学中。
第一步是通过将每个像素除以关闭操作的结果来调整图像中的亮度:
|
1
2
3
|
white = Closing[src, DiskMatrix[5]];srcAdjusted = Image[ImageData[src]/ImageData[white]] |

下一步是找到数独区域,所以我可以忽略(掩蔽)背景。为此,我使用连接分量分析,并选择具有最大凸面积的分量:
|
1
2
3
4
5
|
components = ComponentMeasurements[ ColorNegate@Binarize[srcAdjusted], {"ConvexArea", "Mask"}][[All, 2]];largestComponent = Image[SortBy[components, First][[-1, 2]]] |

通过填写这个图像,我得到了数独网格的面具:
|
1
|
mask = FillingTransform[largestComponent] |

现在,我可以使用二阶导数滤波器在两个不同的图像中找到垂直和水平线:
|
1
2
|
lY = ImageMultiply[MorphologicalBinarize[GaussianFilter[srcAdjusted, 3, {2, 0}], {0.02, 0.05}], mask];lX = ImageMultiply[MorphologicalBinarize[GaussianFilter[srcAdjusted, 3, {0, 2}], {0.02, 0.05}], mask]; |

我再次使用连接分量分析从这些图像中提取网格线。网格线比数字长得多,所以我可以使用卡尺长度来选择仅网格线连接的组件。通过位置排序,我获得图像中每个垂直/水平网格线的2×10个掩模图像:
|
1
2
3
4
5
6
7
8
|
verticalGridLineMasks = SortBy[ComponentMeasurements[ lX, {"CaliperLength", "Centroid", "Mask"}, # > 100 &][[All, 2]], #[[2, 1]] &][[All, 3]];horizontalGridLineMasks = SortBy[ComponentMeasurements[ lY, {"CaliperLength", "Centroid", "Mask"}, # > 100 &][[All, 2]], #[[2, 2]] &][[All, 3]]; |

接下来,我采取每对垂直/水平网格线,扩大它们,计算逐像素交点,并计算结果的中心。这些点是网格线交点:
|
1
2
3
4
5
6
7
|
centerOfGravity[l_] := ComponentMeasurements[Image[l], "Centroid"][[1, 2]]gridCenters = Table[centerOfGravity[ ImageData[Dilation[Image[h], DiskMatrix[2]]]* ImageData[Dilation[Image[v], DiskMatrix[2]]]], {h, horizontalGridLineMasks}, {v, verticalGridLineMasks}]; |

最后一步是通过这些点定义X / Y映射的两个插值函数,并使用这些功能转换图像:
|
1
2
3
4
5
6
|
fnX = ListInterpolation[gridCenters[[All, All, 1]]];fnY = ListInterpolation[gridCenters[[All, All, 2]]];transformed = ImageTransformation[ srcAdjusted, {fnX @@ Reverse[#], fnY @@ Reverse[#]} &, {9*50, 9*50}, PlotRange -> {{1, 10}, {1, 10}}, DataRange -> Full] |

所有的操作都是基本的图像处理功能,所以在OpenCV中也是可以的。基于样条曲线的图像变换可能更难,但我不认为你真的需要它。可能使用现在在每个单独的单元格上使用的透视变换将给出足够好的结果。
Code问答: http://codewenda.com/topics/python/
Stackoverflow: How to remove convexity defects in a Sudoku square?
*转载请注明本文链接以及stackoverflow的英文链接
原文:http://www.cnblogs.com/codewenda/p/7746638.html