select-nms
时间: 2023-10-23 16:13:53 浏览: 105
select-nms是一个目标检测领域常用的算法,用于在检测结果中进行非极大值抑制(Non-Maximum Suppression,简称NMS)。NMS的目的是根据一定的阈值,从多个重叠的候选框中选择出最具代表性的框。
NMS的基本思想是,首先根据检测结果的置信度进行排序,然后从置信度最高的框开始,依次判断其与后续框的重叠程度,如果重叠程度大于设定的阈值,则将该框移除。这样可以保留最具代表性的框,并且去除冗余的框。
相关问题
YOLOv8 CIoU-NMS
### YOLOv8中的CIoU-NMS实现
在YOLOv8中,为了提升目标检测的精度并减少冗余预测框的数量,采用了CIoU-NMS(Complete Intersection over Union Non-Maximum Suppression)。这一方法不仅考虑了边界框之间的重叠区域,还加入了中心点距离以及宽高比例的因素来衡量两个边框间的相似度[^1]。
具体来说,在执行NMS操作时,对于每一个类别下的候选框集合:
- 首先计算这些候选框两两之间的CIoU值;
- 接着选取具有最高置信度得分的那个作为当前类别的最优解;
- 对于剩余未处理过的候选框,则会依据设定阈值剔除掉那些与已选最佳匹配项高度重合的部分;
以下是Python代码片段展示了如何基于PyTorch框架下实现该算法逻辑的一部分:
```python
import torch
def ciou_nms(boxes, scores, iou_threshold=0.5):
"""
实现带有CIoU标准的非极大抑制
参数:
boxes (Tensor[N, 4]): 边界框坐标(xmin,ymin,xmax,ymax)
scores (Tensor[N]): 各个边界框对应的分数
iou_threshold (float): IoU阈值
返回:
Tensor[M]: 经过筛选后的索引列表
"""
# 计算所有box面积
areas = (boxes[:, 2]-boxes[:, 0]) * (boxes[:, 3]-boxes[:, 1])
_, order = scores.sort(descending=True)
keep = []
while order.numel() > 0:
if order.numel() == 1:
break
i = order[0]
keep.append(i.item())
xx1 = torch.index_select(boxes[:, 0], 0, order)[1:].clamp(min=torch.index_select(boxes[:, 0], 0, order)[:1].item())
yy1 = torch.index_select(boxes[:, 1], 0, order)[1:].clamp(min=torch.index_select(boxes[:, 1], 0, order)[:1].item())
xx2 = torch.index_select(boxes[:, 2], 0, order)[1:].clamp(max=torch.index_select(boxes[:, 2], 0, order)[:1].item())
yy2 = torch.index_select(boxes[:, 3], 0, order)[1:].clamp(max=torch.index_select(boxes[:, 3], 0, order)[:1].item())
w = (xx2 - xx1).clamp(min=0.)
h = (yy2 - yy1).clamp(min=0.)
inter = w*h
rem_areas = torch.index_select(areas, 0, order)[1:]
union = rem_areas + areas[i] - inter
center_x1 = (torch.index_select(boxes[:, 0]+boxes[:, 2], 0, order)[1:] / 2.).unsqueeze(-1)
center_y1 = (torch.index_select(boxes[:, 1]+boxes[:, 3], 0, order)[1:] / 2.).unsqueeze(-1)
c = ((center_x1-center_x1[:1])**2+(center_y1-center_y1[:1])**2)**0.5
rho = (((boxes[i][0]+boxes[i][2])/2-(boxes[:, 0]+boxes[:, 2])[order][1:]/2)**2+
((boxes[i][1]+boxes[i][3])/2-(boxes[:, 1]+boxes[:, 3])[order][1:]/2)**2)**0.5
v = (4/((math.pi)**2)) * \
torch.pow(torch.atan(
(boxes[i][2]-boxes[i][0])/(boxes[i][3]-boxes[i][1])) -
torch.atan((boxes[:, 2]-boxes[:, 0])[order][1:] /
(boxes[:, 3]-boxes[:, 1])[order][1:])
, 2)
alpha = v / (1-inter/union+v+eps)
ciou_loss = inter/union-rho/c-alpha*v
overlap = inter / union-ciou_loss
inds = (overlap <= iou_threshold).nonzero().squeeze()
if inds.numel() == 0:
break
order = order[inds+1]
return torch.LongTensor(keep)
```
此函数接收一组边界框及其相应的评分,并返回经过CIoU NMS过滤之后保留下来的边界框索引数组。通过这种方式可以有效地去除重复标记的对象实例,从而提高了模型输出的质量和可靠性。
super(Ui_MainWindow, self).__init__(parent) parser_car_det = argparse.ArgumentParser() # parser.add_argument('--weights', type=str, default='weights-s/best1.pt', help='model.pt path') parser_car_det.add_argument('--weights', type=str, default='weights-s/best1.pt', help='model.pt path') parser_car_det.add_argument('--source', type=str, default='input/3.mp4', help='source') # file/folder, 0 for webcam # parser.add_argument('--source', type=str, default='rtsp://admin:hik12345@192.168.1.64:554//Streaming/Channels/101', help='source') # file/folder, 0 for webcam parser_car_det.add_argument('--output', type=str, default='inference/output', help='output folder') # output folder parser_car_det.add_argument('--img-size', type=int, default=640, help='inference size (pixels)') parser_car_det.add_argument('--conf-thres', type=float, default=0.4, help='object confidence threshold') parser_car_det.add_argument('--iou-thres', type=float, default=0.5, help='IOU threshold for NMS') parser_car_det.add_argument('--fourcc', type=str, default='mp4v', help='output video codec (verify ffmpeg support)') parser_car_det.add_argument('--device', default='cpu', help='cuda device, i.e. 0 or 0,1,2,3 or cpu') parser_car_det.add_argument('--view-img', action='store_true', help='display results') parser_car_det.add_argument('--save-txt', action='store_true', help='save results to *.txt') parser_car_det.add_argument('--classes', nargs='+', type=int, help='filter by class') parser_car_det.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS') parser_car_det.add_argument('--augment', action='store_true', help='augmented inference') parser_car_det.add_argument('--idx', default='2', help='idx') self.opt_car_det = parser_car_det.parse_args() self.opt_car_det.img_size = check_img_size(self.opt_car_det.img_size) half = 0 source_car_det, weights_car_det, view_img_car_det, save_txt_car_det, imgsz_car_det = self.opt_car_det.source, self.opt_car_det.weights, self.opt_car_det.view_img, self.opt_car_det.save_txt, self.opt_car_det.img_size self.device_car_det = torch_utils.select_device(self.opt_car_det.device) self.half_car_det = 0 # half precision only supported on CUDA cudnn.benchmark = True
super(Ui_MainWindow, self).__init__(parent) 表示使用父类的构造函数来初始化子类,这里父类是 Ui_MainWindow。
parser_car_det = argparse.ArgumentParser() 表示定义了一个解析器,用来解析输入的参数。
阅读全文