今天学习Detections和Segmentation底下的Double Detection Filter和一些列方法工具Utils
一、Double Detection Filter(官方文档下归的类)
-
OverlapFilter类
-
介绍:
- OverlapFilter类是一个枚举类,枚举过滤重叠的策略,主要处理一些检测框或检测膜重叠的问题
-
属性:
- NONE:不根据重叠过滤检测
- NON_MAX_SUPPRESSION:使用非极大值抑制过滤nms,重叠度大于阈值时,置信度低的会被舍去
- NON_MAX_MERGE:使用非极大值合并过滤nmm,重叠度大于阈值时,会合并为一个框
-
-
相关方法(注意不是上面类下的方法):
-
return = box_non_max_suppression(predictions,iou_threshold)
: -
对检测框使用非极大值抑制过滤重合度过高的框
- predictions:带有检测结果的数组,格式为(x_min,y_min,x_max,y_max,score,[class])
- iou_threshold:检测的阈值,默认为0.5
- return:为一个布尔数组,指示哪些检测框被去除,哪些保留
-
return = mask_non_max_suppression(predictions,masks,iou_threshold,mask_dimension)
: -
对分割对象使用非极大值抑制过滤重合度过高的掩膜
- predictions:带有检测结果的数组
- mask:掩膜数组
- iou_threshold:检测的阈值,默认为0.5
- mask_dimension:由于掩膜大小不一定一致,在计算IoU时会有粗我u,因此需要先调整大小到一致,默认为640.
- return:为一个布尔数组,指示哪些检测框被去除,哪些保留
-
return = box_non_max_merge(predictions,iou_threshold)
: -
对检测框使用非极大值合并过滤重合度过高的框,参数和返回值与第一个一致
-
演示:
使用的图片是之前使用的,一辆车同时被识别为truck和car的图片
import cv2 import numpy as np import supervision as sv from ultralytics import YOLO model=YOLO('yolo11n.pt') image=cv2.imread('images/dog_bike.jpeg') result=model(image)[0] detections=sv.Detections.from_ultralytics(result) #使用concatenate函数将xyxy和confidence拼接起来,否则如果不满足格式会报错 predictions = np.concatenate((detections.xyxy,detections.confidence.reshape(-1, 1)),axis=1) ret=sv.box_non_max_suppression(predictions)
对比两张图,可见当使用了box_non_max_suppression函数之后,truck类的框被去除了,前三个类的框被保留了
这几个函数其实用的很少,因此剩下的就不过多介绍了
-
二、Utils
-
return = box_iou_batch(boxes_true,boxes_detection)
:-
计算两个框的重叠程度IoU(Intersection over Union)
- box_true:真实的边框的数组。因为IoU是衡量检测程度的一个指标,预测的框和实际的框IoU越接近1,说明预测越正确,所以才取名box_true。形状为(N,4),内容为[x_min,y_min,x_max,y_max]
- box_detection:另一个边框数组,取名原因同box_true。也为一个数组,形状为(M,4),内容同上
- return:一个数组,每个元素表示box_true的每个框与box_detection中每个框的IoU值,形状为(N,M)
import numpy as np import supervision as sv box1=np.array([[0,0,10,10], [0,0,10,10], [5,5,10,10], [5,5,10,10]]) box2=np.array([[0,0,5,10], [0,0,5,5], [5,5,10,10]]) print(sv.box_iou_batch(box1,box2)) """ 输出为: [[0.5 0.25 0.25] [0.5 0.25 0.25] [0. 0. 1. ] [0. 0. 1. ]] 这里每个值都很好算出,结果也与输出一致 """
-
-
return = mask_iou_batch(masks_true,masks_detection,memory_limit)
-
return = oriented_box_iou_batch(boxes_true,boxes_detection)
-
这两个函数与box_iou_batch功能一致,只不过计算的是掩膜和旋转边界框的iou,memory_limit为内存限制,默认为5MB*1024。对于旋转边界框,其格式应为(N,4,2),4表示其四个顶点坐标,不再像水平边界框一样只用两个点就能表示出来。其他不再赘述
-
-
return = ploygon_to_mask
(polygon,resolution_wh)-
从一个多边形生成一个掩膜,多边形包裹的区域为1,其余为0
-
polygon:多边形的顶点坐标,格式为(N,2),注意坐标格式为(x,y),但是数组索引格式是(y,x)
-
resolution_wh:输出的掩膜的大小,格式为(height,width),原点为数组[0][0]点,如果多边形坐标超出了这个范围则只会显示在这个范围内的(即多边形在[0,height-1][0,width-1]这个范围内的部分)
-
return:返回值为一个二值矩阵
import numpy as np import supervision as sv #需要的格式为(x,y),但数组索引为[y][x],这里要注意 poly=np.array([[2,0],[0,2],[2,4]]) print(sv.polygon_to_mask(poly,(6,6))) """ 输出为: [[0. 0. 1. 0. 0. 0.] [0. 1. 1. 0. 0. 0.] [1. 1. 1. 0. 0. 0.] [0. 1. 1. 0. 0. 0.] [0. 0. 1. 0. 0. 0.] [0. 0. 0. 0. 0. 0.]] """
-
-
return = mask_to_xyxy(masks)
-
将一个掩膜数组中的掩膜转换为xyxy格式
-
masks:输入的掩膜数组,注意这个masks是一个数组,数组内容为掩膜,因此形状为[N,W,H],N为掩膜数量,W和H分别为宽和高
-
return:一个形状为(N,4)的数组,表示每个掩膜对应的xyxy值
import numpy as np import supervision as sv #注意,masks需要是三维的 masks=np.array([[ [0,0, 1, 0, 0, 0,], [0, 1, 1, 0, 0, 0,], [1, 1, 1, 0, 0, 0,], [0, 1, 1, 0, 0, 0,], [0, 0, 1, 0, 0, 0,], [0, 0, 0, 0, 0, 0,]]]) xyxy=sv.mask_to_xyxy(masks) print(xyxy) """ 输出为: [[0 0 2 4]] """
-
-
return = mask_to_polygons(mask)
-
将一个掩膜转换为多边形
-
mask:一个掩膜,注意这里跟上一个函数不一样,这里是一个二维数组,即单个掩膜
-
return:返回的多边形坐标的数组,形状为(N,2)如果结果的多边形点数<3的会被排除
import numpy as np import supervision as sv #注意,这里mask是二维的 mask=np.array([ [0, 0, 1, 0, 0, 0,], [0, 1, 1, 0, 0, 0,], [1, 1, 1, 0, 0, 0,], [0, 1, 1, 0, 0, 0,], [0, 0, 1, 0, 0, 0,], [0, 0, 0, 0, 0, 0,]] ) polygon=sv.mask_to_polygons(mask) print(polygon) """ 输出: [array([[2, 0], [0, 2], [2, 4]], dtype=int32)] """
-
-
return = polygon_to_xyxy(polygon)
-
将多边形转换为xyxy格式
-
polygon:多边形顶点坐标数组,形状为(N,2)
-
return:一维数组,为xyxy格式的(x_min,y_min,x_max,y_max)
import numpy as np import supervision as sv polygon=np.array([ [2, 0], [0, 2], [2, 4]]) xyxy=sv.polygon_to_xyxy(polygon) print(xyxy) """ 输出: [0 0 2 4] """
-
-
return = filter_polygons_by_area(polygons,min_area,max_area)
-
根据多边形的区域面积筛选多边形
-
polygons:多边形的数组,注意其类型为List[ndarray],是python的数组,内容为numpy数组,形状为(N,2)
-
min_area:最小面积阈值,< min_area的会被过滤掉。如果为None则表示不使用最小面积阈值,默认为None
-
max_area:最大面积阈值,> max_area的会被过滤掉。如果为None则表示不使用最大面积阈值,默认为None
import supervision as sv import numpy as np polygon1=np.array([[2,4],[4,2],[2,0]]) polygon2=np.array([[1,3],[3,1],[2,2],[1,0]]) list_polygons=[polygon1,polygon2] print(sv.filter_polygons_by_area(list_polygons,4,6)) """ 输出: [array([[2, 4], [4, 2], [2, 0]])] """
-
-
return = move_boxes(xyxy,offset)
-
移动框
-
xyxy:形状为(N,4)的数组,元素为(x_min,y_min,x_max,y_max)
-
offset:一个形状为(2,)的数组,表示x坐标的位移和y坐标的位移
import numpy as np import supervision as sv xyxy = np.array([ [0, 0, 0, 0], [0, 0, 0, 0], [1, 2, 2, 1] ]) offset = np.array([1, 5]) print(sv.move_boxes(xyxy=xyxy, offset=offset)) """ 输出: [[1 5 1 5] [1 5 1 5] [2 7 3 6]] """
-
-
return = scale_boxes(xyxy,factor)
-
缩放边框,由于简单,就不给出代码演示了
- xyxy:一个边框
- factor:缩放因子
-
-
return = clip_boxes(xyxy,resolution_wh)
-
剪辑边框坐标以适应帧分辨率
-
xyxy:一个边框
-
resolution_wh:帧分辨率的宽度和高度,为元组,格式为(width,height)
import numpy as np import supervision as sv xyxy = np.array([ [10, 20, 300, 200], [15, 25, 350, 450], [-10, -20, 30, 40] ]) sv.clip_boxes(xyxy=xyxy, resolution_wh=(320, 240)) # array([ # [ 10, 20, 300, 200], # [ 15, 25, 320, 240], # [ 0, 0, 30, 40] # ])
-
-
return = contains_holes(mask)
-
判断掩膜是否含有孔
-
mask:一个掩膜
-
return:返回一个布尔值,True表示有孔,否则为False
import numpy as np import supervision as sv mask = np.array([ [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0] ]) print(sv.contains_holes(mask=mask)) #输出:True mask = np.array([ [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0] ]) print(sv.contains_holes(mask=mask)) #输出:False
-
-
return = contains_multiple_segments(mask,connectivity)
-
用于检查掩膜中是否包含多个未连接的前景
-
mask:一个掩膜
-
connectivity:确定像素是否属于同一个连通区域的连接方式,有4-连通性和8-连通性,前者包括上下左右,后者还包括了四个斜角。默认为4,还可以为8
-
return:返回一个布尔值,表示是否存在
import numpy as np import supervision as sv mask = np.array([ [0, 0, 0, 0, 0, 0], [0, 1, 1, 0, 1, 1], [0, 1, 1, 0, 1, 1], [0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0], [0, 1, 1, 1, 0, 0] ]) print(sv.contains_multiple_segments(mask=mask, connectivity=4)) #输出:True mask = np.array([ [0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0] ]) print(sv.contains_multiple_segments(mask=mask, connectivity=4)) #输出:False
-
-
对于这些内容,我选取了大部分来学习,对于一些不常用的内容并未列出来
标签:return,Utils,mask,sv,supervision,np,import,xyxy,Day From: https://www.cnblogs.com/WineMarks-Garden/p/18504081