使用Python量化两张黑白图像差异百分比的实现方法
黑白图像差异量化的Python最佳实践方案
选型思路
直方图方法确实不适用于黑白为主的图像,这类方法只统计像素值的分布比例,完全丢失了空间位置信息,很容易出现「两张布局完全不同但黑白占比一致的图被判定为相似」的误判。
针对这类场景优先采用逐像素差异统计作为核心方案,直接输出可直观理解的差异百分比,必要时可以搭配结构相似性指标作为补充,兼顾人眼感知的差异程度。
实现步骤
- 预处理:将两张图统一转为单通道灰度图、对齐分辨率,避免通道数、尺寸不一致导致的计算误差
- 逐像素对比:对两张图的像素值做差,统计超过差异阈值的像素占总像素的比例,就是需要的差异百分比
- 可选补充:计算SSIM结构相似性得分,得分区间为0-1,越接近1代表两张图视觉上越相似,适合需要感知层面差异判断的场景
可直接运行的代码示例
import cv2 import numpy as np from skimage.metrics import structural_similarity as ssim def cal_image_diff_percent(origin_img_path: str, diff_img_path: str, diff_threshold: int = 20) -> tuple[float, float]: """ 计算两张图像的差异百分比和结构相似性得分 :param origin_img_path: 原图路径 :param diff_img_path: 待对比的差异图路径 :param diff_threshold: 像素差异阈值,超过这个值才判定为有效差异,可过滤压缩噪点 :return: 差异百分比(保留2位小数)、SSIM得分(保留4位小数) """ # 读取为单通道灰度图,适配黑白为主的图像场景 img_origin = cv2.imread(origin_img_path, cv2.IMREAD_GRAYSCALE) img_diff = cv2.imread(diff_img_path, cv2.IMREAD_GRAYSCALE) # 统一两张图的分辨率 if img_origin.shape != img_diff.shape: img_diff = cv2.resize(img_diff, (img_origin.shape[1], img_origin.shape[0])) # 统计差异像素数量 pixel_diff = cv2.absdiff(img_origin, img_diff) diff_pixel_count = np.count_nonzero(pixel_diff > diff_threshold) total_pixel_count = img_origin.shape[0] * img_origin.shape[1] diff_percent = round((diff_pixel_count / total_pixel_count) * 100, 2) # 计算结构相似性得分 ssim_score = round(ssim(img_origin, img_diff), 4) return diff_percent, ssim_score if __name__ == "__main__": # 替换为你的本地图像路径即可运行 diff_pct, ssim_score = cal_image_diff_percent("origin.png", "modified.png") print(f"两张图的像素差异占比为:{diff_pct}%") print(f"两张图的结构相似性得分为:{ssim_score}")
调优建议
- 如果你的图像没有压缩、拍摄噪点,可以把
diff_threshold参数设为0,只要像素值不一样就判定为差异,结果会更精准 - 如果不需要感知层面的相似性判断,可以删掉SSIM相关的代码,依赖更少,运行速度更快
内容的提问来源于stack exchange,提问作者B-L
相关产品推荐
相关产品推荐

