【问题标题】:Using C#, how do I search for images in a Windows file system like TinEye.com does on the web?使用 C#,如何在 Web 上的 TinEye.com 等 Windows 文件系统中搜索图像?
【发布时间】:2012-02-04 07:32:35
【问题描述】:

您好,感谢您的关注!

更新

为了清楚起见,第三方 .NET 库就可以了。最好是开源或免费的。解决方案不必是本机 .NET。

背景

我正在开发一个企业 Web 应用程序,客户端为我们提供了数千页 MS Word 文档中的内容,我们必须对其进行解析、提取数据并发送到内容数据库。

在这些文档中包含各种嵌入图像,它们代表单独文件夹中较大的原始图像。

客户端并没有提供任何原始源图片的路径,所以当我们在MS Word doc中看到嵌入图片的内容时,我们必须通过几个“assets”文件夹寻找对应的图片,这是非常特别的耗时。

我们已经在使用DocX 来解析文档,因此您可以假设我们有一个位图图像列表来循环遍历我们从文档中提取的。

问题

给定我们刚刚从文档中提取的位图列表,我们如何在包含数百张图像的不同文件夹中搜索匹配图像,然后将文件路径返回给它?

TinEye.com 通过网络执行此操作。我想知道是否可以使用 System.Drawing 或其他东西在带有 C# 的 PC 上完成。

谢谢!

马特

【问题讨论】:

    标签: c# windows image-processing ms-office system.drawing


    【解决方案1】:

    .NET 框架中没有用于生成图像相似度的内置算法。您需要使用第三方库或自己做。很多关于 SO 的图像相似性算法问题:

    Algorithm for finding similar images

    How can I measure the similarity between two images?

    comparing images programmatically - lib or class

    还有一个,对于 .NET:Are there any OK image recognition libraries for .NET?。这个给你推荐AForge,里面好像有你想要的算法。

    【讨论】:

    • 我会添加另一个类似的问题:stackoverflow.com/questions/225210/removing-duplicate-images
    • 感谢你们俩,但这些链接都没有真正的帮助。这可能就是为什么这个问题在 SO 的各种表现中不断浮出水面的原因。我不在乎这是否发生在本机 .NET 中,一个库就可以了。而且,我目前可能无法自己编写库,所以上面讨论算法理论的所有链接都没有帮助,尤其是那些甚至没有涵盖 .NET 的链接。不过还是谢谢。
    • 查看我的编辑以获取您可能更容易使用的另一个。
    • 啊,是的,我忘记了 AForge,谢谢。去年夏天我偶然发现,图书馆有很多潜力可以做各种各样的事情。倒一杯咖啡的时候,我突然有了一个想法。在进入 AForge 之前,我将尝试它,看看它是否有效。同时为 AForge 投票。干杯!
    • 好吧,几个小时后我有一个新的每日投票配额;)。
    【解决方案2】:

    根据this SO answer 的类似问题,您应该查看 OpenCV 和 VLFeat。前者有 C++ API,后者有 C API,因此您需要编写自己的 P/Invoke 包装器,或者可能将它们包装在 C++/CLI 外观中,您可以从 C# 调用。

    【讨论】:

    • 感谢 dgvid!我会调查这些。与此同时,我将提出一个我刚刚想出的答案,这似乎(对我来说)更优雅一些。
    【解决方案3】:

    不想为我自己的问题提出答案,但我想我可能会在这里做一些事情。以下是 C# 表单应用程序的启发式/伪代码 - 感谢您的想法:

    第 1 部分

    1. 使用 System.IO,遍历“assets”文件夹并获取所有图像。
    2. 对于每个图像,Base64 对其进行编码。
    3. 将生成的字符串放入 XML 文件中:
    <Image>
         <Path>C:\SomePath</Path>
         <EncodedString>[Some Base64 String]<Encoded String>
    </Image>
    

    现在我们有了一个 XML 文件,其中包含所有 原始 图像,采用 Base64 格式,以及它们的文件路径。

    第 2 部分

    1. 使用DocX,从 MS Word Doc 中提取所有图像。
    2. 对于每个图像,使用 Linq-to-Xml 在第 1 部分的 XML 文件中搜索完全匹配。
    3. 如果没有完全匹配,开始迭代 XML 文件并计算 Levenshtein distance
    4. foreach 中,将 XML 节点 ID(或文件路径)和 Levenshtein Distance 作为键值对存储在对象中。
    5. 获取 LD 分数最低的 k/v 对并返回文件路径。
    6. 为了提高性能,请设置容差,以便在某个原始图像与从文档中提取的图像相比具有可接受的低 LD 分数时,foreach 停止。

    由于这是一次性任务,我不需要即时性能。所以,我今晚可以在离开办公室之前运行它,并希望明天回来查看将原始图像连接到文档中嵌入图像的路径列表。

    更新

    上面的启发式方法效果很好!我最终使用Sift library 来有效地计算 Base64 字符串之间的距离。具体来说,我使用了他们的 FastDistance() 方法。即使拍摄照片的角度略有不同,也能 100% 准确地找到我需要的图像。

    【讨论】:

    • 看起来很合理。请注意,它可能受内存限制。您可能需要以某种方式将其分成多个批次。
    • 好点。每个文档最多我有 60 张图像,所以我将在每个文档的基础上进行。现在测试理论。谢谢!
    • 如果同一张图片出现在多个文档中会怎样?
    • 谢谢克里斯。如果多个文档中有一个共同的图像就可以了,因为我只是返回一个文件路径。最终,我会将本地图像发送到 CDN,然后将本地文件路径换成 CDN 路径。由于那时我将在嵌入图像和原始图像文件路径之间建立关联,因此我也可以将其与相应的 CDN 地址交换。谢谢!
    • @ChrisShain-Ah crud。当我尝试将每个 Base64 字符串的长度放入 int[length1,length2] 时遇到 System.OutOfMemory 异常。所以,看起来你对内存问题可能是对的。还在挖。 . .
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 2021-06-03
    • 2017-05-20
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多