Sim*_*ely 38 c# algorithm image image-processing pattern-matching
我有个问题.我的公司给了我一项非常无聊的任务.我们有两个对话框数据库.其中一个数据库包含可怕质量的图像,另一个非常高质量.
不幸的是,可怕质量的对话包含了对其他信息的重要映射.
我的任务是,手动,浏览所有不良图像并将它们匹配到好的图像.
是否有可能在任何程度上自动化这个过程?以下是两个对话框(从Google图像中随机抽取)的示例:


所以我目前正在尝试用C#编写一个程序来从数据库中提取这些照片,循环浏览它们,找到具有常见形状的照片,并返回它们的ID.我最好的选择是什么?
Run*_*ild 29
我真的认为没有理由为此使用任何外部库,我已经做了很多次这样的事情并且以下算法运行得很好.我假设如果你比较两个图像,它们具有相同的尺寸,但你可以只调整一个,如果他们没有.
badness := 0.0
For x, y over the entire image:
r, g, b := color at x,y in image 1
R, G, B := color at x,y in image 2
badness += (r-R)*(r-R) + (g-G)*(g-G) + (b-B)*(b-B)
badness /= (image width) * (image height)
Run Code Online (Sandbox Code Playgroud)
现在,您已经在两个图像之间获得了标准化的错误值,错误越低,图像匹配的可能性越大.这很简单有效,有很多东西可以使它在某些情况下更好或更快地工作,但你可能不需要这样的东西.你甚至不需要将错误标准化,但是如果你想手动查看几个可能的匹配,你就可以为它设置一个阈值.
由于这个问题得到了更多的关注,我决定在你多次处理许多图像的情况下添加一种方法来加快速度.当我有几万个我需要比较的图像时,我使用了这种方法,我确信一对典型的图像会有很大不同.我也知道我的所有图像都是完全相同的尺寸.在您比较对话框的情况下,您的典型图像可能主要是灰色的,并且您的某些图像可能需要调整大小(尽管可能只是表示不匹配),在这种情况下,此方法可能无法获得许多.
想法是形成四叉树,其中每个节点表示节点表示的区域的平均RGB值.因此,4x4图像将具有RGB值等于图像的平均RGB值的根节点,其子节点将具有表示其各自2x2区域的平均RGB值的RGB值,并且它们的子节点将表示各个像素.(实际上,最好不要超过大约16x16的区域,此时你应该开始比较单个像素.)
在开始比较图像之前,您还需要确定不良阈值.您不会以任何可靠的准确度计算高于此阈值的错误,因此这基本上是您愿意将图像标记为"不匹配"的阈值.
现在,当您将图像A与图像B进行比较时,首先要比较其四叉树表示的根节点.像处理单个像素图像一样计算不良情况,如果不良情况超过阈值,则立即返回并报告此级别的不良情况.因为你正在使用标准化的坏处,并且由于使用平方差异来计算坏处,所以任何特定级别的不良将等于或小于较低级别的不良,所以如果它在任何点超过阈值,你知道它也会超过单个像素级别的阈值.
如果阈值测试通过nxn图像,则只需降低到下一级别并将其与2nx2n图像进行比较.一旦你变得足够低,只需比较各个像素.根据您的图像语料库,这可能允许您跳过大量的比较.
Pao*_*tti 14
我个人会去寻找图像哈希算法.
图像散列的目标是将图像内容变换为特征序列,以便获得精简表示.该特征序列(即比特矢量)必须足够短以便快速匹配并保持可区分特征以使相似性测量可行.
有几种算法可以通过开源社区免费获得.
在本文中可以找到一个简单的例子,Neal Krawetz博士展示了Average Hash算法的工作原理:
- 减小尺寸.消除高频和细节的最快方法是缩小图像.在这种情况下,将其缩小到8x8,以便总共有64个像素.不要费心保持纵横比,只需将其压缩到适合8x8的方形.这样,无论比例或纵横比如何,哈希都将匹配图像的任何变化.
- 减少颜色.微小的8x8图像转换为灰度.这会将散列从64像素(64红色,64绿色和64蓝色)更改为64种总颜色.
- 平均颜色.计算64种颜色的平均值.
- 计算位.这是有趣的部分.基于颜色值是高于还是低于均值来简单地设置每个比特.
- 构造哈希.将64位设置为64位整数.只要您保持一致,订单无关紧要.(我使用big-endian从左到右,从上到下设置位.)
David Oftedal编写了一个C#命令行应用程序,它可以使用Average Hash算法对图像进行分类和比较.(我用你的样本图像测试了他的实现,我得到了98.4%的相似度).
此解决方案的主要优点是您只能读取每个图像一次,创建哈希值并根据它们的相似性对其进行分类(例如,使用汉明距离).
通过这种方式,您可以将特征提取阶段与分类阶段分离,如果您发现它不够准确,您可以轻松切换到另一个散列算法.
编辑
你可以在这里找到一个简单的例子(它包括一个40个图像的测试集,它得到40/40的分数).
该商业TinEye API是一个非常不错的选择.
我过去已经完成了图像匹配程序,而现在的图像处理技术令人惊叹,它的先进性非常高.
ps这里你从谷歌那里抽出的两张随机照片来自: http ://www.tineye.com/search/1ec9ebbf1b5b3b81cb52a7e8dbf42cb63126b4ea/
由于这是一项一次性的工作,我将使用脚本(选择您最喜欢的语言;我可能会选择 Perl)和ImageMagick. 您可以使用 C# 来完成与脚本相同的操作,但代码更多。只需调用命令行实用程序并解析结果输出即可。
检查一对相似性的脚本大约有 10 行,如下所示:
首先检索尺寸identify并检查几乎相同的纵横比。如果不是,则不匹配。如果是这样,则使用 将较大的图像缩放到较小的图像convert。您应该提前尝试一些filter选项,以找到在已知等效图像中产生最大相似性的选项。其中九个可用。
然后使用该compare函数生成相似性度量。比较足够智能,可以处理翻译和裁剪。尝试找到一个不会提供太多误报的相似性阈值。