Non-Maximum Suppression for Object Detection in Python

本文通过实例演示了非最大抑制(Non-Maximum Suppression, NMS)算法的具体实现过程,该算法主要用于去除多余的边界框,减少误检,提高目标检测的准确性。文章通过Python代码解释了NMS的工作原理,并展示了如何应用于实际图像中。

之前看很多的nms 解释都没看懂,看了代码,注释比较好,就懂了,原文有更多解释,更快实现.

想法是只留下不重合的框,过程是任何一框,与其它任何一筐,重合超过一个值,去掉它。
http://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/?utm_source=tuicool&utm_medium=referral

# import the necessary packages
import numpy as np


#  Felzenszwalb et al.
def non_max_suppression_slow(boxes, overlapThresh):
	# if there are no boxes, return an empty list
	if len(boxes) == 0:
		return []


	# initialize the list of picked indexes
	pick = []


	# grab the coordinates of the bounding boxes
	x1 = boxes[:,0]
	y1 = boxes[:,1]
	x2 = boxes[:,2]
	y2 = boxes[:,3]


	# compute the area of the bounding boxes and sort the bounding
	# boxes by the bottom-right y-coordinate of the bounding box
	area = (x2 - x1 + 1) * (y2 - y1 + 1)
	idxs = np.argsort(y2)
# import the necessary packages
import numpy as np


#  Felzenszwalb et al.
def non_max_suppression_slow(boxes, overlapThresh):
	# if there are no boxes, return an empty list
	if len(boxes) == 0:
		return []


	# initialize the list of picked indexes
	pick = []


	# grab the coordinates of the bounding boxes
	x1 = boxes[:,0]
	y1 = boxes[:,1]
	x2 = boxes[:,2]
	y2 = boxes[:,3]


	# compute the area of the bounding boxes and sort the bounding
	# boxes by the bottom-right y-coordinate of the bounding box
	area = (x2 - x1 + 1) * (y2 - y1 + 1)
	idxs = np.argsort(y2)


	# keep looping while some indexes still remain in the indexes
	# list
	while len(idxs) > 0:
		# grab the last index in the indexes list, add the index
		# value to the list of picked indexes, then initialize
		# the suppression list (i.e. indexes that will be deleted)
		# using the last index
		last = len(idxs) - 1
		i = idxs[last]
		pick.append(i)
		suppress = [last]
# import the necessary packages
import numpy as np


#  Felzenszwalb et al.
def non_max_suppression_slow(boxes, overlapThresh):
	# if there are no boxes, return an empty list
	if len(boxes) == 0:
		return []


	# initialize the list of picked indexes
	pick = []


	# grab the coordinates of the bounding boxes
	x1 = boxes[:,0]
	y1 = boxes[:,1]
	x2 = boxes[:,2]
	y2 = boxes[:,3]


	# compute the area of the bounding boxes and sort the bounding
	# boxes by the bottom-right y-coordinate of the bounding box
	area = (x2 - x1 + 1) * (y2 - y1 + 1)
	idxs = np.argsort(y2)


	# keep looping while some indexes still remain in the indexes
	# list
	while len(idxs) > 0:
		# grab the last index in the indexes list, add the index
		# value to the list of picked indexes, then initialize
		# the suppression list (i.e. indexes that will be deleted)
		# using the last index
		last = len(idxs) - 1
		i = idxs[last]
		pick.append(i)
		suppress = [last]


		# loop over all indexes in the indexes list
		for pos in xrange(0, last):
			# grab the current index
			j = idxs[pos]


			# find the largest (x, y) coordinates for the start of
			# the bounding box and the smallest (x, y) coordinates
			# for the end of the bounding box
			xx1 = max(x1[i], x1[j])
			yy1 = max(y1[i], y1[j])
			xx2 = min(x2[i], x2[j])
			yy2 = min(y2[i], y2[j])


			# compute the width and height of the bounding box
			w = max(0, xx2 - xx1 + 1)
			h = max(0, yy2 - yy1 + 1)


			# compute the ratio of overlap between the computed
			# bounding box and the bounding box in the area list
			overlap = float(w * h) / area[j]


			# if there is sufficient overlap, suppress the
			# current bounding box
			if overlap > overlapThresh:
				suppress.append(pos)


		# delete all indexes from the index list that are in the
		# suppression list
		idxs = np.delete(idxs, suppress)


	# return only the bounding boxes that were picked
	return boxes[pick]
# import the necessary packages
from pyimagesearch.nms import non_max_suppression_slow
import numpy as np
import cv2


# construct a list containing the images that will be examined
# along with their respective bounding boxes
images = [
<span style="white-space:pre">	</span>("images/audrey.jpg", np.array([
<span style="white-space:pre">	</span>(12, 84, 140, 212),
<span style="white-space:pre">	</span>(24, 84, 152, 212),
<span style="white-space:pre">	</span>(36, 84, 164, 212),
<span style="white-space:pre">	</span>(12, 96, 140, 224),
<span style="white-space:pre">	</span>(24, 96, 152, 224),
<span style="white-space:pre">	</span>(24, 108, 152, 236)])),
<span style="white-space:pre">	</span>("images/bksomels.jpg", np.array([
<span style="white-space:pre">	</span>(114, 60, 178, 124),
<span style="white-space:pre">	</span>(120, 60, 184, 124),
<span style="white-space:pre">	</span>(114, 66, 178, 130)])),
<span style="white-space:pre">	</span>("images/gpripe.jpg", np.array([
<span style="white-space:pre">	</span>(12, 30, 76, 94),
<span style="white-space:pre">	</span>(12, 36, 76, 100),
<span style="white-space:pre">	</span>(72, 36, 200, 164),
<span style="white-space:pre">	</span>(84, 48, 212, 176)]))]


# loop over the images
for (imagePath, boundingBoxes) in images:
<span style="white-space:pre">	</span># load the image and clone it
<span style="white-space:pre">	</span>print "[x] %d initial bounding boxes" % (len(boundingBoxes))
<span style="white-space:pre">	</span>image = cv2.imread(imagePath)
<span style="white-space:pre">	</span>orig = image.copy()


<span style="white-space:pre">	</span># loop over the bounding boxes for each image and draw them
<span style="white-space:pre">	</span>for (startX, startY, endX, endY) in boundingBoxes:
<span style="white-space:pre">		</span>cv2.rectangle(orig, (startX, startY), (endX, endY), (0, 0, 255), 2)


<span style="white-space:pre">	</span># perform non-maximum suppression on the bounding boxes
<span style="white-space:pre">	</span>pick = non_max_suppression_slow(boundingBoxes, 0.3)
<span style="white-space:pre">	</span>print "[x] after applying non-maximum, %d bounding boxes" % (len(pick))


<span style="white-space:pre">	</span># loop over the picked bounding boxes and draw them
<span style="white-space:pre">	</span>for (startX, startY, endX, endY) in pick:
<span style="white-space:pre">		</span>cv2.rectangle(image, (startX, startY), (endX, endY), (0, 255, 0), 2)


<span style="white-space:pre">	</span># display the images
<span style="white-space:pre">	</span>cv2.imshow("Original", orig)
<span style="white-space:pre">	</span>cv2.imshow("After NMS", image)
<span style="white-space:pre">	</span>cv2.waitKey(0)
### 密度图引导的目标检测方法概述 密度图引导的目标检测是一种有效的方法,尤其适用于处理高密度场景中的目标检测问题。这种方法的核心在于通过生成一张描述目标分布的密度图来辅助后续的对象检测过程[^1]。具体来说,密度图可以提供关于目标位置及其相对密集程度的信息,从而帮助模型更好地聚焦于潜在的目标区域。 #### 方法实现的关键步骤 以下是基于密度图引导的目标检测方法的主要组成部分: 1. **密度图生成** 使用特定算法(如卷积神经网络或其他回归技术),从训练数据集中生成目标的密度图。这些密度图通常是一个二维矩阵,其值反映了每个像素处目标的数量或概率[^4]。对于航拍图像而言,由于可能存在大量小型目标(如车辆、行人等),因此精确建模目标的空间分布尤为重要。 2. **聚类区域生成** 基于生成的密度图,采用一种由密度映射引导的聚类区域生成算法,将输入图像分割为若干子区域。此过程中会考虑对象的实际尺寸以及它们之间的距离关系,确保裁剪出的子区域内包含合理数量和规模的目标。这种策略不仅能够减少计算复杂度,还能提升对小目标的检测能力。 3. **多尺度特征提取与融合** 针对不同大小的目标,设计专门的网络结构以增强模型捕获多尺度信息的能力。例如,在某些研究中提到过增加高级语义特征的感受野并细化空间细节的做法可以帮助改善多尺度目标检测的效果[^3]。此外,还可以借鉴其他工作提出的ScaleNet组件动态调整感兴趣区域(ROI) 的形状参数,进一步优化最终预测质量。 4. **后处理阶段——结果融合** 完成上述各步之后,需把来自各个局部窗口的结果重新拼接回原图坐标系下形成全局范围内的检测框集合。与此同时也要注意解决可能存在的重复标记问题 (Non-Maximum Suppression),保证输出干净整洁无冗余。 #### 示例代码片段 下面给出一段简单的伪代码展示如何利用预估得到的density maps来进行object proposals generation: ```python import numpy as np from skimage import measure def generate_proposals(density_map, threshold=0.5): """ Generate object proposal regions based on the density map. Args: density_map (numpy.ndarray): A 2D array representing the estimated number of objects per pixel. threshold (float): Threshold value to binarize the density map into foreground/background masks. Returns: list[tuple]: List of bounding box coordinates [(xmin, ymin, xmax, ymax)]. """ binary_mask = density_map > threshold # Find connected components in the mask label_image = measure.label(binary_mask) props = [] for region in measure.regionprops(label_image): minr, minc, maxr, maxc = region.bbox props.append((minc, minr, maxc, maxr)) return props ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值