Python3.0以上版本在对比图片相似中的应用
首先声明一下,代码是从网上找到的,只是本人作以简单的修改。
请大家尊重原创。
我本地用到的是
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以上版本在对比图片相似中的应用的更多相关文章
- 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. ...
- 记录一次MongoDB3.0.6版本wiredtiger与MMAPv1引擎的写入耗时对比
一.MongoDB3.0.x的版本特性(相对于MongoDB2.6及以下): 增加了wiredtiger引擎: 开源的存储引擎: 支持多核CPU.充分利用内存/芯片级别缓存(注:10月14日刚刚发布的 ...
- 【和我一起学Python吧】Python3.0与2.X版本的区别
做为一个前端开发的码农,却正在阅读最新版的<A byte of Python>.发现Python3.0在某些地方还是有些改变的.准备慢慢的体会,与老版本的<A byte of Pyt ...
- centos下安装python3.7.0以上版本时报错ModuleNotFoundError: No module named '_ctypes'
centos下安装python3.7.0以上版本时报错ModuleNotFoundError: No module named '_ctypes'的解决办法 3.7版本需要一个新的包libffi-de ...
- 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.单继 ...
- 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数据库软件,然 ...
- 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 ...
- 【转载】python3.0与2.x之间的区别
python3.0与2.x之间的区别: 1.性能 Py3.0运行pystone benchmark的速度比Py2.5慢30%.Guido认为Py3.0有极大的优化空间,在字符串和整形操作上可以取得很好 ...
- Windows8 各种版本区别对比详解
微软的 Windows8 操作系统提供了4个不同的版本,分别是 Windows RT.Windows 8 标准版.Windows 8 Pro 专业版 以及 Windows 8 Enterprise 企 ...
随机推荐
- top-N 抽样
1, 使用hive标记random:(如果是mr,就自己标记random值) use ps; set mapred.job.priority=VERY_HIGH; set mapred.job ...
- python一个简单的打包例子
最近写了一些工具,想到分享给同事时好麻烦,并且自己每次用也是需要打开pycharm这些工具,感觉很麻烦,因此想到打包,网上有些例子,照做后又摸索很久方成,索性记录一下,以备不时之需. 主要参考:htt ...
- elephant-bird学习笔记
elephant-bird是Twitter的开源项目,项目的地址为 https://github.com/twitter/elephant-bird 该项目是Twitter为LZO,thrift,pr ...
- 【QT】二进制读取图像文件测试
QDataStream in(&file); int n; in >> n ; file.close(); qDebug() << n<<"en& ...
- ux.form.field.GridDate 支持快速选择日期的日期控件
效果如图,亲测6.2.1版本可用 /** *支持快速选择日期的日期控件 */ Ext.define('ux.form.field.GridDate', { extend: 'Ext.form.fiel ...
- html5与css 1. web标准及组成
学习目标 1.本专业介绍.HTML相关概念,HTML发展历史 2.WEB标准,W3C/WHATWG/ECMA相关概念 3.相关软件的应用以及站点的创建 4.HTML基本结构和HTML语法 5.HTML ...
- 【持续集成】GIT+jenkins+sonar——GIT
一.GIT基础 1.1 git简介 linus用C语言编写 2005年诞生 分布式管理系统 速度快.适合大规模.跨地区多人协同开发 1.2 本地管理.集中式.分布式 1.3 git安装 #CentOS ...
- Spring-Boot数据库密码加密配置
springboot集成mysql/oracle时需要在yml/properties中配置数据库信息,用户名密码是肯定有的,所以就涉及到密码的加密,当然不加密也是可以的,正如某位大佬所说的,不加密就像 ...
- jQuery实现限制input框 textarea文本框输入字符数量的方法
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...
- 个人小爱好:Operating System: three easy pieces—第6章第3小节问题2#进程间的切换
问题2#:进程间的切换 直接执行的下一个问题是如何实现进程的切换.进程的切换按理说是挺简单的,对吧?不就是决定哪一个进程应该停止,哪一进程应该开始而已,才多大点事情啊?但,事实上这还真的有点棘手:尤其 ...