3. 基于模板匹配的焊缝类型识别

任务目标

构建一个最小可用的焊缝模板匹配识别系统:预先为I型、V型、U型三种焊缝各建立模板图像,输入待识别焊缝图像后,通过归一化相关系数匹配(NCC)判定焊缝类型,并输出匹配得分与识别结果。

环境与依赖

  • Python 3.8+
  • OpenCV(opencv-python)
  • NumPy

实现要点

本案例使用灰度图像与归一化相关系数匹配(cv2.matchTemplate + TM_CCOEFF_NORMED)。该方法对光照变化不敏感,适合焊缝图像在固定工位下的识别场景。模板库以字典形式存储,键为焊缝类型名称,值为对应的模板图像路径。识别时依次与每个模板匹配,取最高得分对应的类型作为输出。

关键完整代码

import cv2
import numpy as np
from pathlib import Path

# ========== 模板库构建 ==========
# 模板图像目录结构:
#   templates/
#     I_type.png
#     V_type.png
#     U_type.png
TEMPLATE_DIR = Path("templates")

def build_template_library(template_dir: Path) -> dict:
    """加载模板目录下所有焊缝模板图像"""
    library = {}
    for img_path in template_dir.glob("*.png"):
        img = cv2.imread(str(img_path), cv2.IMREAD_GRAYSCALE)
        if img is None:
            raise ValueError(f"无法加载模板图像: {img_path}")
        library[img_path.stem] = img
    return library

# ========== 焊缝类型识别 ==========
def classify_weld(image: np.ndarray, template_lib: dict) -> tuple:
    """
    对输入图像进行模板匹配,返回 (焊缝类型, 最高得分)
    image: 待识别灰度图像(尺寸需大于等于模板尺寸)
    """
    best_type = None
    best_score = -1.0

    for weld_type, template in template_lib.items():
        # 输入图像尺寸必须不小于模板尺寸
        if image.shape[0] < template.shape[0] or image.shape[1] < template.shape[1]:
            continue

        result = cv2.matchTemplate(image, template, cv2.TM_CCOEFF_NORMED)
        _, max_val, _, _ = cv2.minMaxLoc(result)

        if max_val > best_score:
            best_score = max_val
            best_type = weld_type

    return best_type, best_score

# ========== 最小调用入口 ==========
if __name__ == "__main__":
    # 1. 构建模板库
    templates = build_template_library(TEMPLATE_DIR)

    # 2. 加载待识别图像(示例:V型焊缝)
    test_img = cv2.imread("test_weld.png", cv2.IMREAD_GRAYSCALE)
    if test_img is None:
        raise FileNotFoundError("未找到测试图像 test_weld.png")

    # 3. 执行识别
    weld_type, score = classify_weld(test_img, templates)

    # 4. 输出结果
    print(f"识别焊缝类型: {weld_type}")
    print(f"匹配得分: {score:.4f}")

    # 5. 判定阈值(可根据实际场景调整)
    threshold = 0.75
    if score >= threshold:
        print(f"判定结果: 可靠识别为 {weld_type}")
    else:
        print("判定结果: 匹配度不足,请检查输入图像或补充模板")

运行与验证

  1. 准备模板图像:创建 templates/ 目录,放入三张焊缝截面灰度图,分别命名为 I_type.png、V_type.png、U_type.png。模板应只包含焊缝区域,背景尽量简洁。
  2. 准备测试图像:在程序同级目录放置 test_weld.png,内容为某一种焊缝的截面图。
  3. 执行程序:python weld_classifier.py
  4. 通过条件:程序输出的焊缝类型与测试图像实际类型一致,且匹配得分 ≥ 0.75。若得分低于阈值,程序会提示匹配度不足,此时应检查模板与测试图像的拍摄角度、尺度是否一致。

常见问题

  • 模板与测试图像尺度不一致:模板匹配要求测试图像尺寸 ≥ 模板尺寸。若实际场景中焊缝大小变化明显,需先对图像做尺度归一化(如统一缩放到固定宽度)。
  • 得分普遍偏低:检查模板是否包含过多背景噪声,建议裁剪模板时只保留焊缝坡口区域。
  • 误识别:当I型与U型外观接近时,可增加模板数量(如不同焊接参数下的子模板),或提高判定阈值。
模板匹配焊缝识别流程 模板库 I型 / V型 / U型 待识别图像 灰度图 NCC匹配 逐像素计算 相关系数 取每个模板的 最大响应值 类型判定 比较各模板得分 取最高分对应类型 得分 ≥ 阈值? 是 → 输出类型 否 → 提示匹配不足

上述流程图中,模板库与待识别图像并行进入NCC匹配模块,对每个模板计算归一化相关系数并取最大值,最终比较各模板得分并依据阈值输出判定结果。该流程与代码实现一一对应,可直接用于理解算法逻辑与调试。