小试“以图搜图”

news/2024/11/16 20:55:42/

毕业设计做的User-based Recommend System,其中涉及到了“余弦相似度”这个概念。

阮一峰大牛的博客介绍了以图搜图的原理(这里就不赘言),并给除了Python实现的代码 ,这个程序对于我来说,有的地方感觉稍显复杂,搜图的效果也不那么棒,于是我重写了下。


改进的地方有两点:

1.图片哈希:

原来的代码是这样的:

reduce(lambda x, (y, z): x | (z << y),enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())),0)

我直接用python的map+lambda给简化成求64个像素点的像素值,然后又平均像素值比较,转化成0、1组成的向量:

avg = reduce(lambda x, y: x + y, im.getdata()) / 64
return map(lambda x: 0 if x>avg else 1, im.getdata())


打印看下效果:

[1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

2.比较相似度的方法:


原来的代码用hamming距离求:

def hamming(h1, h2):h, d = 0, h1 ^ h2while d:h += 1d &= d - 1return h

我用余弦距离求:

def cos_dist(a, b):if len(a) != len(b):return Nonepart_up = 0.0a_sq = 0.0b_sq = 0.0for x, y in zip(a,b):part_up += x*ya_sq += x**2b_sq += y**2part_down = math.sqrt(a_sq*b_sq)if part_down == 0.0:return Noneelse:return part_up / part_down

最后,写出的代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import math
import glob
from PIL import Image
EXTS = ['png']
master = Image.open('image.png')
master = master.resize((8, 8), Image.ANTIALIAS).convert('L')
avg = reduce(lambda x, y: x + y, master.getdata()) / 64
master_data = map(lambda x: 0 if x>avg else 1, master.getdata())
#print master_data
def cos_dist(a, b):
if len(a) != len(b):
return None
part_up = 0.0
a_sq = 0.0
b_sq = 0.0
for x, y in zip(a,b):
part_up += x*y
a_sq += x**2
b_sq += y**2
part_down = math.sqrt(a_sq*b_sq)
if part_down == 0.0:
return None
else:
return part_up / part_down
images = []
for ext in EXTS:
#fill in images list
images.extend(glob.glob('*.%s' % ext))
#print repr(images)
dists = []
for f in images:
if f == "image.png":
continue
im = Image.open(f)
im = im.resize((8, 8), Image.ANTIALIAS).convert('L')
avg = reduce(lambda x, y: x + y, im.getdata()) / 64
#这里还有问题,得出的像素是反的,所以我把">"号变成了"<"号
im_data = map(lambda x: 0 if x<avg else 1, im.getdata())
dist = cos_dist(master_data, im_data)
print "image: %s\t avg: %f\t dist:%s\t" % (f, avg, dist)
print im_data
dists.append((f, dist))
for f, dist in sorted(dists, key=lambda i: i[1]):
print "%f\t%s" % (dist, f)        

我有这样几张图片:


1. 基准图片 image.png:




下面这几张图片就是要测试的图片,与基准图片的相似度 image1 > image2 > image3 > image4 > image5


2.image1.png


3.image2.png



4.image3.png


5.image4.png


6.image5.png:



运行结果如下:

image: image1.png	 avg: 215.000000	 dist:0.970142500145	
[1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
image: image2.png	 avg: 210.000000	 dist:0.857250857251	
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
image: image3.png	 avg: 168.000000	 dist:0.735980072194	
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
image: image4.png	 avg: 108.000000	 dist:0.714434508312	
[1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1]
image: image5.png	 avg: 76.000000	 dist:0.25	
[0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
0.250000	image5.png
0.714435	image4.png
0.735980	image3.png
0.857251	image2.png
0.970143	image1.png

可见,计算出的余弦相似度 image1 > image2 > image3 > image4 > image5

这与我们看到的是一样的,最后,我们搜索出的最相似的图片就是image1喽~

--------------

代码放在了github上。



http://www.ppmy.cn/news/181884.html

相关文章

图片搜索引擎大合集

转自&#xff1a;bbs.service.alibaba.com/bbs/read.php?tid2768 相似图片搜索网站(以图搜图) 如何凭着一张现有图片找出它的原始图片&#xff0c;或者是凭着一张小的缩略图找出原始大图&#xff1f;下面的搜索引擎可以帮你实现、以图找图、以图搜图。 以图搜图是颠覆性的搜…

图片搜索引擎网站大全,以图搜图网站

当我们需要搜索一些图片的时候使用图片搜索引擎网站可以帮我们更快地找到自己需要的图片&#xff0c;那么有哪些图片搜索引擎网站可以搜索图片呢&#xff1f;下面小编就来和大家分享几个以图搜图的网站。 1.百度图片搜索引擎网站 百度是最大的中文搜索引擎&#xff0c;百度的图…

比Everything更强的文件搜索工具,支持文件名、文件内容和文件图片上的文字搜索,文件内容搜索工具,文件图片内容搜索工具,OCR图片文本识别搜索,文件快速搜索工具,文字识别文件搜索工具

Windows自带的文件搜索功能想必不需要过多吐槽&#xff0c;搜索速度简直是在龟爬&#xff0c;所以小编很早之前就在用Everything进行文件搜索了&#xff0c;不过&#xff0c;今天的主角不是它&#xff0c;而是比它更更更更更强的一款软件&#xff01; 这款软件适用于以下情景&…

联想收购IBM 部分PC业务是联想最大的失败!

联想收购了IBM,他还能走多远...偶的看法&#xff0c;呵呵 联想...在国内卖PC还凑合&#xff0c;真把IBM的PC业务给买过来了&#xff0c;真强&#xff0c;不过感觉联想还真没这个本事把IBM的PC业务给整合起来。 1&#xff09;人终究要流失的。如果你在IBM搞开发&#xff0c;现在…

联想为什么不卖X系列服务器,IBM欲向联想出售x86服务器业务,涉及System x产品线...

拼 命 加 载 中 ... 现在距离当年IBM把PC部门出售给联想已经接近十年了&#xff0c;有新的消息指最近IBM又在考虑向联想出售x86服务器业务&#xff0c;而价格在50亿至60亿美元之间。 这次收购可能会涉及到IBM的System x系列产品线&#xff0c;包括基于英特尔和AMD的塔式服务器、…

联想将于10月1日收购IBM服务器业务

联想和IBM正在进行封闭式交易&#xff0c;预计联想将收购IBM x86服务器业务&#xff0c;将于10月1日在主流市场开始过渡。 这一消息当初在一月份公布的时候就闹的不可开交&#xff0c;以至于引起了美国政府的外国投资部门的关注&#xff0c;他们不得不考虑该收购会不会有潜在的…

联想服务器销售额,联想宣布将完成对 IBM x86 服务器业务的收购,交易额为 21 亿美元...

联想集团董事长杨元庆今日宣布联想对 IBM x86 服务器业务的收购预期于 10 月 1 日完成。收购完成后联想将成为全球第三大 x86 服务器厂商&#xff0c;并将显著加强自身企业服务实力。 这次联想由 IBM 处收购的部分包括 System x、BladeCenter、Flex 系统刀片服务器/交换机、x86…

联想收购IBM谁赚了?

不经意间看到联想的经营状况&#xff0c;发现所有指标都在节节攀升&#xff0c;然后想起04年刚收购IBM时&#xff0c;业界一片哗然&#xff0c;有些人持乐观态度&#xff0c;认为联想可以走向国际市场了&#xff0c;不会走向清华同方北大方正的道路&#xff0c;也有些人认为联想…