当前位置:   article > 正文

opencv模板匹配相同位置去除重复的框_opencv 去除重叠连通区域

opencv 去除重叠连通区域

使用opencv自带的模板匹配

1、目标匹配函数:cv2.matchTemplate()
res=cv2.matchTemplate(image, templ, method, result=None, mask=None)
image:待搜索图像
templ:模板图像
result:匹配结果
method:计算匹配程度的方法,主要有以下几种:
CV_TM_SQDIFF    平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
CV_TM_CCORR    相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
CV_TM_CCOEFF    相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
CV_TM_SQDIFF_NORMED    计算归一化平方差,计算出来的值越接近0,越相关
CV_TM_CCORR_NORMED    计算归一化相关性,计算出来的值越接近1,越相关
CV_TM_CCOEFF_NORMED    计算归一化相关系数,计算出来的值越接近1,越相关

待检测的图片如下,需要检测里面金币的位置

需要检测金币的模板如下:

2、基本的多对象模板匹配效果代码如下:

  1. import cv2
  2. import numpy as np
  3. img_rgb = cv2.imread('mario.jpg')
  4. img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
  5. template = cv2.imread('mario_coin.jpg', 0)
  6. h, w = template.shape[:2]
  7. res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
  8. threshold = 0.8
  9. # 取匹配程度大于%80的坐标
  10. loc = np.where(res >= threshold)
  11. #np.where返回的坐标值(x,y)是(h,w),注意h,w的顺序
  12. for pt in zip(*loc[::-1]):
  13. bottom_right = (pt[0] + w, pt[1] + h)
  14. cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
  15. cv2.imwrite("001.jpg",img_rgb)
  16. cv2.imshow('img_rgb', img_rgb)
  17. cv2.waitKey(0)

检测效果如下:

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

解决方案:对于使用同一个待检区域使用NMS进行去掉重复的矩形框

3、使用NMS对模板匹配出来的矩形框进行去掉临近重复的,代码如下:

  1. import cv2
  2. import time
  3. import numpy as np
  4. def py_nms(dets, thresh):
  5. """Pure Python NMS baseline."""
  6. #x1、y1、x2、y2、以及score赋值
  7. # (x1、y1)(x2、y2)为box的左上和右下角标
  8. x1 = dets[:, 0]
  9. y1 = dets[:, 1]
  10. x2 = dets[:, 2]
  11. y2 = dets[:, 3]
  12. scores = dets[:, 4]
  13. #每一个候选框的面积
  14. areas = (x2 - x1 + 1) * (y2 - y1 + 1)
  15. #order是按照score降序排序的
  16. order = scores.argsort()[::-1]
  17. # print("order:",order)
  18. keep = []
  19. while order.size > 0:
  20. i = order[0]
  21. keep.append(i)
  22. #计算当前概率最大矩形框与其他矩形框的相交框的坐标,会用到numpy的broadcast机制,得到的是向量
  23. xx1 = np.maximum(x1[i], x1[order[1:]])
  24. yy1 = np.maximum(y1[i], y1[order[1:]])
  25. xx2 = np.minimum(x2[i], x2[order[1:]])
  26. yy2 = np.minimum(y2[i], y2[order[1:]])
  27. #计算相交框的面积,注意矩形框不相交时w或h算出来会是负数,用0代替
  28. w = np.maximum(0.0, xx2 - xx1 + 1)
  29. h = np.maximum(0.0, yy2 - yy1 + 1)
  30. inter = w * h
  31. #计算重叠度IOU:重叠面积/(面积1+面积2-重叠面积)
  32. ovr = inter / (areas[i] + areas[order[1:]] - inter)
  33. #找到重叠度不高于阈值的矩形框索引
  34. inds = np.where(ovr <= thresh)[0]
  35. # print("inds:",inds)
  36. #将order序列更新,由于前面得到的矩形框索引要比矩形框在原order序列中的索引小1,所以要把这个1加回来
  37. order = order[inds + 1]
  38. return keep
  39. def template(img_gray,template_img,template_threshold):
  40. '''
  41. img_gray:待检测的灰度图片格式
  42. template_img:模板小图,也是灰度化了
  43. template_threshold:模板匹配的置信度
  44. '''
  45. h, w = template_img.shape[:2]
  46. res = cv2.matchTemplate(img_gray, template_img, cv2.TM_CCOEFF_NORMED)
  47. start_time = time.time()
  48. loc = np.where(res >= template_threshold)#大于模板阈值的目标坐标
  49. score = res[res >= template_threshold]#大于模板阈值的目标置信度
  50. #将模板数据坐标进行处理成左上角、右下角的格式
  51. xmin = np.array(loc[1])
  52. ymin = np.array(loc[0])
  53. xmax = xmin+w
  54. ymax = ymin+h
  55. xmin = xmin.reshape(-1,1)#变成n行1列维度
  56. xmax = xmax.reshape(-1,1)#变成n行1列维度
  57. ymax = ymax.reshape(-1,1)#变成n行1列维度
  58. ymin = ymin.reshape(-1,1)#变成n行1列维度
  59. score = score.reshape(-1,1)#变成n行1列维度
  60. data_hlist = []
  61. data_hlist.append(xmin)
  62. data_hlist.append(ymin)
  63. data_hlist.append(xmax)
  64. data_hlist.append(ymax)
  65. data_hlist.append(score)
  66. data_hstack = np.hstack(data_hlist)#将xmin、ymin、xmax、yamx、scores按照列进行拼接
  67. thresh = 0.3#NMS里面的IOU交互比阈值
  68. keep_dets = py_nms(data_hstack, thresh)
  69. print("nms time:",time.time() - start_time)#打印数据处理到nms运行时间
  70. dets = data_hstack[keep_dets]#最终的nms获得的矩形框
  71. return dets
  72. if __name__ == "__main__":
  73. img_rgb = cv2.imread('mario.jpg')#需要检测的图片
  74. img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)#转化成灰色
  75. template_img = cv2.imread('mario_coin.jpg', 0)#模板小图
  76. template_threshold = 0.8#模板置信度
  77. dets = template(img_gray,template_img,template_threshold)
  78. count = 0
  79. for coord in dets:
  80. cv2.rectangle(img_rgb, (int(coord[0]),int(coord[1])), (int(coord[2]),int(coord[3])), (0, 0, 255), 2)
  81. cv2.imwrite("result.jpg",img_rgb)

检测效果如下所示:

参考资料:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/81325
推荐阅读
相关标签
  

闽ICP备14008679号