• 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(' Calculating... [' + '#' * 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("{} {}".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)


    对比方法一和方法二,在执行的效率上基本一致,但是在对比的准确度上,方法二要优于方法一。

  • 相关阅读:
    golang框架对比Revel and Beego
    Gin框架系列02:路由与参数
    用cp命令拷贝文件,源目录后带不带斜杠的区别
    Isilon Gen6的换盘步骤
    如何在同一行里执行多个linux命令?
    KB,MB,GB,TB,PB,EB,ZB,YB,BB
    Isilon的WebUI上指定跨时区时间的小问题
    用Powershell强制同步Windows主机与Internet time server的时间
    Remote Desktop突然不能用了 “This could be due to CredSSP encryption oracle remediation”
    打开KVM Console的一些注意事项
  • 原文地址:https://www.cnblogs.com/wozijisun/p/6478388.html
Copyright © 2020-2023  润新知