转自:https://testerhome.com/topics/4539
在2年前我发过一个帖子,就是说图片相似度的。总体来讲,最近工作上绕了一圈又回到了这里。所以就开个帖子再来说下,让更多的同学能够去使用。
在图片处理上其实还是需要用到一个库,前两天社区还有朋友说到——PILLOW。聊下PILLOW吧,前身是PIL,PIL可以非常简单的将一个图 片直接转换成像素点的一个集合。就比如Python中提供简单的API可以直接将一张300*200的图转换成由300*200个RGBA数据组成的 tuple。我们拿到像素点之后想怎么比较就是可以自定义以及算法的事儿了。
这里直接切入主题就来说方法了,也推荐大家一个github库参考。
直方图的话是将图片转换成一个队列,通过这个队列的相似度来判断图片的相似度的。但是直方图本身优点缺点都很明显。优点的话就是对比的结果很直观,而且天
生支持模糊对比。但是缺点就是直方图其实不够智能,因为大多都是像素点上的颜色分布来做对比的,却没有任何算法和模型上的支持,导致精准度其实不高(但其
实也是比较特殊的情况下才可能被误导)
比如下面的两张图:
我们调用如下的代码能够直观的看到两张图的直方图的对比的结果:
import matplotlib.pyplot as plt
from pylab import *
from PIL
import Image
import math
import operator
image1 = Image.open('1.JPG')
image2 = Image.open('2.JPG')
plot(image1.histogram(),linewidth=2)
plot(image2.histogram(),linewidth=2)
show()
结果就很直观了。
我们还是说下缺点,这个图你们也看到了,几乎可以说是差不多了,所以直方图的结果曲线吻合度还是很高的。但是同样的,这张图是蓝色和绿色偏多,如果说是一个穿着天蓝色内裤,绿色大衣的姑娘的图片,也许直方图出来的结果差不多。so,你们明白啥意思了吧
直方图方法一:
这个也是我最常用的,Google出来的方法:
#sudo pip install PIL
def pil_image_similarity(filepath1, filepath2):
from PIL import Image
import math
import operator
image1 = Image.open(filepath1)
image2 = Image.open(filepath2)
# image1 = get_thumbnail(img1)
# image2 = get_thumbnail(img2)
h1 = image1.histogram()
h2 = image2.histogram()
rms = math.sqrt(reduce(operator.add, list(map(lambda a,b: (a-b)**2, h1, h2)))/len(h1) )
return rms
直方图方法二:
fromPIL
import
Image
defclassfiy_histogram(image1,image2,size
=
(256,256)):
image1
=
image1.resize(size).convert("RGB")
g
=
image1.histogram()
image2=
image2.resize(size).convert("RGB")
s
=
image2.histogram()
assertlen(g)
==
len(s),"error"
data=
[]
for
index
in
range(0,len(g)):
if
g[index]
!=
s[index]:
data.append(1-
abs(g[index]
-
s[index])/max(g[index],s[index])
)
else:
data.append(1)
return
sum(data)/len(g)
直方图方法三:
from
PIL
import
Image
def
calculate(image1,image2):
g
=
image1.histogram()
s
=
image2.histogram()
assert
len(g)
==
len(s),"error"
data
=
[]
for
index
in
range(0,len(g)):
if
g[index]
!=
s[index]:
data.append(1
-
abs(g[index]
-
s[index])/max(g[index],s[index])
)
else:
data.append(1)
return
sum(data)/len(g)
def
split_imgae(image,part_size):
pw,ph
=
part_size
w,h
=
image.size
sub_image_list
=
[]
assert
w
%
pw
==
h
%
ph
==
0,"error"
for
i
in
range(0,w,pw):
for
j
in
range(0,h,ph):
sub_image
=
image.crop((i,j,i+pw,j+ph)).copy()
sub_image_list.append(sub_image)
return
sub_image_list
def
classfiy_histogram_with_split(image1,image2,size
=
(256,256),part_size=(64,64)):
image1
=
image1.resize(size).convert("RGB")
sub_image1
=
split_imgae(image1,part_size)
image2
=
image2.resize(size).convert("RGB")
sub_image2
=
split_imgae(image2,part_size)
sub_data
=
0;
for
im1,im2
in
zip(sub_image1,sub_image2):
sub_data
+=
calculate(im1,
im2)
x
=
size[0]/part_size[0]
y
=
size[1]/part_size[1]
pre
=
round((sub_data/(x*y)
),3
)
return
pre
__all__
=
[classfiy_histogram_with_split]
更多的方法可见:https://github.com/monkeytest15/Learn-to-identify-similar-images。这个也是前几天找到的,感谢作者