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

如何在OpenCV图像对比中设置容差忽略偏移仅显示真实差异

解决方法与代码示例

1. 精准定位消除偏移根源

模板匹配默认的整数坐标定位易产生微小偏移,改用亚像素级定位可大幅提升对齐精度:

import cv2
import numpy as np

# 加载灰度图
ref_gray = cv2.imread("reference.png", cv2.IMREAD_GRAYSCALE)
sample_gray = cv2.imread("sample_scanned.png", cv2.IMREAD_GRAYSCALE)
sample_h, sample_w = sample_gray.shape

# 用归一化相关系数做匹配,抗干扰性更强
match_result = cv2.matchTemplate(ref_gray, sample_gray, cv2.TM_CCOEFF_NORMED)
_, max_val, _, max_loc = cv2.minMaxLoc(match_result)

# 亚像素修正:取峰值周围3x3区域计算梯度,微调坐标
y, x = np.unravel_index(np.argmax(match_result), match_result.shape)
patch = match_result[y-1:y+2, x-1:x+2]
dy, dx = np.gradient(patch)[0][1,1], np.gradient(patch)[1][1,1]
sub_x, sub_y = x - dx/2, y - dy/2
top_left = (int(round(sub_x)), int(round(sub_y)))

# 裁剪参考图对应区域,确保与样本图完全对齐
ref_crop = ref_gray[top_left[1]:top_left[1]+sample_h, top_left[0]:top_left[0]+sample_w]

2. 过滤偏移产生的无效差异

若仍存在细微偏移,用阈值+形态学操作过滤边缘小差异,只保留真正的打印缺失:

# 计算绝对差异图
diff = cv2.absdiff(ref_crop, sample_gray)
# 阈值过滤:只保留灰度差大于30的区域(可根据实际调整)
_, thresh_diff = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)
# 形态学闭操作:先膨胀再腐蚀,消除小噪点,保留大缺失区域
kernel = np.ones((2,2), np.uint8)
cleaned_diff = cv2.morphologyEx(thresh_diff, cv2.MORPH_CLOSE, kernel)

3. 彩色叠加只显示有效差异

用处理后的差异图做掩码,仅在缺失区域叠加红蓝对比:

# 生成红蓝彩色层
ref_blue = np.zeros((sample_h, sample_w, 3), dtype=np.uint8)
ref_blue[..., 0] = ref_crop  # BGR格式,蓝色通道用参考图灰度值
sample_red = np.zeros((sample_h, sample_w, 3), dtype=np.uint8)
sample_red[..., 2] = sample_gray  # 红色通道用样本图灰度值

# 转换掩码为BGR格式
mask_bgr = cv2.cvtColor(cleaned_diff, cv2.COLOR_GRAY2BGR) // 255

# 叠加:仅在掩码区域显示红蓝对比
overlay = cv2.bitwise_and(ref_blue, mask_bgr) + cv2.bitwise_and(sample_red, mask_bgr)
# 非差异区域设为黑色
overlay[cleaned_diff == 0] = 0

# 显示结果
cv2.imshow("Printer Quality Check", overlay)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 进阶:精准提取目标缺失元素

若已知待检测元素(如B和O右侧小点)的大小,可通过轮廓筛选直接定位:

# 提取差异图中的轮廓
contours, _ = cv2.findContours(cleaned_diff, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

final_mask = np.zeros_like(cleaned_diff)
for cnt in contours:
    area = cv2.contourArea(cnt)
    # 根据实际元素大小设置面积阈值(需自行调整)
    if 10 < area < 100:
        cv2.drawContours(final_mask, [cnt], -1, 255, -1)

# 用最终掩码生成结果
final_mask_bgr = cv2.cvtColor(final_mask, cv2.COLOR_GRAY2BGR) // 255
final_overlay = cv2.bitwise_and(ref_blue, final_mask_bgr) + cv2.bitwise_and(sample_red, final_mask_bgr)

cv2.imshow("Target Defects Only", final_overlay)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 17:57:47