图像比较算法
computer-vision
image
image-processing
python
4
0

我正在尝试将图像相互比较,以找出它们是否不同。首先,我尝试对RGB值进行皮尔逊校正,除非图像移位很小,否则效果也很好。因此,如果a具有100%相同的图像,但其中的图像有些移动,则相关值将变差。

有什么更好的算法建议吗?

顺便说一句,我正在谈论比较千张图片...

编辑:这是我的图片(微观)的示例:

im1:

在此处输入图片说明

im2:

在此处输入图片说明

im3:

在此处输入图片说明

im1和im2相同,但有一点偏移/切割,应将im3视为完全不同...

编辑: 通过彼得·汉森(Peter Hansen)的建议解决了问题!效果很好!感谢所有答案!一些结果可以在这里找到http://labtools.ipk-gatersleben.de/image%20comparison/image%20comparision.pdf

参考资料:
Stack Overflow
收藏
评论
共 5 个回答
高赞 时间 活跃

很久以前,我已经完成了一些图像处理课程,请记住,匹配时,通常是先将图像设为灰度,然后再锐化图像的边缘,这样您才可以看到边缘。然后,您(软件)可以移动并减去图像,直到差异最小为止。

如果该差异大于您设置的阈值,则图像不相等,您可以继续下一个。然后可以分析阈值较小的图像。

我确实认为,您最多可以从根本上筛选出可能的比赛,但是需要亲自比较可能的比赛,以确定它们是否真正相等。

我很久以前不能真正显示代码,因此我在课程中使用了Khoros / Cantata。

收藏
评论

我通过图像直方图比较完成了这一任务。我的基本算法是这样的:

  1. 将图像分为红色,绿色和蓝色
  2. 为红色,绿色和蓝色通道创建归一化的直方图,并将它们连接成向量(r0...rn, g0...gn, b0...bn) ,其中n是“存储桶”的数量,256应该足够
  3. 从另一张图像的直方图中减去该直方图,然后计算距离

这是一些带有numpypil代码

r = numpy.asarray(im.convert( "RGB", (1,0,0,0, 1,0,0,0, 1,0,0,0) ))
g = numpy.asarray(im.convert( "RGB", (0,1,0,0, 0,1,0,0, 0,1,0,0) ))
b = numpy.asarray(im.convert( "RGB", (0,0,1,0, 0,0,1,0, 0,0,1,0) ))
hr, h_bins = numpy.histogram(r, bins=256, new=True, normed=True)
hg, h_bins = numpy.histogram(g, bins=256, new=True, normed=True)
hb, h_bins = numpy.histogram(b, bins=256, new=True, normed=True)
hist = numpy.array([hr, hg, hb]).ravel()

如果您有两个直方图,则可以得到如下距离:

diff = hist1 - hist2
distance = numpy.sqrt(numpy.dot(diff, diff))

如果两个图像相同,则距离为0,它们之间的差异越大,距离就越大。

对于我来说,它对于照片来说效果很好,但是在文本和徽标等图形上却失败了。

收藏
评论

您确实确实需要更好地说明问题,但是,从那5张图像来看,所有生物似乎都以相同的方式定向。如果总是这样,则可以尝试在两个图像之间进行归一化互相关 ,并将峰值作为相似度。我不知道Python中的标准化互相关函数,但是有一个类似的fftconvolve()函数,您可以自己进行循环互相关:

a = asarray(Image.open('c603225337.jpg').convert('L'))
b = asarray(Image.open('9b78f22f42.jpg').convert('L'))
f1 = rfftn(a)
f2 = rfftn(b)
g =  f1 * f2
c = irfftn(g)

由于图像大小不同,输出也没有加权或归一化,因此这将无法正常工作。

输出峰值的位置指示两个图像之间的偏移,并且峰值的大小指示相似性。应该有一种加权/归一化的方法,这样您就可以分辨出匹配良好与匹配不佳之间的区别。

这并不是我想要的答案,因为我还没有弄清楚如何规范化它,但是如果我弄清楚了它,我会对其进行更新,它将为您提供一个思路。

收藏
评论

如果您的问题与像素移位有关,也许应该将其与频率变换进行比较。

FFT应该可以( numpy具有2D矩阵的实现 ),但我一直在听到小波对此类任务更好^ _ ^

关于性能,如果所有图像都具有相同的大小,那么我记得很好,FFTW包为每个FFT输入大小创建了一个专用功能,因此您可以通过重复使用相同的代码来获得不错的性能提升。我不知道numpy是否基于FFTW,但如果不是,您可以尝试在那里进行一些研究。

在这里,您有一个原型...您可以稍微玩一下,看看哪个阈值适合您的图像。

import Image
import numpy
import sys

def main():
    img1 = Image.open(sys.argv[1])
    img2 = Image.open(sys.argv[2])

    if img1.size != img2.size or img1.getbands() != img2.getbands():
        return -1

    s = 0
    for band_index, band in enumerate(img1.getbands()):
        m1 = numpy.fft.fft2(numpy.array([p[band_index] for p in img1.getdata()]).reshape(*img1.size))
        m2 = numpy.fft.fft2(numpy.array([p[band_index] for p in img2.getdata()]).reshape(*img2.size))
        s += numpy.sum(numpy.abs(m1-m2))
    print s

if __name__ == "__main__":
    sys.exit(main())

另一种进行方法可能是模糊图像,然后从两个图像中减去像素值。如果差异不为零,则可以在每个方向上将图像之一移动1 px,然后再次进行比较;如果差异小于上一步,则可以在渐变方向上重复移动并减去,直到差异低于某个阈值或再次增加。如果模糊内核的半径大于图像的偏移,那应该可以工作。

另外,您可以尝试使用摄影工作流程中常用的一些工具来混合多个曝光或进行全景拍摄,例如Pano Tools

收藏
评论

一年前,有人问过类似的问题 ,并且得到了很多答复,其中包括一个关于图像像素化的问题,我至少建议将其作为资格预审步骤(因为它将很快排除非常相似的图像)。

那里还有指向更早的问题的链接,这些问题有更多的参考文献和很好的答案。

这是一个使用Scipy的一些想法的实现,使用上面的三个图像(分别保存为im1.jpg,im2.jpg和im3.jpg)。最终输出显示将im1与自身进行比较作为基线,然后将每个图像与其他图像进行比较。

>>> import scipy as sp
>>> from scipy.misc import imread
>>> from scipy.signal.signaltools import correlate2d as c2d
>>>
>>> def get(i):
...     # get JPG image as Scipy array, RGB (3 layer)
...     data = imread('im%s.jpg' % i)
...     # convert to grey-scale using W3C luminance calc
...     data = sp.inner(data, [299, 587, 114]) / 1000.0
...     # normalize per http://en.wikipedia.org/wiki/Cross-correlation
...     return (data - data.mean()) / data.std()
...
>>> im1 = get(1)
>>> im2 = get(2)
>>> im3 = get(3)
>>> im1.shape
(105, 401)
>>> im2.shape
(109, 373)
>>> im3.shape
(121, 457)
>>> c11 = c2d(im1, im1, mode='same')  # baseline
>>> c12 = c2d(im1, im2, mode='same')
>>> c13 = c2d(im1, im3, mode='same')
>>> c23 = c2d(im2, im3, mode='same')
>>> c11.max(), c12.max(), c13.max(), c23.max()
(42105.00000000259, 39898.103896795357, 16482.883608327804, 15873.465425120798)

因此请注意,im1与自身的得分为42105,im2与im1的得分相差不远,但是im3与其他任一个相比的得分都远低于该值的一半。您必须尝试其他图像,以查看其效果如何以及如何改进。

运行时间很长……在我的机器上几分钟。我会尝试进行一些预过滤,以避免浪费大量时间来比较非常不同的图像,也许是因为在回答另一个问题时提到了“比较jpg文件大小”的技巧,或者是像素化。您拥有不同大小的图像的事实使事情复杂化,但是您没有提供足够的信息,以了解可能发生的屠杀程度,因此很难给出一个考虑到这一点的具体答案。

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号