【问题标题】:How to classify blurry numbers with openCV如何使用 openCV 对模糊数字进行分类
【发布时间】:2016-10-05 08:40:45
【问题描述】:

我想从这种图片中捕捉数字。

我尝试通过以下链接进行多尺度匹配。

http://www.pyimagesearch.com/2015/01/26/multi-scale-template-matching-using-python-opencv/

我只想知道红色数字。但问题是,openCV 识别/匹配模板的红色数字是模糊的。是否有其他可能的方法来检测黑色背景上的这个红色数字?

【问题讨论】:

标签: python opencv edge-detection number-recognition


【解决方案1】:

分类数字

您在 cmets 中澄清说您已经隔离了图像预检测的数字部分,所以我将从这个假设开始。

也许您可以通过将其视为手写数字来近似数字的透视效果和“模糊性”。在这种情况下,有一个著名的手写数字数据集用于分类训练,称为 mnist。

Yann LeCun 在mnist hand-written dataset 列举了该数据集的最新技术水平。

在频谱的远端,卷积神经网络产生outrageously low error rates(误差为 1% 的分数)。对于更简单的解决方案,使用去偏斜、去噪、模糊和 2 像素移位的 k 最近邻产生了大约 1% 的误差,并且实施起来明显更快。 Python opencv has an implementation。具有去偏斜的神经网络和支持向量机也有一些令人印象深刻的性能。

请注意,卷积网络不会让您选择自己的特征,因此此处重要的色差信息可能仅用于缩小感兴趣区域。定义特征空间的其他方法可能会更精确地结合已知的色差。

Python 在很棒的包 sklearn - here are examples of sklearn applied to mnist 中支持许多机器学习技术。 如果您正在寻找 Python 中机器学习的教程解释,sklearn's own tutorial is very verbose

来自 sklearn 链接:

如果您使用这种方法进行学习,您会尝试对这些项目进行分类。为了强调开始训练这些基于机器学习的分类器是多么容易,这里是链接 sklearn 包中示例代码的节选部分:

digits = datasets.load_digits() # built-in to sklearn!
data = digits.images.reshape((len(digits.images), -1))

# Create a classifier: a support vector classifier
classifier = svm.SVC(gamma=0.001)

# We learn the digits on the first half of the digits
classifier.fit(data[:n_samples / 2], digits.target[:n_samples / 2])

如果你喜欢openCv(可能是因为你将来想移植到实时系统),opencv3/pythonhas a tutorial on this exact topic too!他们的演示使用了 k-nearest-neighbor(列在 LeCun 页面中),但他们也使用了 have svms 和 sklearn 中的许多其他工具。他们使用 SVM 的 ocr 页面使用去偏斜,这可能对您问题中的透视效果有用:


更新:我在您的图片上使用了上述开箱即用的 skimage 方法,经过大量裁剪,并且它正确分类。需要进行大量更多测试,看看这在实践中是否可靠

^^ 那个小图像是您嵌入问题中的图像的 8x8 裁剪。 mnist 是 8x8 图像。这就是为什么它在 skimage 中使用默认参数在不到一秒的时间内完成训练。

我通过使用将其放大到 mnist 范围将其转换为正确的格式

number = scipy.misc.imread("cropped_image.png")
datum  =  (number[:,:,0]*15).astype(int).reshape((64,))
classifier.predict(datum) # returns 8

我没有更改示例中的任何其他内容;在这里,我只使用第一个通道进行分类,没有智能特征计算。 15 左右看着我;您需要对其进行调整以达到目标范围或(理想情况下)提供您自己的训练和测试集


物体检测

如果您没有隔离图像中的数字,则需要一个对象检测器。关于这个问题的文献空间很大,我不会从那个兔子洞开始(谷歌 Viola 和 Jones,也许?)This blog 涵盖了 Python 中“滑动窗口”检测器的基础知识。 Adrian Rosebrock 看起来他甚至是 SO 的贡献者,并且该页面有一些很好的 opencv 和基于 python 的对象检测器的例子,相当教程(你实际上在你的问题中链接到那个博客,我没有意识到)。

简而言之,对图像中的窗口进行分类并选择置信度最高的窗口。用感兴趣的区域缩小搜索空间当然会在所有性能领域产生巨大的改进

【讨论】:

  • 哦,谢谢 en_Knight。由于我对 opencv 很陌生,请您指导我一些关于如何使用 python 提供的分类功能的教程?我最初的尝试是裁剪图像,以便只出现黑色背景和红色数字。然后运行分类器来识别数字?听起来合法吗?
  • 这听起来不错。如果可以裁剪图像,问题就会变得有趣一万倍;在我的示例中,我们使用他们的内置数字数据集来训练分类器,我在数字周围裁剪了您的图像,然后将其缩小为 8x8。那个skimage链接很难遵循吗?我可以寻找一些替代品,那里肯定有很多分类教程
  • datum = (number[:,:,0]*15).astype(int).reshape((64,)) ------- 我不确定我是否理解这一点线。你能详细给我解释一下吗?我认为它将裁剪图像的大小调整为 8x8,但是当我尝试时,我得到一个值错误,指出数组大小必须保持不变。
  • @spencerJANG imread("cropped_image.png") 行将您的图像作为NxMx3 矩阵从内存加载。就我而言,我已经将其裁剪为8x8 矩阵(我将该图像附加到答案中,以便您可以下载并自己尝试)。您需要提供自己的额外裁剪/缩小代码才能做到这一点。下一行,number[:,:,0] 说“只提取红色通道”,因为我们需要一个灰度图像。你可以用任何你想要的方式让它变灰。 x15 将其缩放到预期范围(再次尝试)。有意义吗?
  • 是的。感谢cmets。只是另一个快速的问题。是否有其他库或工具来计算箭头?字母?就像数字识别一样?
【解决方案2】:

您可以利用以下几点来发挥自己的优势:

  • 数字位于黑色矩形边框和一种颜色内
  • 该数字似乎是分段式 LCD 显示器,如果是这样,则只有有限数量的段处于关闭或打开状态。

所以我建议你:

  • 校准您的相机并预处理图像以消除镜头失真
  • 校正显示矩形:
    • 使用 hough 的交集检测显示矩形 线,或边缘检测,然后是轮廓检测,然后选择 最大、最方形的轮廓
    • 使用GetPerspectiveTransform得到图像坐标与理想矩形之间的变换,然后对输入图像进行变换 使用WarpPerspective
  • 将图像拆分为 R、G 和 B 通道并计算出r - avg(g, b),这有点依赖于光照,但应该给出这样的结果:

  • 然后尝试对此进行模式匹配,或者重新分割图像并尝试找出哪些显示段被点亮,或者通过 OCR 包运行。

【讨论】:

  • “校准你的相机”如果他没有相机参数,这会有多少工作?
  • 如果没有它,它可能会工作,如果您不知道相机参数,可以使用“GML C++相机校准工具箱”或类似的工具
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-30
相关资源
最近更新 更多