图片相似度检测

3
我一直在尝试编写一个爬虫程序,用于从Deviantart.com网站爬取数据。程序会将新的图片保存到本地,并在Postgresql数据库中为每张图片创建一条记录。问题是:随着新图片的出现,如何知道这张新图片是否与我以前看过的图片相同?虽然DA上重复图片很少,但更广义的来说,这是一个有趣的问题。
有什么想法可以解决这个问题吗?
目前,当我爬取图片时,Postgresql数据库被填充并且其中有一张表格,看起来像这样:
CREATE TABLE Image
(
    id SERIAL PRIMARY KEY NOT NULL,
    url varchar(5000) UNIQUE NOT NULL,
    dateadded timestamp without time zone default (now() at time zone 'utc'),
    width int,
    height int
);

当url是从DA中提取的图像链接时(例如:http://th05.deviantart.net/fs70/PRE/f/2014/222/2/3/sketch_dump_56_by_lilaira-d7uj8pe.png),dateadded是爬虫发现图像的日期和时间,widthheight是图像的尺寸。

目前我并不将图片本身存储在数据库中,但我会保留一个本地镜像——我获取图像的URL并使用wget -r -nc下载文件。所以对于这样的URL:http://th05.deviantart.net/fs70/PRE/f/2014/222/2/3/sketch_dump_56_by_lilaira-d7uj8pe.png,我在本地保存一份副本,路径为:<somedir>/th05.deviantart.net/fs70/PRE/f/2014/222/2/3/sketch_dump_56_by_lilaira-d7uj8pe.png

现在,在一般情况下进行图像识别是非常困难的。我希望能够处理诸如轻微调整的情况,这可以通过将所有保存的图像标准化为特定分辨率来实现,并在查询时将查询图像归一化到同一分辨率。我希望能够处理格式的更改(PNG与JPG等),这可以通过将图像文件读入标准化格式(例如:每个像素的未压缩RGB值),尽管最好有些“弹性”。

以下是额外的信息:

  • 我希望能够处理图像裁剪(例如:我之前看过imageA,有人截取并上传了imageB,我希望能够将其视为重复项)。
  • 我希望能够处理带有标志的水印图像。
  • 我希望能够处理裁剪情况,在这种情况下,要分类的新图像是以前看到的某个图像的子图像(即——我存储了imageA,有人对其进行了裁剪,我希望能够将该裁剪图像映射到imageA)。
  • 我完全不感兴趣找到不同但相似的图片(例如:同一辆红色公交车的两张不同照片应该分别报告为两张不同的图片)
  • 虽然我并不完全反对使用元数据(例如:艺术家、图像类别等),但我希望尽可能将其限制在图像数据上(EXIF数据、分辨率、RGB颜色值等)
  • 一个被缩小并出现在一个新的更大的图像中,我希望考虑它是不同的。例如:我有imageA,我将其调整到50x50大小,并且该50x50网格出现在一个新的图像中,我不会认为新图像与imageA是“相同的”(尽管按照之前列出的标准,我会认为imageA和新图像是重复的)
  • 如果能检测图像中的“次要”修订则更好(例如:图像中的伽马值发生了全面改变等)

有什么想法?建议吗?

对于我的用例,我更关心误报而不是漏报,因此“模糊匹配”的方法应该是谨慎为好。

如果有必要,我想指出我正在用Python编写所有这些内容,不过说实话,如果有其他技术能够优雅/高效地解决我的问题,我也很乐意使用。


1
为什么不从颜色直方图开始,然后再转向特征匹配呢?请参见被接受的答案:https://dev59.com/SWgu5IYBdhLWcg3wJT5I?rq=1 - dan
1个回答

0

我会在不靠近边缘的地方抓取一个小的子图像,并在数据库图像中的源位置附近进行交叉相关。您可以在交叉相关之前重新采样它以考虑小的调整大小,并且您可以选择匹配的邻域大小以考虑某个百分比的非对称裁剪。

为了避免在无特征区域(例如天空)上出现完美匹配,您可以使用局部图像变化作为子图像位置的选择标准。

这仍然会相当慢,因此需要使用全局图像度量来首先从数据库中选择候选重复项(例如danf提到的颜色直方图)。


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