为Dilbert漫画开发图像分类算法的一般方法

32

作为一项自我发展练习,我想开发一个简单的分类算法,可以识别出迪尔伯特漫画中出现的人物角色(Dilbert、PHB、Ratbert等)。

我认为最好的方法是:(1) 对图像应用某种算法,将其转换为一组特征,并且 (2) 利用训练集和可能的机器学习算法之一,将某些特征的存在/缺失与单元格中的特定角色相关联。

那么我的问题是—— (a) 这样做是否正确,(b) 由于有多个分类算法和 ML 算法需要测试,有什么好的方法来找到正确的算法,以及 (c) 鉴于我们实际上正在对漫画进行分类练习,您会从哪些算法开始?


2
有趣的是,我刚刚发现了M.Weber的这篇论文,它涉及到星座(视觉单词)模型,并且在结尾处还包含了处理Dilbert漫画的实验。 - Michal Kottman
4个回答

25

所以我认为你在第一步 (将算法应用于图像,从而将其转换为一组特征) 上走在了正确的道路上。

这个项目比大多数机器学习问题更具挑战性,因为你实际上需要从原始数据中创建训练数据集(由卡通片的各个帧组成)。例如,获取一个帧,识别其中两个角色(Dilbert和带有角的角色(Dilbert的老板,我认为他的名字不知道),从该帧中提取这两个角色,并将适当的类标签(例如,“1”表示Dilbert)附加到每个角色上。

第一步

要从组成Dilbert卡通片的每个帧中提取单个字符,我建议对每个帧进行光谱分解。如果你不熟悉这种技术,它本质上就是一种特征向量分解。

如果你喜欢python(或者R,因为你可以使用像RPy这样的Python-to-R绑定),那么我强烈建议你看看sklearn。特别是这个优秀的库(最初是在SciPy scikits项目伞下开发的,因此使用NumPy + SciPy进行矩阵计算)有几个用于图像分割的算法之一是基于光谱聚类。对于你项目中的这一步骤,你最可能想要查看这两个scikits.learn模块:

  • sklearn.feature_extraction(特别是image子模块)

  • sklearn.cluster.spectral_clustering

这两个模块附带了两个很好的示例脚本。一个脚本用于分割数字照片,链接为这里;另一个脚本用于分割由三个部分互相覆盖的圆所组成的图像,这些圆与背景之间对比度很小,链接为这里。我认为这两个问题都比您需要执行的分解问题更加困难。换句话说,sklearn在源代码分发中包含了两个完整、文档良好的示例脚本,这两个脚本处理的数据类似于您的数据。其中任何一个都可以作为此步骤的出色模板。

第二步 第一步完成后,接下来是第二步:将分解图像的所有组件按照角色名分组,每个组只对应一个Dilbert角色。然后,为每个组分配一个类别标签,例如,如果您的分解步骤得到了四个角色,则分类标签的一个不错的选择是“0”、“1”、“2”和“3”。将这些类别标签附加到每个分解产生的组件矩阵上,以便将每个角色矩阵映射到其相应的类别(Dilbert角色)。

第三步

选择一个合适的机器学习技术。你有很多选择;唯一的标准是该技术属于监督类别(因为你已经为数据分配了类标签),并且它能够作为一个分类器运行(即返回一个类标签,而不是一个输出数值的回归器)。考虑到这是一个个人项目,我建议你选择最有趣的那个。一些满足我刚才提到的标准的技术包括:多层感知器(神经网络)、支持向量机(SVM)和k-近邻(kNN)。

第四步

训练、验证和测试你的分类器。

替代技术: 模板匹配

完成第一步后(每个图像都被分解成一组对象,其中一些无疑代表字符),您可以手动筛选这些分解产物,并收集漫画中每个字符的示例。 这些是模板

接下来,您将从图像中分割出来的对象与这组唯一模板进行比较。在scikit-image中,另一个scipy scikit,您可以使用match_template方法,将模板图像和候选图像作为参数传入。该方法返回一个二维数组,显示像素与像素之间的相关性(介于-1和1之间)。


感谢您提供详细的答案!我是一个Python程序员,所以sklearn看起来是一个很好的起点。我会跟进我学到的内容。 - Andrew J
嗨,我想做类似的事情。你有没有把你的发现写出来? - Declan Cook

2

我认为,总的来说,这是正确的方法,你可以看看两种技术。

  • Eigenfaces,使用特征向量进行人脸识别的所有算法的名称。
  • 词袋或视觉单词方法。

1
你可以尝试通过将训练数据(漫画图像)上传到demo.nanonets.ai(免费使用)来构建模型。
然后使用以下Python代码查询API:
import requests
import json
import urllib
model_name = "Enter-Your-Model-Name-Here"
url = "http://static5.businessinsider.com/image/525464f969bedd0b0422cfb6/dilbert-creator-scott-adams-presents-his-10-favorite-comics-of-all-time.jpg"
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)

响应结果如下:

{
  "message": "Model trained",
  "result": [
    {
      "label": "Dilbert",
      "probability": 0.97
    },
    {
      "label": "PHB",
      "probability": 0.025
    },
    {
      "label": "Ratbert",
      "probability": 0.005
    }
  ]
}

0
这个问题是5年前提出的,因此上面提供的答案已经过时了,因为深度学习在过去的3-4年中改变了计算机视觉的面貌。基于深度学习的解决方案将涉及训练卷积神经网络,该网络将学习特征并在端到端的学习框架中执行分类。然而,由于同一图像中可能存在多个卡通形象,因此图像分类中使用的标准softmax交叉熵损失可能不适用。因此,应使用独立的逻辑回归作为损失函数。每个类别的阈值可以根据在保留验证集上获得的准确性来获得。即使对于卡通形象,最好也使用使用imagenet初始化的预训练模型,而不是从头开始训练(https://arxiv.org/pdf/1611.05118v1.pdf,尽管本文中的最终任务不同,但他们仍然在处理卡通形象)。如果您有丰富的数据,预训练可能并不重要。这项任务可以使用标准库如caffe/torch等来完成。

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