目標檢測——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)

 

 
        
 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM