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

请大家尊重原创。

我本地用到的是

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. #pragma multi_compile_fwdbase会增加很多个shader variants

    #pragma multi_compile_fwdbase是unity内置的用于前向渲染的关键字快捷方式,它包含了前向渲染光照计算需要的大多数关键字,因此会被shader带来很多的变体. 下面这个简单 ...

  2. 字符集之在UTF-8中,一个汉字为什么需要三个字节?

    (一)在UTF-8中,一个汉字为什么需要三个字节? UNICODE是万能编码,包含了所有符号的编码,它规定了所有符号在计算机底层的二进制的表示顺序.有关Unicode为什么会出现就不叙述了,Unico ...

  3. Spring中@Resource与@Autowired、@Qualifier的用法与区别

    1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上. 2.@Autowired默认按类型装配(这个注解是属业spring的),默认情况下必 ...

  4. 阿里云php-7.2.12 安装

    安装依赖 yum -y install libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml ...

  5. ML 激励函数 Activation Function (整理)

    本文为内容整理,原文请看url链接,感谢几位博主知识来源 一.什么是激励函数 激励函数一般用于神经网络的层与层之间,上一层的输出通过激励函数的转换之后输入到下一层中.神经网络模型是非线性的,如果没有使 ...

  6. 谢大神给的C++和C# DES加解密代码

    // CPPdesTest.cpp : 定义控制台应用程序的入口点.// #include "stdafx.h"//#include <windows.h>//#inc ...

  7. 二、JavaScript基础(2)

    BOM基础加强 1.浏览器对象BOM DOM Window DOM Navigator DOM Screen DOM History DOM Location 2.浏览器对象的使用 History H ...

  8. jquery 在页面上根据ID定位(jQuery锚点跳转及相关操作) 经典

    1.锚点跳转简介 Edit 锚点其实就是可以让页面定位到某个位置上的点.在高度较高的页面中经常见到.比如百度的百科页面,wiki中的page内容. 我知道实现锚点的跳转有两种形式,一种是a标签+nam ...

  9. 编写函数求整形数组a中存储的m个不重复的整数的第k大的整数(其中m>=1,1<=k<=m)很简单的一个思路是酱紫的:管他辣么多干啥,上来一把排序然后直接得答案

    /** * @author:(LiberHome) * @date:Created in 2019/2/28 20:38 * @description: * @version:$ *//*编写函数求整 ...

  10. java 中重写toString()方法

    toString()方法 一般出现在System.out.println(类名.toString()); toString()是一种自我描述方法 本身返回的是 getClass().getName() ...