如何在OpenCV中消除白噪声并提取连通分量?

问题描述

我正在研究一个数独求解器,它从摄像机(笔记本电脑)获取输入并进行处理,将数独图像解析为列表列表,对其进行求解,然后将解决方案投影到图纸上。

我现在需要识别图像中的每个数字。我正在使用MNIST数据集来训练我的模型,该模型期望每个输入图像的形状为(28,28,1),我能够成功定位每个数字并提取出它,但是对数字执行任何类型的阈值都会导致手指周围有很多噪音,最终导致我的模型分类错误

Warped and Thresholded Sudoku image

有什么方法可以消除白噪声,仅从正方形中提取数字,然后将其输入到Keras模型中。

我认为可以通过使用cv2.connectedComponentsWithStats提取最大的连接组件来实现,但是我不知道该方法的工作方式(以及它期望的参数或方法输出),我无法找到有关如何使用它的很好的解释。

如果除了使用cv2.connectedComponentsWithStats以外,还有其他方法可以产生更好的结果,请提出建议,如果不能,请说明cv2.connectedComponentsWithStats方法的工作方式,或者向我指出有助于我理解的优质资源它以及如何在我的特定情况下使用它。

PS。如果您认为MNIST并不是完成此任务的良好数据集,请务必说明原因以及可能实现数字识别任务的任何其他数据集。

解决方法

要消除噪音,可以使用erosion。它用于滤除白色像素并“填充(白色)间隙”。 每个白色区域都会变小,并且非常小的区域会消失。数字看起来会变稀。

然后您可以扩大dilate以获得与原始图像更相似的图像(细微的数字将变得更胖,看起来像原始的数字,即使几乎没有差异)。

此操作称为开孔。参见https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html

示例:

import cv2
import numpy as np

img = cv2.imread('input.jpg',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
dilatation = cv2.dilate(erosion,iterations = 1)

编辑(3,3)的核用于膨胀,使图像不太模糊。

输入

Input

侵蚀

Erosion

膨胀

Dilatation

,

只需忽略小斑点(小宽度,小高度和/或小面积)。同时,您可以忽略较大的内容。

enter image description here

要跳过网格线,建议重建网格几何形状(使用字符定位网格的列/行,并可能检测长直线),并且仅将斑点完全保留在单元格内。