千家信息网

Python+Opencv怎么实现图像匹配功能

发表于:2025-01-19 作者:千家信息网编辑
千家信息网最后更新 2025年01月19日,这篇文章给大家介绍Python+Opencv怎么实现图像匹配功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1、原理简单来说,模板匹配就是拿一个模板(图片)在目标图片上依次滑动
千家信息网最后更新 2025年01月19日Python+Opencv怎么实现图像匹配功能

这篇文章给大家介绍Python+Opencv怎么实现图像匹配功能,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

1、原理

简单来说,模板匹配就是拿一个模板(图片)在目标图片上依次滑动,每次计算模板与模板下方的子图的相似度,最后就计算出了非常多的相似度;
如果只是单个目标的匹配,那只需要取相似度最大值所在的位置就可以得出匹配位置;
如果要匹配多个目标,那就设定一个阈值,就是说,只要相似度大于比如0.8,就认为是要匹配的目标。

1.1 相似度度量指标

  • 差值平方和匹配 CV_TM_SQDIFF

  • 标准化差值平方和匹配 CV_TM_SQDIFF_NORMED

  • 相关匹配 CV_TM_CCORR

  • 标准相关匹配 CV_TM_CCORR_NORMED

  • 相关匹配 CV_TM_CCOEFF

  • 标准相关匹配 CV_TM_CCOEFF_NORMED

1.2 计算步骤

有一张模板图像Templa和一张较大的待搜索图像Image,模板匹配是一种用于在较大图像中搜索和查找模板图像位置的方法。
具体就是将模板图像滑动到输入图像上(就像在卷积操作一样),然后在模板图像下比较模板和输入图像的子图的相似度。
它返回一个灰度图像,其中每个像素表示该像素的邻域与模板匹配的相似度。如果输入图像的大小(WxH)和模板图像的大小(wxh),则输出图像的大小将为(W-w+ 1,H-h + 1)。 获得相似度图像之后,在其上查找最大相似度所在的像素。将其作为匹配区域矩形的左上角,并以(w,h)作为矩形的宽度和高度。该矩形是与模板匹配的区域。

2、代码实现

2.1 单模板匹配单个目标

代码如下:

# 相关系数匹配方法: cv2.TM_CCOEFFres = cv2.matchTemplate(img, template, cv2.TM_CCOEFF)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)left_top = max_loc   # 左上角right_bottom = (left_top[0] + w, left_top[1] + h)   # 右下角cv2.rectangle(img, left_top, right_bottom, 255, 2)  # 画出矩形位置plt.subplot(121), plt.imshow(res, cmap='gray')plt.title('Matching Result'), plt.xticks([]), plt.yticks([])plt.subplot(122), plt.imshow(img, cmap='gray')plt.title('Detected Point'), plt.xticks([]), plt.yticks([])plt.show()

2.2 单模板匹配多个目标

目标照片:mario.jpg


模板照片:mario_coin.jpg


代码如下:

import cv2import numpy as npimg_rgb = cv2.imread('mario.jpg')img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)template = cv2.imread('mario_coin.jpg', 0)h, w = template.shape[:2] res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)threshold = 0.8# 取匹配程度大于%80的坐标loc = np.where(res >= threshold)#np.where返回的坐标值(x,y)是(h,w),注意h,w的顺序for pt in zip(*loc[::-1]):      bottom_right = (pt[0] + w, pt[1] + h)    cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)cv2.imwrite("img.jpg",img_rgb)cv2.imshow('img', img_rgb)cv2.waitKey(0)

检测结果如下:


3、算法精度优化

  • 多尺度模板匹配

  • 旋转目标模板匹配

  • 非极大值抑制

通过上图可以看到对同一个图有多个框标定,需要去重,只需要保留一个

解决方案:对于使用同一个待检区域使用NMS(非极大值抑制)进行去掉重复的矩形框

NMS 原理

对于Bounding Box的列表B及其对应的置信度S,采用下面的计算方式。选择具有最大score的检测框M,将其从B集合中移除并加入到最终的检测结果D中。通常将B中剩余检测框中与M的IoU大于阈值Nt的框从B中移除,重复这个过程,直到B为空。

ps. 重叠率(重叠区域面积比例IOU)常用的阈值是 0.3 ~ 0.5.

代码如下:

import cv2import timeimport numpy as np def py_nms(dets, thresh):    """Pure Python NMS baseline."""    #x1、y1、x2、y2、以及score赋值    # (x1、y1)(x2、y2)为box的左上和右下角标    x1 = dets[:, 0]    y1 = dets[:, 1]    x2 = dets[:, 2]    y2 = dets[:, 3]    scores = dets[:, 4]    #每一个候选框的面积    areas = (x2 - x1 + 1) * (y2 - y1 + 1)    #order是按照score降序排序的    order = scores.argsort()[::-1]    # print("order:",order)     keep = []    while order.size > 0:        i = order[0]        keep.append(i)        #计算当前概率最大矩形框与其他矩形框的相交框的坐标,会用到numpy的broadcast机制,得到的是向量        xx1 = np.maximum(x1[i], x1[order[1:]])        yy1 = np.maximum(y1[i], y1[order[1:]])        xx2 = np.minimum(x2[i], x2[order[1:]])        yy2 = np.minimum(y2[i], y2[order[1:]])        #计算相交框的面积,注意矩形框不相交时w或h算出来会是负数,用0代替        w = np.maximum(0.0, xx2 - xx1 + 1)        h = np.maximum(0.0, yy2 - yy1 + 1)        inter = w * h        #计算重叠度IOU:重叠面积/(面积1+面积2-重叠面积)        ovr = inter / (areas[i] + areas[order[1:]] - inter)        #找到重叠度不高于阈值的矩形框索引        inds = np.where(ovr <= thresh)[0]        # print("inds:",inds)        #将order序列更新,由于前面得到的矩形框索引要比矩形框在原order序列中的索引小1,所以要把这个1加回来        order = order[inds + 1]    return keep def template(img_gray,template_img,template_threshold):    '''    img_gray:待检测的灰度图片格式    template_img:模板小图,也是灰度化了    template_threshold:模板匹配的置信度    '''     h, w = template_img.shape[:2]    res = cv2.matchTemplate(img_gray, template_img, cv2.TM_CCOEFF_NORMED)    start_time = time.time()    loc = np.where(res >= template_threshold)#大于模板阈值的目标坐标    score = res[res >= template_threshold]#大于模板阈值的目标置信度    #将模板数据坐标进行处理成左上角、右下角的格式    xmin = np.array(loc[1])    ymin = np.array(loc[0])    xmax = xmin+w    ymax = ymin+h    xmin = xmin.reshape(-1,1)#变成n行1列维度    xmax = xmax.reshape(-1,1)#变成n行1列维度    ymax = ymax.reshape(-1,1)#变成n行1列维度    ymin = ymin.reshape(-1,1)#变成n行1列维度    score = score.reshape(-1,1)#变成n行1列维度    data_hlist = []    data_hlist.append(xmin)    data_hlist.append(ymin)    data_hlist.append(xmax)    data_hlist.append(ymax)    data_hlist.append(score)    data_hstack = np.hstack(data_hlist)#将xmin、ymin、xmax、yamx、scores按照列进行拼接    thresh = 0.3#NMS里面的IOU交互比阈值     keep_dets = py_nms(data_hstack, thresh)    print("nms time:",time.time() - start_time)#打印数据处理到nms运行时间    dets = data_hstack[keep_dets]#最终的nms获得的矩形框    return detsif __name__ == "__main__":    img_rgb = cv2.imread('mario.jpg')#需要检测的图片    img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)#转化成灰色    template_img = cv2.imread('mario_coin.jpg', 0)#模板小图    template_threshold = 0.8#模板置信度    dets = template(img_gray,template_img,template_threshold)    count = 0    for coord in dets:        cv2.rectangle(img_rgb, (int(coord[0]),int(coord[1])), (int(coord[2]),int(coord[3])), (0, 0, 255), 2)    cv2.imwrite("result.jpg",img_rgb)

关于Python+Opencv怎么实现图像匹配功能就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

模板 图像 目标 矩形 相似 阈值 面积 维度 检测 最大 代码 位置 区域 坐标 像素 图片 多个 就是 左上角 标准 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 海南大学网络安全大赛 浅谈qq微信网络安全心得体会 浙江混合现实设计软件开发 软件开发测试与集成的实验 网络技术系学生会生活部 信息网络安全专业的就业方向 计算机网络技术论文致谢 服务器内存条能用在台式电脑上吗 厦门软件开发薪资 用户登录数据库表主要字段 睢宁同城百事通网络技术 电子科技大学网络安全考研难吗 计算机网络技术职业优势 界面用什么软件开发 服务器账号和密码怎么修改 停车场服务器设置 关于东京奥运会的数据库 英雄联盟服务器代表什么 数据库获得焦点应该怎样设置 江苏服务器维修调试哪家便宜 宏观经济数据库爬虫技术 北京华品博睿网络技术 软件开发所要缴纳的税 dell服务器t440拆机 中国量子数据库外媒 腾讯服务器的数据能查吗 物理服务器需要多少钱 停车场服务器设置 常熟网络技术专业服务 公安大学网络安全考研科目
0