Python3.0以上版本在对比图片相似中的应用
2017-02-28 12:47
831 查看
首先声明一下,代码是从网上找到的,只是本人作以简单的修改。
请大家尊重原创。
我本地用到的是
Python 3.4 以及 Pillow (4.0.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[/code]# 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以上版本在对比图片相似中的应用
- python 3.0以上的版本注意
- 自己实现的一个python版本的多线程 ftp扫描器,python版本3.0以上
- Python3.0以上版本安装pip和MySQLdb
- Android 使用OKhttp 3.0以上版本上传文件或图片(MultipartBuilder已不可用)
- mac电脑安装 python3.0以上版本
- ubuntu环境下 python 3.0以上版本对sqlite3的支持问题
- shape 画圆角图片,圆角位置在3.0版本以下和3.0以上取值相反的解决办法
- centos下,将python升级3.0+以上版本后,yum、update等无法使用问题
- 使用FastReport 3.0及以上版本创建动态报表的几个技巧(转)
- WSS 3.0与Form Server 2007、MOSS 2007各版本功能对比(8)
- WSS 3.0与Form Server 2007、MOSS 2007各版本功能对比(5)
- WSS 3.0与Form Server 2007、MOSS 2007各版本功能对比(10)
- WSS 3.0与Form Server 2007、MOSS 2007各版本功能对比(9)
- Python3.0和以前版本的区别
- SQL2005以上版本数据库级触发器的应用
- WSS 3.0与Form Server 2007、MOSS 2007各版本功能对比(3)
- WSS 3.0与Form Server 2007、MOSS 2007各版本功能对比(2)
- WSS 3.0与Form Server 2007、MOSS 2007各版本功能对比(12)
- [转载]使用FastReport 3.0及以上版本创建动态报表的几个技巧