1. 什么是非极大抑制
在计算机视觉领域的目标检测任务中,非极大抑制(Non-Maximum Suppression,NMS)是一种常用的策略。其主要作用是从多个重叠的候选框中选择出较优的一个,以减少检测结果中的重复框。具体思想是通过计算各个框的置信度得分,并删除重叠区域内得分低的框。在本文中,将介绍如何使用Python对图像进行非极大抑制。
2. 实现过程
2.1 导入必要模块
首先,我们需要导入必要的Python模块:
import numpy as np
import cv2
其中,numpy
模块用于数组操作,cv2
模块用于图像处理。
2.2 加载图像
接下来,我们需要加载一张待处理的图像。
image = cv2.imread("test.jpg")
其中,test.jpg
是一张测试用的图像。
2.3 对图像进行预处理
在进行非极大抑制之前,我们需要对图像进行一些预处理。首先,我们需要将图像转换为灰度图像。
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
该操作将图像从BGR模式(彩色图像)转换为灰度模式,便于接下来的操作。
2.4 进行边缘检测
接下来,我们对灰度图像进行边缘检测,得到图像中候选框的边缘信息。
edges = cv2.Canny(gray, 100, 200)
该操作使用Canny算法进行边缘检测,得到一张二值图像。该二值图像中,边缘处的像素值为255,非边缘处的像素值为0。
2.5 查找候选框
接下来,我们将在边缘图像中查找候选框。首先,使用OpenCV中的findContours
函数查找边缘。
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
这里,将返回一组轮廓线,其中每个轮廓线都是一组 (x,y) 坐标的集合,表示了边缘的形状和位置。而返回值中的第二个参数是层次结构,用于描述轮廓之间的关系。
接下来,根据得到的轮廓,我们可以创建候选框。
rects = []
for cnt in contours:
rect = cv2.boundingRect(cnt)
rects.append(rect)
其中,cv2.boundingRect
函数可以返回一组 (x,y,w,h) 坐标,表示轮廓的外接矩形。在我们的应用中,该矩形即为候选框。
2.6 对候选框进行排序
接下来,我们需要对候选框按照置信得分进行排序。
confidences = np.random.rand(len(rects))
sorted_idx = np.argsort(-confidences)
rects = [rects[idx] for idx in sorted_idx]
我们这里先用随机数生成了一组置信得分,实际应用中,需要根据实际情况计算该值。然后,使用np.argsort
函数将得分从高到低排序。
2.7 实现非极大抑制
使用排好序的候选框及其置信得分,我们可以实现非极大抑制:
nms_rects = []
for rect in rects:
iou = [cv2.rectangle(image.copy(), rect, (0, 0, 255), 2)]
for nms_rect in nms_rects:
iou.append(get_iou(rect, nms_rect))
if max(iou) < threshold:
nms_rects.append(rect)
else:
continue
其中,nms_rects
变量用于存储非极大抑制后的候选框。我们遍历排好序的候选框,并计算其与前面的所有框的交并比(IoU),判断是否和前面的框重叠。如果重叠度过高,删除该框。否则将其加入nms_rects
中。
以上是完整的Python代码:
import numpy as np
import cv2
def get_iou(rect1, rect2):
x1, y1, w1, h1 = rect1
x2, y2, w2, h2 = rect2
x_inter = max(0, min(x1+w1, x2+w2) - max(x1, x2))
y_inter = max(0, min(y1+h1, y2+h2) - max(y1, y2))
iou = x_inter * y_inter / ((w1*h1) + (w2*h2) - x_inter*y_inter)
return iou
# 加载图像
image = cv2.imread("test.jpg")
# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 进行边缘检测
edges = cv2.Canny(gray, 100, 200)
# 查找候选框
contours, _ = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
rects = []
for cnt in contours:
rect = cv2.boundingRect(cnt)
rects.append(rect)
# 对候选框按照置信得分进行排序
confidences = np.random.rand(len(rects))
sorted_idx = np.argsort(-confidences)
rects = [rects[idx] for idx in sorted_idx]
# 实现非极大抑制
threshold = 0.6
nms_rects = []
for rect in rects:
iou = [cv2.rectangle(image.copy(), rect, (0, 0, 255), 2)]
for nms_rect in nms_rects:
iou.append(get_iou(rect, nms_rect))
if max(iou) < threshold:
nms_rects.append(rect)
else:
continue
3. 总结
本文简要介绍了如何使用Python对图像进行非极大抑制。实现步骤包括加载图像、进行预处理、查找候选框、对候选框进行排序以及实现非极大抑制等。