当前位置: 首页 > news >正文

使用OpenCV识别图片相似度评分的应用

使用OpenCV识别图片相似度评分的应用技术博客

一、架构设计

本应用采用Python语言,基于OpenCV库实现。整体架构包括以下几个模块:

  1. 图像读取与预处理模块

    • 读取输入的两张图像。
    • 将图像转换为灰度图(cv2.cvtColor())。
    • 图像尺寸标准化(cv2.resize()),确保两图大小一致。
  2. 特征提取模块

    • 使用OpenCV中的特征检测算法(如SIFT, SURF, ORB等)提取关键点和描述符。
    • 匹配两幅图像的关键点(通过BFMatcher或FLANN匹配器)。
  3. 相似度计算模块

    • 根据匹配结果,计算相似度评分。
    • 可以使用匹配点数、距离比值测试(Lowe’s Ratio Test)等方法优化匹配精度。
  4. 可视化与输出模块

    • 显示匹配的关键点(cv2.drawMatches())。
    • 输出最终的相似度评分。
  5. 用户接口模块

    • 提供命令行参数或图形界面供用户输入图像路径和选择算法。

示例代码结构:

【similarity.py】

import cv2
import numpy as np# 返回的相似度评分是通过 cv2.compareHist 方法计算两张图像在指定颜色空间(如HSV或Lab)下的直方图相关性(Correlation),
# 其值范围通常在[0, 1]之间。以下是对该评分的详细解读:
#
# ✅ 相似度评分含义
# 评分范围
# 含义说明
# 0.9 - 1.0非常相似,颜色分布高度一致,可能是同一舌头或拍摄条件相近的照片。
# 0.7 - 0.9较为相似,颜色特征接近,可能存在轻微光照、角度或拍摄设备差异。
# 0.5 - 0.7部分相似,颜色分布有一定差异,可能舌苔颜色有变化或存在轻微遮挡。
# 0.3 - 0.5不太相似,颜色特征已有明显不同,可能为不同人或舌象差异较大。
# 0.0 - 0.3极不相似,颜色分布差异显著,基本可判断为完全不同的舌头或图像内容。
#
# ⚠️
# 注意事项
# 该评分仅反映颜色分布的相似度,并不考虑形状、纹理等其他视觉特征。
# 若图像中舌头的颜色均匀但亮度差异大,建议使用HSV空间并忽略V通道,
# 或使用Lab空间以减少亮度影响。
# 若你用于医学舌诊分析,建议结合其他特征(如舌苔厚度、裂纹、齿痕等)进行综合判断。
def preprocess_tongue_image(image_path, target_size=(256, 256)):image = cv2.imread(image_path)# image = cv2.resize(image, target_size)return imagedef get_color_histogram(image, color_space='hsv', bins=64):if color_space == 'hsv':image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)# 只取 H 和 S 通道,忽略 V(亮度)hist = cv2.calcHist([image], [0, 1], None, [8, 8], [0, 180, 0, 256])elif color_space == 'lab':image = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)# 取 a 和 b 通道hist = cv2.calcHist([image], [1, 2], None, [8, 8], [0, 256, 0, 256])else:raise ValueError("Unsupported color space")cv2.normalize(hist, hist).flatten()return histdef compare_tongue_color_similarity(image1_path, image2_path, color_space='hsv'):img1 = preprocess_tongue_image(image1_path)img2 = preprocess_tongue_image(image2_path)hist1 = get_color_histogram(img1, color_space)hist2 = get_color_histogram(img2, color_space)similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)return similarity

【main.py】

from match.imgresize import extract_and_resize_car
from match.similarity import  compare_tongue_color_similarity
import os
import cv2
import numpy as npdef main():# 构建图片的相对路径或绝对路径# img1_path = '/Users/franks/项目资料/99 个人/壁纸/20231206-100802.jpeg'# img2_path = '/Users/franks/项目资料/99 个人/壁纸/20231206-100812.jpeg'## similarity_score = compare_images_sift(img1_path, img2_path)# if similarity_score is not None:#     print(f"Similarity score: {similarity_score:.2f}")# else:#     print("无法计算相似度,请检查输入图片内容。")# 示例调用# input_image = '/Users/franks/Downloads/2.jpeg'# output_image = '/Users/franks/Downloads/resized-2.png'# extract_and_resize_car(input_image,output_image)# /Users/franks/workspace/AI/ModelTrain/data/images/val/1_0.jpgimage1_path = '/Users/franks/workspace/AI/ModelTrain/data/images/val/3_0.jpg'image2_path = '/Users/franks/workspace/AI/ModelTrain/data/images/val/1_0.jpg'similarity_score = compare_tongue_color_similarity(image1_path, image2_path, color_space='hsv')print(f"舌头颜色相似度评分: {similarity_score}")if __name__ == "__main__":main()

【imgresize.py】

import numpy as np
from ultralytics import YOLO
import cv2# 计算缩放比例并保持宽高比
def resize_with_transparent_padding(image, target_size=(256, 256)):old_h, old_w = image.shape[:2]target_w, target_h = target_size# 计算缩放比例ratio = min(target_w / old_w, target_h / old_h)new_w = int(old_w * ratio)new_h = int(old_h * ratio)# 缩放图像resized_img = cv2.resize(image, (new_w, new_h), interpolation=cv2.INTER_AREA)# 转换为带透明通道的 BGRA 格式if resized_img.ndim == 2:resized_img = cv2.cvtColor(resized_img, cv2.COLOR_GRAY2BGR)  # 灰度图转 BGRresized_img = cv2.cvtColor(resized_img, cv2.COLOR_BGR2BGRA)# 创建透明画布(全透明:alpha=0)canvas = np.zeros((target_h, target_w, 4), dtype=np.uint8)# 居中放置缩放后的图像x_offset = (target_w - new_w) // 2y_offset = (target_h - new_h) // 2canvas[y_offset:y_offset+new_h, x_offset:x_offset+new_w, :3] = resized_img[:, :, :3]  # 拷贝 RGBcanvas[y_offset:y_offset+new_h, x_offset:x_offset+new_w, 3] = 255  # 设置 Alpha 为不透明return canvasdef extract_and_resize_car(image_path, output_path,output_size=(256, 256)):# 加载预训练的 YOLOv8 模型# model = YOLO('../models/yolov8s.pt')  # 自动下载模型权重(首次运行)model = YOLO('../models/yolov8_model_tongue.pt')  # 自动下载模型权重(首次运行)# 推理results = model(image_path)# 读取原始图像image = cv2.imread(image_path)for result in results:boxes = result.boxes.cpu().numpy()for box in boxes:cls_id = int(box.cls[0])if model.names[cls_id] == 'tongue':  # 只提取类别为 tongue 的对象x1, y1, x2, y2 = map(int, box.xyxy[0])  # 获取边界框坐标# 裁剪车辆区域car_crop = image[y1:y2, x1:x2]# 缩放为固定尺寸# resized_car = cv2.resize(car_crop, output_size, interpolation=cv2.INTER_AREA)resized_car = resize_with_transparent_padding(car_crop, target_size=output_size)# 保存结果cv2.imwrite(output_path, resized_car)print(f"舌头已裁剪并保存为 {output_path}")return resized_carprint("未检测到舌头。")return None

二、实现原理

1. 特征提取

OpenCV提供多种特征检测算法,其中SIFT(Scale-Invariant Feature Transform)和SURF(Speeded-Up Robust Features)是较为常用的两种方法。它们能够从图像中提取具有尺度不变性和旋转不变性的关键点及其对应的描述符,用于后续的匹配操作。

  • cv2.SIFT_create():创建SIFT对象,用于检测关键点并生成描述符。
  • detectAndCompute():返回图像的关键点(keypoints)和描述符(descriptors)。

2. 特征匹配

特征匹配主要依赖于描述符之间的欧氏距离。OpenCV提供了两种主要的匹配器:

  • Brute-Force Matcher (cv2.BFMatcher)
    • 直接比较每一对描述符的距离。
    • 设置crossCheck=True可提高匹配准确性。
  • FLANN-Based Matcher (cv2.FlannBasedMatcher)
    • 基于近似最近邻搜索,速度更快,适合大规模数据集。

3. 相似度评分

在匹配完成后,根据匹配点数量进行评分。这里采用了简单的匹配比例评分法:

score = len(good_matches) / len(matches) * 100

也可以结合Lowe’s Ratio Test来筛选更可靠的匹配点:

good_matches = []
for m, n in matches:if m.distance < 0.75 * n.distance:good_matches.append(m)

4. 可视化

利用cv2.drawMatches()函数将两幅图像的关键点匹配结果显示出来,帮助用户直观地理解图像相似性。


三、使用效果分析

1. 准确度评估

  • 对于内容相似的图像(如同一场景的不同拍摄角度、不同光照条件下的照片),该算法可以达到较高的相似度评分(>90%)。
  • 对于内容差异较大的图像(如完全不同的物体或背景),评分较低(<30%)。
  • 由于基于特征点匹配,对于图像缩放、轻微旋转等变化具有较好的鲁棒性。

2. 性能表现

  • SIFT/SURF算法在CPU上运行效率较高,但对高分辨率图像可能较慢。
  • 使用GPU加速(如OpenCV的CUDA模块)或降低图像分辨率可以提升性能。
  • 在实际部署中,建议对图像进行标准化处理(统一尺寸)以减少计算开销。

3. 局限性

  • 纹理缺失问题:若图像过于模糊或缺乏纹理细节,特征点提取会受限,导致匹配失败。
  • 光照影响:强烈光照变化可能导致描述符失真,从而影响匹配质量。
  • 视角变换敏感:若图像视角变化较大,即使为相同物体,也可能导致低评分。

四、应用场景

  1. 图像检索系统:基于特征匹配进行图像相似度排序,适用于商品识别、版权监测等。
  2. 重复图像检测:可用于社交媒体平台检测重复上传的内容。
  3. 文档扫描验证:对比扫描件与原始文件,判断是否一致。
  4. 视频帧比对:在视频摘要生成或去重任务中,比较相邻帧的相似度。

五、总结

本文介绍了基于OpenCV的图像相似度评分应用,从架构设计到具体实现进行了详细说明,并分析了其适用性及局限性。该方法适用于大多数基于局部特征匹配的图像相似度判断任务,在实际工程中可根据需求进一步优化算法(如引入深度学习模型提取更高级特征)以提升准确率和鲁棒性。

http://www.lryc.cn/news/579092.html

相关文章:

  • YOLOv11剪枝与量化(一)模型压缩的必要性
  • 深入理解C++11原子操作:从内存模型到无锁编程
  • SpringCloud系列(47)--SpringCloud Bus实现动态刷新定点通知
  • 04-动态规划
  • 数学建模_微分方程
  • 内存架构的十字路口:深入解析统一内存访问(UMA)与非一致内存访问(NUMA)
  • 虚拟机知识点-Vagrant 在通过 VirtualBox 启动 CentOS 虚拟机时失败-VERR_NEM_VM_CREATE_FAILED
  • 从0开始学习R语言--Day36--空间杜宾模型
  • maven仓库
  • WSL2 + Docker Desktop 环境中查看本地镜像
  • 【Vue入门学习笔记】Vue核心语法
  • CentOS 卸载docker
  • 移动conda虚拟环境的安装目录
  • mongo常用命令
  • odoo17 警示: selection attribute will be ignored as the field is related
  • Node.js-http模块
  • Day04:玩转标准库中的数据处理与日志记录
  • Chart.js 安装使用教程
  • 基于SpringBoot和Leaflet的区域冲突可视化系统(2025企业级实战方案)
  • VC Spyglass:工具简介
  • React Native 开发环境搭建--window--android
  • 24年京东秋季笔试题
  • CSS外边距合并(塌陷)全解析:原理、场景与解决方案
  • flutter更改第三方库pub get的缓存目录;更改.gradle文件夹存放目录
  • 告别告警风暴:深入理解 Prometheus Alertmanager 的智能告警策略
  • 为什么星敏感器(Star Tracker)需要时间同步?—— 从原理到应用的全解析
  • 1-RuoYi框架配置与启动
  • 整流电路Multisim电路仿真实验汇总——硬件工程师笔记
  • qml实现 裁剪进度条
  • 使用案例 - 根据nuscenes-devkit工具读取nuscnes数据集