用到的关键技术
IOU
iou表示两个框重叠的比例,iou越大,表示两个框重叠部分越多,越有可能框的是同一个物体
import numpy as np<br># 定义IOU(交并比)计算公式, 传入真实框和其他移动后的框<br>def iou(box, boxes, isMin=False):<br> box_area = (box[2] - box[0]) * (box[3] - box[1]) # 计算原始真实框的面积<br> boxes_area = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) # 计算移动后的框的面积,这里计算的是矩阵<br> # 找到两个框的内部点计算交集<br> x1 = np.maximum(box[0], boxes[:, 0])<br> y1 = np.maximum(box[1], boxes[:, 1])<br> x2 = np.minimum(box[2], boxes[:, 2])<br> y2 = np.minimum(box[3], boxes[:, 3])<br> # 然后找到交集区域的长和宽,有的框没有交集那么相差可能为负,所以需要使用0来规整数据<br> w = np.maximum(0, x2 - x1)<br> h = np.maximum(0, y2 - y1)<br> # 计算交集的面积<br> inter_area = w * h<br> # 两种计算方法:1是交并比等于交集除以并集,2是交集除以最小的面积<br> if isMin:<br> ovr_area = np.true_divide(inter_area, np.minimum(boxes_area, box_area))<br> else:<br> ovr_area = np.true_divide(inter_area, (boxes_area + box_area - inter_area))<br># 返回交并比,也就是IOU<br> return ovr_area<br>
NMS
# 定义NMS,筛选符合标准的线框<br>def nms(boxes, thresh=0.3, isMin=False):<br># 如果照片里面没有框数据了,就返回空列表<br> if len(boxes) == 0:<br> return np.array([])<br># 以计算出的iou从大到小排列<br> _boxes = boxes[(-boxes[:, 4]).argsort()]<br> r_boxes = []<br># 如果框的有1个以上就进行对比<br> while len(_boxes) > 1:<br> a_box = _boxes[0] # 取出最大的框<br> b_boxes = _boxes[1:] # 剩下的框分别和之前的进行比对<br> r_boxes.append(a_box) # 先将最大iou的框添加到保留框的列表中<br> # 保留iou 小于0.3的,说明这个框和目前比对的不是同一个框,去除交集较多的框<br> index = np.where(iou(a_box, b_boxes, isMin) <= thresh)<br> _boxes = b_boxes[index]<br> # _boxes = b_boxes[iou(a_box, b_boxes, isMin) < thresh]<br> # 如果保留的框数量大于0,则添加iou最大的那个框<br> if len(_boxes) > 0:<br> r_boxes.append(_boxes[0])<br> # 将这些框堆叠在一起<br> return np.stack(r_boxes)<br>
Convert2Square(Numpy实现)
# 定义函数将P网络在原图中抠出来的带有人脸的框转变成正方形,以便输入到R网络中<br>def convert_to_square(bbox):<br> squre_bbox = bbox.copy()<br> if len(bbox) == 0:<br> return np.array([])<br> h = bbox[:,3]-bbox[:,1]<br> w = bbox[:,2]-bbox[:,0]<br> max_side = np.maximum(w,h)<br> squre_bbox[:,0] = bbox[:,0]+w*0.5-max_side*0.5<br> squre_bbox[:,1] = bbox[:, 1] + h* 0.5 - max_side * 0.5<br> squre_bbox[:,2] = squre_bbox[:,0]+max_side<br> squre_bbox[:,3] = squre_bbox[:,1]+max_side<br> return squre_bbox<br>