计算机视觉(7)基于NMS算法从一副图像中找出相同的目标物体

NMS算法(NonMaximumSuppression):

非极大值抑制(NMS)顾名思义就是抑制不是极大值的元素,搜索局部的极大值。这个局部代表的是一个邻域,邻域有两个参数可变,一是邻域的维数,二是邻域的大小。这里不讨论通用的NMS算法,而是用于在目标检测中用于提取分数最高的窗口的。

例如在行人检测中,滑动窗口经提取特征,经分类器分类识别后,每个窗口都会得到一个分数。但是滑动窗口会导致很多窗口与其他窗口存在包含或者大部分交叉的情况。这时就需要用到NMS来选取那些邻域里分数最高(是行人的概率最大),并且抑制那些分数低的窗口。

实现步骤如下:

  1. 设定目标框的置信度阈值,常用的阈值是0.5左右

  2. 根据置信度降序排列候选框列表

  3. 选取置信度最高的框A添加到输出列表,并将其从候选框列表中删除

  4. 计算A与候选框列表中的所有框的IoU值,删除大于阈值的候选框

  5. 重复上述过程,直到候选框列表为空,返回输出列表

 

 1 import cv2
 2 import numpy as np
 3 import os
 4 import time
 5 import matplotlib.pyplot as plt
 6 import copy
 7 
 8 
 9 
10 def NMS(boxes, overlapThresh = 0.4):
11     #return an empty list, if no boxes given
12     if len(boxes) == 0:
13         return []
14     x1 = boxes[:, 0]  # x coordinate of the top-left corner
15     y1 = boxes[:, 1]  # y coordinate of the top-left corner
16     x2 = boxes[:, 2]  # x coordinate of the bottom-right corner
17     y2 = boxes[:, 3]  # y coordinate of the bottom-right corner
18     # compute the area of the bounding boxes and sort the bounding
19     # boxes by the bottom-right y-coordinate of the bounding box
20     areas = (x2 - x1 + 1) * (y2 - y1 + 1) # We have a least a box of one pixel, therefore the +1
21     indices = np.arange(len(x1))
22     for i,box in enumerate(boxes):
23         temp_indices = indices[indices!=i]
24         xx1 = np.maximum(box[0], boxes[temp_indices,0])
25         yy1 = np.maximum(box[1], boxes[temp_indices,1])
26         xx2 = np.minimum(box[2], boxes[temp_indices,2])
27         yy2 = np.minimum(box[3], boxes[temp_indices,3])
28         w = np.maximum(0, xx2 - xx1 + 1)
29         h = np.maximum(0, yy2 - yy1 + 1)
30         # compute the ratio of overlap
31         overlap = (w * h) / areas[temp_indices]
32         if np.any(overlap) > treshold:
33             indices = indices[indices != i]
34     return boxes[indices].astype(int)
35 
36 def bounding_boxes(image, template):
37     (tH, tW) = template.shape[:2]             # getting height and width of template
38     imageGray = cv2.cvtColor(image, 0)        # convert the image to grayscale
39     templateGray = cv2.cvtColor(template, 0)  # convert the template to grayscale
40 
41     result = cv2.matchTemplate(imageGray, templateGray, cv2.TM_CCOEFF_NORMED)  # template matching return the correlatio
42     print(result)
43     print('--------------')
44     (y1, x1) = np.where(result >= treshold)  # object is detected, where the correlation is above the treshold
45 
46     boxes = np.zeros((len(y1), 4))      # construct array of zeros
47     x2 = x1 + tW                       # calculate x2 with the width of the template
48     y2 = y1 + tH                       # calculate y2 with the height of the template
49     # fill the bounding boxes array
50     boxes[:, 0] = x1
51     boxes[:, 1] = y1
52     boxes[:, 2] = x2
53     boxes[:, 3] = y2
54     return boxes.astype(int)
55 
56 def draw_bounding_boxes(image,boxes):
57     for box in boxes:
58 
59     return image
60 
61 if __name__ == "__main__":
62     # time.sleep(2)
63     treshold = 0.5837 # the correlation treshold, in order for an object to be recognised
64     # template_diamonds = plt.imread(r"cones/ace_diamonds_plant_template.jpg")
65     template_diamonds = plt.imread(r"cones/22.jpg")
66 
67     ace_diamonds_rotated = plt.imread(r"cones/11.jpg")
68 
69     boxes_redundant = bounding_boxes(ace_diamonds_rotated, template_diamonds) # calculate bounding boxes
70     print(len(boxes_redundant))
71     boxes = NMS(boxes_redundant)   # remove redundant bounding boxes
72 
73     print(boxes)
74     overlapping_BB_image = draw_bounding_boxes(ace_diamonds_rotated,boxes_redundant)  # draw image with all redundant bounding boxes
75     segmented_image = draw_bounding_boxes(ace_diamonds_rotated,boxes)           # draw the bounding boxes onto the image
76     plt.imshow(overlapping_BB_image)
77     plt.show()
78     plt.imshow(segmented_image)
79     plt.show()
View Code

 

 

 

posted @ 2021-12-16 14:37  hotzhml  阅读(247)  评论(0编辑  收藏  举报