Python中的图像分类

16

我正在寻找一种分类由大量文本组成的扫描页面的方法。

以下是我的问题的具体细节。我有一个大型扫描文档集合,需要检测这些文档中特定类型的页面的存在。我计划将文档“分裂”成它们的组成页面(每个页面是一个独立的图像),并将每个图像分类为“A”或“B”。但我不知道最好的方法是什么。

更多细节:

  • 我有许多“A”和“B”图像(页面)的例子,因此我可以进行监督学习。
  • 我不清楚如何最好地从这些图像中提取特征进行训练。例如,那些特征是什么?
  • 页面偶尔会轻微旋转,因此如果分类对旋转(以及较小程度的缩放)不太敏感,那将是很好的。
  • 我想要一个跨平台的解决方案,最好是使用纯Python或常用库。
  • 我考虑过使用OpenCV,但这似乎是一种“重量级”的解决方案。

编辑:

  • “A”和“B”页面之间的区别在于,“B”页面上有带有相同一般结构的表单,包括条形码的存在。而“A”页面是自由文本。

它们有什么不同?字体?大小?您能否只OCR一部分(标题或页眉中的作者)? - Nick T
Nick,我添加了一个编辑来澄清这一点。实际上,我的目标是抛弃B页之后的所有内容,因为我不需要对它们进行OCR。所以,在进行任何OCR之前,我真的需要检测它们。 - Kyle
3
这是一个很棘手的问题--除非你的收藏非常庞大,否则手动将页面分类为“A”或“B”会更容易些。你可以编写一个小的GUI应用程序,依次显示它们,这样你只需每页按下一个键即可。 - Katriel
4个回答

9
I will answer in 3 parts since your problem is clearly a large one and I would highly recommend manual method with cheap labour if the collection of pages does not exceed a 1000.
Part 1: 特征提取 - 在目标检测领域中,您有很多特征可供选择。由于您的一个要求是旋转不变性,我建议使用SIFT/SURF类特征。您可能也会发现Harris角等特征适合。决定使用哪些特征可能需要专业知识,如果您拥有计算能力,我建议创建一个漂亮的特征混合物,并通过分类器训练基于重要性估计器进行传递。
Part 2: 分类器选择 - 我非常喜欢随机森林分类器。这个概念非常简单易懂,它非常灵活和非参数化。调整需要非常少的参数,您还可以在监督训练期间以参数选择模式运行它。 第三部分:实现 - Python本质上是一种胶水语言。纯Python实现图像处理永远不会非常快。我建议使用OpenCV进行特征检测,使用R进行统计工作和分类器。

解决方案可能看起来过于复杂,但即使页面之间的差异仅仅是书的左手和右手页面,机器学习也从未是一项简单的任务。


SIFT 确实是一个好主意,但在这种情况下,由于我们的先验知识(如条形码或明文的存在等),我们可能可以直接定义更定制化的特征(参见我的帖子)。使用分类器训练来找出如何组合我们的特征以给出答案是一个不错的选择。(总体上,对该帖子表示 +1)。 - ThR37
@wok:我认为whatnick想提出一个更一般(和干净)的方法来解决问题,而不是直接深入探讨“我应该使用什么功能?”的问题。我们必须记住,条形码并不是解决这个问题的唯一方法,尝试结合不同的方式。无论如何,你的链接都非常有趣。 - ThR37
非常好的回答。我看到了SIFT和SURF,但是我的应用程序是商业性质的,而SIFT是有专利的。 - Kyle
@Kyle 专利并不意味着无法使用,如果sift确实有用,你只需要支付一笔版税。 - whatnick
这可能是一个早已过时的问题,但如果需要旋转不变性,为什么不使用SPIN呢?据我所知它没有被专利保护,并且具有旋转不变性。 - user334911

4
首先,我想说在我看来OpenCV是这种操作的非常好的工具。此外,它有一个很好描述的Python接口,可以在这里找到。
OpenCV经过高度优化,而你的问题并不容易解决。
以下是一些可能用到的特征的想法:
- 对于检测条形码,如果条形码是孤立的,您应该尝试进行距离变换(OpenCV中的DistTransform)。也许您将能够使用match或matchShapes轻松地找到感兴趣的点。我认为这是可行的,因为条形码应该具有相同的形状(大小等)。感兴趣点的分数可以用作特征。 - 图像的矩可以在这里有用,因为您有不同类型的全局结构。这可能足以区分A和B页面(请参见此处的openCV函数)(顺便说一下,您将获得不变的描述符 :)) - 您应该尝试计算垂直梯度和水平梯度。条形码是一个特定的位置,其中垂直梯度== 0且水平梯度!= 0。这个主要优点是这些操作的成本很低,因为您的目标仅是检查页面上是否有这样的区域。您可以找到感兴趣的区域并将其分数用作特征。
一旦您拥有了这些特征,您可以尝试进行监督学习并测试泛化能力。您的问题需要非常少的假阴性(因为您将扔掉一些页面),因此您应该使用ROC曲线评估性能,并仔细观察灵敏度(应该很高)。 对于分类,您可以使用带有套索惩罚的回归来找到最佳特征。 whatnick的帖子还提供了其他良好的想法和其他描述符(也许更通用)。

3

所以你想通过特定元素区分两种页面 - 基本上是条形码的存在。有两个步骤:

  1. 特征提取(计算机视觉):找到可能是条形码而不是文本的感兴趣点或线。

  2. 二元分类(统计学习):根据提取的特征确定是否存在条形码。


处理第一步,你应该一定要看一下Hough变换。它是用于在图像中识别线条的理想方法,并且对于条形码检测可能很有用。例如,阅读这两个页面。这里有使用OpenCV的示例
关于第二步,最有用的分类方法基于以下几种:
  • 最近邻居
  • 逻辑回归
  • 随机森林(在R中实现非常好,但我不知道Python如何)

Orange学习套件有一个不错的随机森林实现,我在发现R中的实现之前曾经使用过它。 - whatnick

1
你可以尝试将A和B的训练数据上传到demo.nanonets.ai(免费使用),以构建模型。
1)在此处上传您的训练数据:

demo.nanonets.ai

2)然后使用以下Python代码查询API:

import requests
import json
import urllib
model_name = "Enter-Your-Model-Name-Here"
url = "https://cdn.pixabay.com/photo/2012/04/24/12/13/letter-39694_960_720.png"
files = {'uploadfile': urllib.urlopen(url).read()}
url = "http://demo.nanonets.ai/classify/?appId="+model_name
r = requests.post(url, files=files)
print json.loads(r.content)

3) 响应看起来像:
{
  "message": "Model trained",
  "result": [
    {
      "label": "A",
      "probability": 0.97
    },
    {
      "label": "B",
      "probability": 0.03
    }
  ]
}

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