sno*_*ake 43 python compare image image-processing computer-vision
我试图将图像相互比较,以确定它们是否不同.首先,我尝试对RGB值进行Pearson相关,除非图像是轻微的位移,否则它的效果也相当不错.因此,如果一个100%相同的图像,但一个有点移动,我得到一个不好的相关值.
有关更好算法的任何建议吗?
顺便说一下,我正在谈论比较数千个图片......
编辑:以下是我的照片示例(微观):
IM1:

IM2:

IM3:

im1和im2是相同但有点移位/切割,im3应该被认为是完全不同的...
编辑: 问题是通过Peter Hansen的建议解决的!效果很好!感谢所有答案!一些结果可以在这里找到 http://labtools.ipk-gatersleben.de/image%20comparison/image%20comparision.pdf
Pet*_*sen 37
一年前也提出了一个类似的问题并且有很多回复,包括一个关于图像像素化的回答,我将建议至少作为资格预审步骤(因为它会很快排除非常相似的图像).
还有更早期问题的链接,这些问题有更多的参考和好的答案.
这是使用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)
Run Code Online (Sandbox Code Playgroud)
因此请注意,im1与自身相比得分为42105,im2与im1相比并不遥远,但im3与其他任何一个相比都低于该值的一半.您必须尝试其他图像,以了解这可能会有多好以及如何改进它.
运行时间很长......在我的机器上运行几分钟.我会尝试一些预过滤,以避免浪费时间比较非常不同的图像,可能与回答另一个问题时提到的"比较jpg文件大小"技巧,或与像素化.你有不同大小的图像这一事实使事情变得复杂,但你没有提供足够的信息来说明人们可能期望的屠杀程度,因此很难给出一个考虑到这一点的特定答案.
Ott*_*ger 13
我有一个用图像直方图比较完成这个.我的基本算法是这样的:
(r0...rn, g0...gn, b0...bn),其中n是"桶"的数量,256应该足够这是一些带numpy和的代码pil
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()
Run Code Online (Sandbox Code Playgroud)
如果你有两个直方图,你可以得到这样的距离:
diff = hist1 - hist2
distance = numpy.sqrt(numpy.dot(diff, diff))
Run Code Online (Sandbox Code Playgroud)
如果两个图像相同,则距离为0,它们发散的越多,距离越大.
它适用于我的照片,但在文字和徽标等图形上失败了.
如果你的问题是移位像素,也许你应该与频率变换进行比较.
FFT应该没问题(numpy有2D矩阵的实现),但我总是听说Wavelet对于这类任务更好^ _ ^
关于性能,如果所有图像都具有相同的大小,如果我记得很清楚,那么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())
Run Code Online (Sandbox Code Playgroud)
另一种继续进行的方法可能是模糊图像,然后从两个图像中减去像素值.如果差异为非零,则可以在每个方向上移动一个图像1 px并再次进行比较,如果差异低于上一步骤,则可以在渐变方向上重复移动并减去差异直到差异低于某个阈值或再次增加.如果模糊内核的半径大于图像的偏移,那应该有效.
此外,您可以尝试使用摄影工作流程中常用的一些工具来混合多个展览或制作全景图,例如Pano Tools.
你真的需要更好地指出这个问题,但是,看看这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)
Run Code Online (Sandbox Code Playgroud)
这将无法正常工作,因为图像的大小不同,输出根本没有加权或标准化.
输出峰值的位置表示两个图像之间的偏移,峰值的大小表示相似性.应该有一种方法可以对它进行加权/标准化,这样你就可以分辨出良好的匹配和糟糕的匹配.
这不是我想要的答案,因为我还没有弄清楚如何将其标准化,但是如果我弄明白的话我会更新它,它会给你一个想法.
| 归档时间: |
|
| 查看次数: |
57233 次 |
| 最近记录: |