七夜星七夜月 2023-11-15 11:00 采纳率: 0%
浏览 6
已结题

PCB线路进行模板匹配寻找缺陷

任务是需要在搜索图当中找到和模板图相似的位置,然后进行相减得到缺陷的位置(绿色区域)。但是在使用opencv的templatematch进行模板匹配时,最佳匹配值特别低而且匹配位置也不对。我数过像素了,其实搜索图和模板图的线路宽度差只有两三个像素,已经高度一致了。所以问题出在了哪里,应该怎么解决模板匹配的问题以及后续计算图像差异的方法是什么.
为了方便回答,我放入自己的代码和检测结果,但是结果很小,maxval只有0.3.应该怎么样提高这个准确率,一直对这个不满意。

img


img


img

import numpy as np
import argparse
import imutils
import glob
import cv2
import datetime

# 读取模板图片 matching4.png template_bina.jpg
template = cv2.imread("template1_bina.bmp")
# 转换为灰度图片
template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
# 执行边缘检测
template = cv2.Canny(template, 50, 200)
(tH, tW) = template.shape[:2]
# 显示模板
# cv2.imshow("Template", template)


# 读取测试图片并将其转化为灰度图片
image = cv2.imread("search4.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
found = None
highest_matching_value = (0, 0)
window_size = (1640, 1360)  # 滑动窗口的大小
step_size = 1000  # 步长
start_angle = 1.7
end_angle = 1.8
step = 0.001

scale_array = np.linspace(0.8, 1.0, 20)
scale_array = np.append((0.905, 0.91, 0.9103), scale_array)
for scale in scale_array[::-1]:
    # 根据尺度大小对输入图片进行裁剪
    resized = imutils.resize(gray, width=int(gray.shape[1] * scale))
    r =  gray.shape[1]  / float(resized.shape[1])

    # 如果裁剪之后的图片小于模板的大小直接退出
    if resized.shape[0] < tH or resized.shape[1] < tW:
        break

    for angle in np.arange(start_angle, end_angle, step):
        center = (resized.shape[1] // 2, resized.shape[0] // 2)
        rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
        rotated_image = cv2.warpAffine(resized, rotation_matrix, (resized.shape[1], resized.shape[0]))

        # 首先进行边缘检测,然后执行模板检测,接着获取最小外接矩形
        edged = cv2.Canny(rotated_image, 50, 200)
        result = cv2.matchTemplate(edged, template, cv2.TM_CCOEFF_NORMED)
        (_, maxVal, _, maxLoc) = cv2.minMaxLoc(result)

        # 如果发现一个新的关联值则进行更新
        if found is None or maxVal > found[0]:
            found = (maxVal, maxLoc, r, angle, scale)
            print(maxVal, maxLoc, scale, angle)

(maxVal, maxLoc, r, angle, scale) = found
center = (image.shape[1] // 2, image.shape[0] // 2)
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated_image = cv2.warpAffine(image, rotation_matrix, (gray.shape[1], gray.shape[0]))
# 计算测试图片中模板所在的具体位置,即左上角和右下角的坐标值,并乘上对应的裁剪因子
(startX, startY) = (int(maxLoc[0] * r) + highest_matching_value[0],
                    int(maxLoc[1] * r) + (highest_matching_value[1]))
(endX, endY) = (int((maxLoc[0] + tW) * r) + highest_matching_value[0],
                int((maxLoc[1] + tH) * r) + highest_matching_value[1])
print(maxVal, scale, angle)

c = rotated_image[startY:endY, startX:endX]
cv2.imwrite('matching4.bmp', c)
cv2.rectangle(rotated_image, (startX, startY), (endX, endY), (0, 0, 255), 2)
cv2.imwrite('matching_rect4.bmp', rotated_image)
cv2.waitKey(0)
  • 写回答

13条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2023-11-15 11:01
    关注

    引自强大而免费的微信小程序:皆我百晓生

    问题分析:

    根据问题描述,你正在使用OpenCV中的模板匹配方法进行图像缺陷的定位。但是你发现,使用templatematch方法时最佳匹配值较低且匹配位置不正确。你已经确定了要搜索图与模板图的线路宽度差只有两三个像素,并且高度一致。现在你想知道问题出在哪里,以及如何解决模板匹配问题并计算图像差异。

    解决方案:

    1. 确认模板匹配的方法:检查你使用的是OpenCV中的哪个模板匹配方法。OpenCV中有几种不同的模板匹配方法可供选择,包括平方差匹配(cv2.TM_SQDIFF),归一化平方差匹配(cv2.TM_SQDIFF_NORMED),相关匹配(cv2.TM_CCORR),归一化相关匹配(cv2.TM_CCORR_NORMED),相关系数匹配(cv2.TM_CCOEFF),归一化相关系数匹配(cv2.TM_CCOEFF_NORMED)。根据你的需求选择合适的方法。

    2. 确认模板和搜索图的大小:确保模板图和搜索图的尺寸相同。如果尺寸不同,可以使用图像缩放函数(cv2.resize)将其调整为相同大小。

    3. 使用模板匹配方法:根据确定的方法,使用OpenCV中的模板匹配函数(cv2.matchTemplate)进行匹配。确保将正确的方法参数传递给函数。

      # 使用平方差匹配方法进行模板匹配
      method = cv2.TM_SQDIFF
      result = cv2.matchTemplate(search_img, template_img, method)
      
    4. 找到最佳匹配位置:根据匹配方法的不同,结果图像中可以找到最佳匹配的位置。

      # 寻找最佳匹配位置
      min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
      top_left = min_loc if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED] else max_loc
      
    5. 计算缺陷位置:根据模板图和最佳匹配位置,可以计算出缺陷的位置。将模板图的大小与最佳匹配位置进行对齐,然后计算差异图像(绿色区域)。

      # 对齐模板图和最佳匹配位置
      template_width, template_height = template_img.shape[::-1]
      bottom_right = (top_left[0] + template_width, top_left[1] + template_height)
      
      # 绘制绿色矩形框表示缺陷位置
      cv2.rectangle(search_img, top_left, bottom_right, (0, 255, 0), 2)
      
    6. 显示结果图像:显示搜索图,并在上面绘制绿色矩形框表示缺陷位置。

      # 显示结果图像
      cv2.imshow("Result", search_img)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
      

    以上是一个基本的解决方案,你可以根据需要进行调整和优化。如果问题依然存在,可能需要考虑以下一些因素:

    • 模板图和搜索图之间的细微差异:请确认模板图和搜索图之间的差异是否足够明显,以便模板匹配算法能够正确检测到缺陷。

    • 其他图像处理方法的使用:除了模板匹配,你还可以考虑使用其他图像处理方法,如边缘检测、特征提取等,以获取更准确的结果。

    希望这个解决方案对你有帮助!如果需要更详细的代码示例,请提供相关代码,我将尽力帮助你解决问题。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月20日
  • 修改了问题 11月15日
  • 赞助了问题酬金15元 11月15日
  • 创建了问题 11月15日

悬赏问题

  • ¥15 java代码写在记事本上后在cmd上运行时无报错但又没生成文件
  • ¥15 关于#python#的问题:在跑ldsc数据整理的时候一直抱这种错误,要么--out识别不了参数,要么--merge-alleles识别不了参数(操作系统-linux)
  • ¥15 PPOCRLabel
  • ¥15 混合键合键合机对准标识
  • ¥100 现在不懂的是如何将当前的相机中的照片,作为纹理贴图,映射到扫描出的模型上
  • ¥15 魔霸ROG7 pro,win11.息屏后会显示黑屏,如图,如何解决?(关键词-重新启动)
  • ¥15 有没有人知道这是哪里出了问题啊?要怎么改呀?
  • ¥200 C++表格文件处理-悬赏
  • ¥15 Windows Server2016本地登录失败
  • ¥15 复合卡卡号轨道写入芯片卡