You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何使用OpenCV比较两张图像的相似度

图像相似度比对优化方案

现有方案的核心问题

  • 冗余磁盘IO:预处理后的图像矩阵不需要写入本地临时文件再读取,完全可以在内存中完成格式转换对接后续逻辑,省去文件读写、删除的额外开销,比对速度会有明显提升,也不会出现文件权限错误、残留文件占用磁盘的问题
  • 代码逻辑bug:
    • os.remove仅支持传入单个完整文件路径参数,现有传参方式会直接抛出类型错误
    • 参考图预处理后保存为datagray.jpg,哈希计算时读取的是datagray.jpeg,后缀不匹配会触发文件不存在错误
    • 参考图做了固定尺寸resize,待比对的采集图没有做相同尺寸对齐,会引入不必要的哈希计算误差
    • 硬编码绝对路径做文件删除,换运行环境会直接报错
  • 跨库调用冗余:需求明确优先使用OpenCV,可以直接在OpenCV生态内实现哈希计算,不需要额外依赖PIL、imagehash库

优化后实现

方案1:保留感知哈希逻辑,消除冗余IO

不需要写临时文件,OpenCV处理完的矩阵在内存中直接转PIL格式对接imagehash即可,修正后的代码如下:

import cv2
import numpy as np
from PIL import Image
import imagehash

def compareImg(imgWarpColor, threshold=5, ref_img_path="data.jpg", standard_size=(660, 880)):
    # 预处理参考图
    ref_img = cv2.imread(ref_img_path)
    ref_img = cv2.resize(ref_img, standard_size)
    ref_img_gray = cv2.cvtColor(ref_img, cv2.COLOR_BGR2GRAY)
    ref_img_blur = cv2.GaussianBlur(ref_img_gray, (3,3), 0)
    # 内存中转PIL格式,无需写临时文件
    ref_pil = Image.fromarray(cv2.cvtColor(ref_img_blur, cv2.COLOR_BGR2RGB))
    hash_ref = imagehash.average_hash(ref_pil)

    # 预处理待比对图,和参考图做完全一致的尺寸、预处理操作
    target_img = cv2.resize(imgWarpColor, standard_size)
    target_img_gray = cv2.cvtColor(target_img, cv2.COLOR_BGR2GRAY)
    target_img_blur = cv2.GaussianBlur(target_img_gray, (3,3), 0)
    target_pil = Image.fromarray(cv2.cvtColor(target_img_blur, cv2.COLOR_BGR2RGB))
    hash_target = imagehash.average_hash(target_pil)

    hash_diff = hash_ref - hash_target
    print(f"哈希差值:{hash_diff}")
    return hash_diff < threshold

方案2:纯OpenCV实现(无额外依赖)

如果要完全基于OpenCV实现,可以直接用OpenCV实现均值哈希/差值哈希算法,不需要引入其他第三方库,示例代码如下:

import cv2
import numpy as np

def aHash(img, size=(8,8)):
    # 均值哈希实现
    img_resize = cv2.resize(img, size, interpolation=cv2.INTER_CUBIC)
    img_gray = cv2.cvtColor(img_resize, cv2.COLOR_BGR2GRAY) if len(img_resize.shape)==3 else img_resize
    pixel_mean = np.mean(img_gray)
    hash_str = ''
    for i in range(size[1]):
        for j in range(size[0]):
            hash_str += '1' if img_gray[i,j] > pixel_mean else '0'
    return hash_str

def hammingDist(hash1, hash2):
    # 计算汉明距离
    return np.sum([1 for i in range(len(hash1)) if hash1[i]!=hash2[i]])

def compareImg(imgWarpColor, threshold=5, ref_img_path="data.jpg", standard_size=(660, 880)):
    # 预处理参考图
    ref_img = cv2.imread(ref_img_path)
    ref_img = cv2.resize(ref_img, standard_size)
    ref_img_gray = cv2.cvtColor(ref_img, cv2.COLOR_BGR2GRAY)
    ref_img_blur = cv2.GaussianBlur(ref_img_gray, (3,3), 0)
    hash_ref = aHash(ref_img_blur)

    # 预处理待比对图
    target_img = cv2.resize(imgWarpColor, standard_size)
    target_img_gray = cv2.cvtColor(target_img, cv2.COLOR_BGR2GRAY)
    target_img_blur = cv2.GaussianBlur(target_img_gray, (3,3), 0)
    hash_target = aHash(target_img_blur)

    hash_diff = hammingDist(hash_ref, hash_target)
    print(f"哈希差值:{hash_diff}")
    return hash_diff < threshold

调参建议

  • 相似度阈值可以根据实际场景调整:一般汉明距离小于5判定为高度相似,5~10判定为中度相似,大于10基本为不同图像
  • 如果采集的图像存在光照偏差,可以把高斯模糊核调大,或者改用感知哈希(pHash)代替平均哈希,抗干扰性更强
  • 如果图像存在旋转、裁剪偏移,不建议用哈希算法,可以改用OpenCV的ORB特征点匹配做相似度计算,鲁棒性更好

内容的提问来源于stack exchange,提问作者xkycc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:24:25