python 使用cv2实现以图搜图,并输出符合相似度的图片

核心算法:
一、分别自定义三种计算图片相似度算法

1)计算图片相似度算法ORB算法

优点:

ORB 特征具有以下优点:
1、特征提取速度快;
2、在大多数情况下,去重效果能够与 SIFT/SURF 持平;
3、提取的特征直接是二元编码形式,无需使用哈希学习方法就可以直接利用汉明距离快速计算相似度。

参考【python 图像相似度】OpenCV图像相似度ORB算法--相似图像去重

https://blog.csdn.net/u013421629/article/details/87364489

2)局部敏感哈希phash算法

参考:文档的相似度(3)--局部敏感哈希算法 分析的很透彻

https://blog.csdn.net/qq_29883591/article/details/63686371 

3)传统的直方图计算相似度算法

参考:图像处理之相似图片识别(直方图应用篇)
https://blog.csdn.net/jia20003/article/details/7771651

2、定义融合相似度阈值为0.70,若三种算法计算出来的相似度最大值大于等于0.70,则取最大值为融合算法之后的相似度。
否则,则取三种算法计算出来的相似度的最小值,作为融合算法的之后的相似度。
3、定义最终相似度较高判断阈值为0.95,若融合之后的相似度值达到0.95,则认为图片非常相似。
4、图片相似的图片复制到一个文件夹下。

以下为具体实现

函数文件 image_similarity_function.py

# -*- encoding=utf-8 -*-

# 导入包
import cv2
from functools import reduce
from PIL import Image


# 计算两个图片相似度函数ORB算法
def ORB_img_similarity(img1_path,img2_path):
    """
    :param img1_path: 图片1路径
    :param img2_path: 图片2路径
    :return: 图片相似度
    """
    try:
        # 读取图片
        img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
        img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)

        # 初始化ORB检测器
        orb = cv2.ORB_create()
        kp1, des1 = orb.detectAndCompute(img1, None)
        kp2, des2 = orb.detectAndCompute(img2, None)

        # 提取并计算特征点
        bf = cv2.BFMatcher(cv2.NORM_HAMMING)
        # knn筛选结果
        matches = bf.knnMatch(des1, trainDescriptors=des2, k=2)

        # 查看最大匹配点数目
        good = [m for (m, n) in matches if m.distance < 0.75 * n.distance]
        similary = len(good) / len(matches)
        return similary

    except:
        return '0'


# 计算图片的局部哈希值--pHash
def phash(img):
    """
    :param img: 图片
    :return: 返回图片的局部hash值
    """
    img = img.resize((8, 8), Image.ANTIALIAS).convert('L')
    avg = reduce(lambda x, y: x + y, img.getdata()) / 64.
    hash_value=reduce(lambda x, y: x | (y[1] << y[0]), enumerate(map(lambda i: 0 if i < avg else 1, img.getdata())), 0)
    return hash_value


#计算两个图片相似度函数局部敏感哈希算法
def phash_img_similarity(img1_path,img2_path):
    """
    :param img1_path: 图片1路径
    :param img2_path: 图片2路径
    :return: 图片相似度
    """
    # 读取图片
    img1 = Image.open(img1_path)
    img2 = Image.open(img2_path)

    # 计算汉明距离
    distance = bin(phash(img1) ^ phash(img2)).count('1')
    similary = 1 - distance / max(len(bin(phash(img1))), len(bin(phash(img1))))
    return similary



# 直方图计算图片相似度算法
def make_regalur_image(img, size=(256, 256)):
    """我们有必要把所有的图片都统一到特别的规格,在这里我选择是的256x256的分辨率。"""
    return img.resize(size).convert('RGB')

def hist_similar(lh, rh):
    assert len(lh) == len(rh)
    return sum(1 - (0 if l == r else float(abs(l - r))/max(l, r)) for l, r in zip(lh, rh))/len(lh)

def calc_similar(li, ri):
    return sum(hist_similar(l.histogram(), r.histogram()) for l, r in zip(split_image(li), split_image(ri))) / 16.0

def calc_similar_by_path(lf, rf):
    li, ri = make_regalur_image(Image.open(lf)), make_regalur_image(Image.open(rf))
    return calc_similar(li, ri)

def split_image(img, part_size = (64, 64)):
    w, h = img.size
    pw, ph = part_size
    assert w % pw == h % ph == 0
    return [img.crop((i, j, i+pw, j+ph)).copy() for i in range(0, w, pw) \
            for j in range(0, h, ph)]
————————————————
版权声明:本文为CSDN博主「开心果汁」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013421629/article/details/87697794

实现文件:new_similarity_compare.py

# -*- encoding=utf-8 -*-

from similarity.image_similarity_function import *
import os
import shutil


# 融合相似度阈值
threshold1 = 0.70
# 最终相似度较高判断阈值
threshold2 = 0.95


# 融合函数计算图片相似度
def calc_image_similarity(img1_path,img2_path):
    """
    :param img1_path: filepath+filename
    :param img2_path: filepath+filename
    :return: 图片最终相似度
    """

    similary_ORB=float(ORB_img_similarity(img1_path,img2_path))
    similary_phash=float(phash_img_similarity(img1_path,img2_path))
    similary_hist=float(calc_similar_by_path(img1_path, img2_path))
    # 如果三种算法的相似度最大的那个大于0.7,则相似度取最大,否则,取最小。
    max_three_similarity=max(similary_ORB,similary_phash,similary_hist)
    min_three_similarity=min(similary_ORB,similary_phash,similary_hist)
    if max_three_similarity>threshold1:
        result=max_three_similarity
    else:
        result=min_three_similarity

    return round(result,3)



if __name__ == '__main__':

    # 搜索文件夹
    filepath = 'D:/test/'

    # 相似图片存放路径
    newfilepath = 'F:/same_pic_new/'

    for parent, dirnames, filenames in os.walk(filepath):
        for srcfilename in filenames:
            img1_path = filepath + srcfilename
            for parent, dirnames, filenames in os.walk(filepath):
                for filename in filenames:
                    # 全量的比对效率差,所以形成图片时在名称上做了标记,下划线后面相同的进行比对
                    name1 = srcfilename.split('_')[1]
                    # 第二张照片对应的标记
                    name2 = filename.split('_')[1]
                    img2_path = filepath + filename
                    # 取两张照片是否是同名
                    if name1 == name2 :
                        # 相同非同一张图片的则比较
                        if img1_path != img2_path:
                            kk = calc_image_similarity(img1_path, img2_path)
                            try:
                                if kk >= threshold2:
                                    # 将两张照片同时拷贝到指定目录(存在冗余操作,待优化)
                                    shutil.copy(img1_path, newfilepath)
                                    shutil.copy(img2_path, newfilepath)
                            except Exception as e:
                                # print(e)
                                pass

 

以上功能可以实现对指定文件夹下所有具有相同标记的照片进行相似度的比对,并将比对的结果输出到指定路径。

初涉图像比对还有很多不足指出,希望大神指教!

 

感谢以下博主的文章:

【python 以图搜图】三种图片相似度计算融合算法

原文链接:https://blog.csdn.net/u013421629/article/details/87697794
参考:图像处理之相似图片识别(直方图应用篇)
https://blog.csdn.net/jia20003/article/details/7771651

参考:文档的相似度(3)--局部敏感哈希算法 分析的很透彻

https://blog.csdn.net/qq_29883591/article/details/63686371 

参考【python 图像相似度】OpenCV图像相似度ORB算法--相似图像去重

https://blog.csdn.net/u013421629/article/details/87364489

 

  • 3
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以文搜,也称作以搜文,其实是一种基于像识别技术的搜索方式。通过对输入的图片进行分析、处理,然后从海的文本语料库中匹配相应的文字描述或相关信息,从而达到实现搜文的目的。而Python作为一种广受欢迎的编程语言,也提供了许多像处理和人工智能相关的开发工具和库,极大地方便了此类应用的开发。 实现以文搜的过程大体可以分为三部分:像处理、特征提取和文本匹配。在像处理模块中,可以利用Python像处理库Pillow或OpenCV等进行像的预处理操作。例如,可以将像进行resize、变形、裁剪等操作,以及进行各种像特效加工,以避免图片失真或者不符合搜索标准。在特征提取模块,可以利用深度学习中的卷积神经网络提取图片特征,或者使用传统像处理特征,如SIFT和SURF等,提取具有代表性的特征点。最后,在文本匹配模块中,可以通过Python的自然语言处理工具(如NLTK、TexSoup等)对像特征提取的结果进行处理,将其与海的语料库中的文字描述进行比较,从而找出最相符的文本结果,即实现以文搜功能。 总之,Python是一种优秀的编程语言,可以方便地实现像处理、深度学习、自然语言处理等众多功能模块,这些工具和库的支持使得以文搜实现变得更加简便和高效。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值