如何使用Python对图片进行非极大抑制

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对图像进行非极大抑制。实现步骤包括加载图像、进行预处理、查找候选框、对候选框进行排序以及实现非极大抑制等。

后端开发标签