目标检测——yolov4预测及后处理

运用训练好的模型进行目标检测,模型输出为中心点对grid的偏移,长宽相对于anchor的缩放比例以及类别

其维度为(b, 13, 13, 3, classes+5)

1. 根据(x, y, h, w)计算出预测框相对于原图像的位置和大小

def yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape):
    # (b, 13, 13, 3, 2)
    box_yx = box_xy[..., ::-1]
    box_hw = box_wh[..., ::-1]

    input_shape = K.cast(input_shape, K.dtype(box_yx))
    image_shape = K.cast(image_shape, K.dtype(box_yx))

    new_shape = K.round(image_shape * K.min(input_shape / image_shape))
    # 原图相对于input_shape的偏移
    offset = (input_shape - new_shape) / 2. / input_shape
    # 原图相对于input_shape的缩放比例
    scale = input_shape / new_shape
    # 映射回原图
    box_yx = (box_yx - offset) * scale
    box_hw *= scale

    box_mins = box_yx - (box_hw / 2.)
    box_maxes = box_yx + (box_hw / 2.)
    # (b, 13, 13, 3, 4)
    boxes = K.concatenate([
        box_mins[..., 0:1],  # y_min
        box_mins[..., 1:2],  # x_min
        box_maxes[..., 0:1],  # y_max
        box_maxes[..., 1:2]  # x_max
    ])
    # 实际大小
    boxes *= K.concatenate([image_shape, image_shape])
    return boxes

2. 获取得分

box_scores = box_confidence * box_class_probs # 预测置信度和预测类别概率的乘积

3.非极大值抑制

# (n, 4)
boxes = K.concatenate(boxes, axis=0)
# (n, classes_num)
box_scores = K.concatenate(box_scores, axis=0)

设定阈值,大于此阈值的判断为正类(有目标)

mask = box_scores >= score_threshold

对于每一种类别,采用非极大值抑制

    for c in range(num_classes):
        # 取出所有box_scores >= score_threshold的框,和成绩
        class_boxes = tf.boolean_mask(boxes, mask[:, c])
        class_box_scores = tf.boolean_mask(box_scores[:, c], mask[:, c])

        # 非极大抑制,去掉box重合程度高的那一些
        nms_index = tf.image.non_max_suppression(
            class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold)

        # 获取非极大抑制后的结果
        # 下列三个分别是
        # 框的位置,得分与种类
        class_boxes = K.gather(class_boxes, nms_index)
        class_box_scores = K.gather(class_box_scores, nms_index)
        classes = K.ones_like(class_box_scores, 'int32') * c
        boxes_.append(class_boxes)
        scores_.append(class_box_scores)
        classes_.append(classes)
    boxes_ = K.concatenate(boxes_, axis=0)
    scores_ = K.concatenate(scores_, axis=0)
    classes_ = K.concatenate(classes_, axis=0)

    return boxes_, scores_, classes_

非极大值抑制,顾名思义,即如果不是极大值,就将它抑制掉,选取这个类别最大的score,这个就是极大值,是要显示的框,即目标存在与这个位置

将其他位置分别与这个框进行iou计算,如果iou大于阈值,则判定这两个框预测的使同一个目标,则将这个框抑制掉,将此处的score置为0,

一直重复这个过程,知道选择出全部的目标。

4.在图像上画框

out_boxes, out_scores, out_classes = self.yolo_model.predict([image_data, input_image_shape])
        for i, c in list(enumerate(out_classes)):
            predicted_class = self.class_names[c]
            box = out_boxes[i]
            score = out_scores[i]

            top, left, bottom, right = box
            top = top - 5
            left = left - 5
            bottom = bottom + 5
            right = right + 5
            top = max(0, np.floor(top + 0.5).astype('int32'))
            left = max(0, np.floor(left + 0.5).astype('int32'))
            bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32'))
            right = min(image.size[0], np.floor(right + 0.5).astype('int32'))

            # 画框框
            label = '{} {:.2f}'.format(predicted_class, score)
            draw = ImageDraw.Draw(image)
            label_size = draw.textsize(label, font)
            label = label.encode('utf-8')
            print(label)

            if top - label_size[1] >= 0:
                text_origin = np.array([left, top - label_size[1]])
            else:
                text_origin = np.array([left, top + 1])

            for i in range(thickness):
          # 目标区域画框 draw.rectangle( [left
+ i, top + i, right - i, bottom - i], outline=self.colors[c])
       # text区域画框 draw.rectangle( [tuple(text_origin), tuple(text_origin
+ label_size)], fill=self.colors[c])
       # text区域写字(lable) draw.text(text_origin, str(label,
'UTF-8'), fill=(0, 0, 0), font=font)

 



 

posted @ 2020-12-09 22:52  learningcaiji  阅读(4111)  评论(0编辑  收藏  举报