首先声明一下,代码是从网上找到的,只是本人作以简单的修改。

请大家尊重原创。

我本地用到的是

Python 3.4   以及 Pillow (4.0.0)  第三方包。

方法一、

#!/usr/bin/python
# coding : utf-8
import glob
import os
import sys
from functools import reduce from PIL import Image # EXTS = 'jpg', 'jpeg', 'JPG', 'JPEG', 'gif', 'GIF', 'png', 'PNG'
EXTS = 'jpg', 'jpeg', 'gif', 'png' # 通过计算哈希值来得到该张图片的“指纹”
def avhash(im):
# 判断参数im,是不是Image类的一个参数
try:
if not isinstance(im, Image.Image):
im = Image.open(im)
except OSError as ose:
print("打不开图片:{}".format(im))
return "ng"
# resize,格式转换,把图片压缩成8*8大小,ANTIALIAS是抗锯齿效果开启,“L”是将其转化为
# 64级灰度,即一共有64种颜色
im = im.resize((8, 8), Image.ANTIALIAS).convert('L')
# 递归取值,这里是计算所有
# 64个像素的灰度平均值
avg = reduce(lambda x, y: x + y, im.getdata()) / 64.
print(reduce(func_reduce_param, enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())), 0))
# 比较像素的灰度,将每个像素的灰度与平均值进行比较,>=avg:1;<avg:0
return reduce(func_reduce_param,
enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())), 0) def func_reduce_param(x, a):
if type(a) == tuple:
y = a[0]
z = a[1]
return x | (z << y) # 比较指纹,等同于计算“汉明距离”(两个字符串对应位置的字符不同的个数)
def hamming(h1, h2):
if h1 == "ng" or h2 == "ng":
return "获取指纹失败。"
h, d = 0, h1 ^ h2
while d:
h += 1
d &= d - 1
return h def compare(img1, img2):
if os.path.isfile(img1):
print("源图为:{}".format(img1))
else:
print("给定的源图片:{} 不存在".format(img1))
return "img1" if os.path.isfile(img2):
print("对比图为:{}".format(img2))
else:
print("给定的对比图片:{} 不存在".format(img2))
return "img2" ham = hamming(avhash(img2), avhash(img1))
if type(ham) == int:
if ham == 0:
print("源图:{} 与对比图:{} 一样。{}".format(img1, img2, ham))
elif ham <= 3:
print("源图:{} 与对比图:{} 存在差异。{}".format(img1, img2, ham))
elif ham <= 5:
print("源图:{} 与对比图:{} 对比明显存在差异。{}".format(img1, img2, ham))
elif ham <= 8:
print("源图:{} 与对比图:{} 还能看到一点儿相似的希望。{}".format(img1, img2, ham))
elif ham <= 10:
print("源图:{} 与对比图:{} 这两张图片有相同点,但少的可怜啊。{}".format(img1, img2, ham))
elif ham > 10:
print("源图:{} 与对比图:{} 不一样。{}".format(img1, img2, ham))
else:
print("未知的结果,无法完成对比。")
return "" def compare_many_pic(img, abs_dir):
if os.path.isfile(img):
print("源图为:{}".format(img))
else:
print("给定的源图片:{} 不存在".format(img))
print("Usage: image.jpg [dir]")
return "img"
if os.path.isdir(abs_dir):
print("给定目录为:{}".format(abs_dir))
else:
print("给定的目录:{} 不存在".format(abs_dir))
print("Usage: image.jpg [dir]")
return "dir" h = avhash(img) os.chdir(abs_dir)
images = []
for ext in EXTS:
images.extend(glob.glob('*.%s' % ext))
print(images) seq = []
prog = int(len(images) > 50 and sys.stdout.isatty())
for f in images:
seq.append((f, hamming(avhash(f), h)))
if prog:
perc = 100. * prog / len(images)
x = int(2 * perc / 5)
print('\rCalculating... [' + '#' * x + ' ' * (40 - x) + ']')
print('%.2f%%' % perc, '(%d/%d)' % (prog, len(images)))
sys.stdout.flush()
prog += 1 if prog: print("")
for f, ham in sorted(seq, key=lambda i: i[1]):
print("{}\t{}".format(ham, f))
return "" if __name__ == '__main__': compare(img1="./images/1.png", img2="./images/4.png") 此方法的详细描述,已经在代码中给出,不做赘述。 方法二、
# 原作者发布在GitHub上的一些列图片对比的方法。有兴趣研究的可以访问链接如下:
# https://github.com/MashiMaroLjc/Learn-to-identify-similar-images
# coding : utf-8
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_image(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' 和 'image2' 都是Image 对象.
可以通过'Image.open(path)'进行创建。
'size' 重新将 image 对象的尺寸进行重置,默认大小为256 * 256 .
'part_size' 定义了分割图片的大小.默认大小为64*64 .
返回值是 'image1' 和 'image2'对比后的相似度,相似度越高,图片越接近,达到100.0说明图片完全相同。
'''
img1 = image1.resize(size).convert("RGB")
sub_image1 = split_image(img1, part_size) img2 = image2.resize(size).convert("RGB")
sub_image2 = split_image(img2, 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)), 6)
print(pre * 100)
return pre * 100 if __name__ == '__main__':
image1 = Image.open("./images/1.png")
image2 = Image.open("./images/brain.jpg")
classfiy_histogram_with_split(image1, image2) 对比方法一和方法二,在执行的效率上基本一致,但是在对比的准确度上,方法二要优于方法一。

Python3.0以上版本在对比图片相似中的应用的更多相关文章

  1. VMware vSphere 5.x 与 vSphere 6.0各版本功能特性对比

    各版本中的新特性及功能对比:   VMware vSphere 5.0 VMware vSphere 5.1 VMware vSphere 5.5 VMware vSphere 6.0 ESXi 5. ...

  2. 记录一次MongoDB3.0.6版本wiredtiger与MMAPv1引擎的写入耗时对比

    一.MongoDB3.0.x的版本特性(相对于MongoDB2.6及以下): 增加了wiredtiger引擎: 开源的存储引擎: 支持多核CPU.充分利用内存/芯片级别缓存(注:10月14日刚刚发布的 ...

  3. 【和我一起学Python吧】Python3.0与2.X版本的区别

    做为一个前端开发的码农,却正在阅读最新版的<A byte of Python>.发现Python3.0在某些地方还是有些改变的.准备慢慢的体会,与老版本的<A byte of Pyt ...

  4. centos下安装python3.7.0以上版本时报错ModuleNotFoundError: No module named '_ctypes'

    centos下安装python3.7.0以上版本时报错ModuleNotFoundError: No module named '_ctypes'的解决办法 3.7版本需要一个新的包libffi-de ...

  5. Python3 与 C# 面向对象之~继承与多态 Python3 与 C# 面向对象之~封装 Python3 与 NetCore 基础语法对比(Function专栏) [C#]C#时间日期操作 [C#]C#中字符串的操作 [ASP.NET]NTKO插件使用常见问题 我对C#的认知。

    Python3 与 C# 面向对象之-继承与多态   文章汇总:https://www.cnblogs.com/dotnetcrazy/p/9160514.html 目录: 2.继承 ¶ 2.1.单继 ...

  6. oracle数据库升级记(记一次10.2.0.3版本升级到11.2.0.1版本的过程)

    操作系统:windows xp 已有数据库版本:10.2.0.3 升级目标版本:11.2.0.1 步骤大纲: 在源操作系统(安装有10.2.0.3数据库的操作系统)上安装11.2.0.1数据库软件,然 ...

  7. Atitit python3.0 3.3 3.5 3.6 新特性 Python2.7新特性1Python 3_x 新特性1python3.4新特性1python3.5新特性1值得关注的新特性1Pyth

    Atitit python3.0 3.3 3.5 3.6 新特性 Python2.7新特性1 Python 3_x 新特性1 python3.4新特性1 python3.5新特性1 值得关注的新特性1 ...

  8. 【转载】python3.0与2.x之间的区别

    python3.0与2.x之间的区别: 1.性能 Py3.0运行pystone benchmark的速度比Py2.5慢30%.Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可以取得很好 ...

  9. Windows8 各种版本区别对比详解

    微软的 Windows8 操作系统提供了4个不同的版本,分别是 Windows RT.Windows 8 标准版.Windows 8 Pro 专业版 以及 Windows 8 Enterprise 企 ...

随机推荐

  1. go语言调用append之后是否重新分配内存?

    查看tidb源代码:::util/charset/charset.go,下面有段代码: // GetAllCharsets gets all charset descriptions in the l ...

  2. CRC码计算及校验原理的最通俗诠释

    5.3.2 循环冗余校验检错方案 奇偶校验码(PCC)只能校验一位错误,本节所要介绍的循环冗余校验码(CRC)的检错能力更强,可以检出多位错误. 1. CRC校验原理      CRC校验原理看起来比 ...

  3. 解决vscode无法提示golang的问题

    https://github.com/Microsoft/vscode-go/wiki/Go-with-VS-Code-FAQ-and-Troubleshooting Q: Auto-completi ...

  4. 承上 DBlink 与 SCN | 新增视图找出外部 SCN 跳变

     综述    SQL> set pages 100 lines 200 col result for a15 col OPERATION_TIMESTAMP for a35 col HOST_N ...

  5. Ubuntu 10.04下架设流媒体服务器

    Ubuntu 10.04下架设流媒体服务器 个人建议:使用DarwinStreamingSrvr5.5.5,因为DarwinStreamingSrvr6.0.3安装过程中有很多问题需要解决! 目前主流 ...

  6. PHP 正则 空字符 / NUL字符

    \xnn 匹配中ASCII代码十六进制代码为nn的字符.[\x00-\x7F] 匹配ASCII值从0-127的字符.0-127表示单字节字符,也就是:数字,英文字符,半角符号,以及某些控制字符. 正则 ...

  7. php冒泡排序详解笔记

    冒泡 /* * 冒泡排序(从小到大) * 介绍: * 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来. * 思路: * 比较相邻的元素.如果第一个比第二个大,就交换他 ...

  8. Oracle中的NULL、’’(空字符串)以及’_’(空格)

    本文首发于 http://youngzy.com/ 在Oracle中使用 null,''(空字符串),'_'(空格)时,有没有遇到问题?产生疑惑? null和’’(空字符串)是一个意思 注: 为了便于 ...

  9. shell脚本监控网站状态

    shell脚本监控网站状态 #!/bin/sh date=`date +"%Y%m%d-%H%M"` title="status" contentFail=&q ...

  10. 11.14 redis

    2018-11-14 10:07:39 购物车有思路,用django中redis来做!!!具体思路参考下面笔记 回学校后,把笔记里面面试题都认真整理一下!!!!!! 越努力,越幸运!永远不要高估自己! ...