首页 > 解决方案 > 如何准确检索使用 TensorFlow 对象检测 API 检测到的对象的边界框?

问题描述

我试图了解如何在检测到对象时找到边界框的位置。我使用 Tensorflow 对象检测 API 来检测盒子中的鼠标。只是为了测试如何检索边界框坐标的目的,当检测到鼠标时,我想在它的头上方打印“这是一只鼠标”。然而,我的目前打印出几英寸的偏差。例如,这是我的对象检测视频的屏幕截图。

截屏

这是相关的代码片段:

with detection_graph.as_default():
with tf.Session(graph=detection_graph) as sess:
    start = time.time()
    while True:

        # Read frame from camera
        ret, image_np = cap.read()

        cv2.putText(image_np, "Time Elapsed: {}s".format(int(time.time() - start)), (50,50),cv2.FONT_HERSHEY_PLAIN,3, (0,0,255),3)
        # Expand dimensions since the model expects images to have shape: [1, None, None, 3]
        image_np_expanded = np.expand_dims(image_np, axis=0)
        # Extract image tensor
        image_tensor = detection_graph.get_tensor_by_name('image_tensor:0')
        # Extract detection boxes
        boxes = detection_graph.get_tensor_by_name('detection_boxes:0')
        # Extract detection scores
        scores = detection_graph.get_tensor_by_name('detection_scores:0')
        # Extract detection classes
        classes = detection_graph.get_tensor_by_name('detection_classes:0')
        # Extract number of detectionsd
        num_detections = detection_graph.get_tensor_by_name(
            'num_detections:0')
        # Actual detection.
        (boxes, scores, classes, num_detections) = sess.run(
            [boxes, scores, classes, num_detections],
            feed_dict={image_tensor: image_np_expanded})
        # Visualization of the results of a detection.
        vis_util.visualize_boxes_and_labels_on_image_array(
            image_np,
            np.squeeze(boxes),
            np.squeeze(classes).astype(np.int32),
            np.squeeze(scores),
            category_index,
            use_normalized_coordinates=True,
            line_thickness=8)

        for i, b in enumerate(boxes[0]):
            if classes[0][i] == 1:
                if scores[0][i] >= .5:
                    mid_x = (boxes[0][i][3] + boxes[0][i][1]) / 2
                    mid_y = (boxes[0][i][2] + boxes[0][i][0]) / 2


                    cv2.putText(image_np, 'FOUND A MOUSE', (int(mid_x*600), int(mid_y*800)), cv2.FONT_HERSHEY_PLAIN, 2, (0,255,0), 3)

        # Display output
        cv2.imshow(vid_name, cv2.resize(image_np, (800, 600)))

        #Write to output
        video_writer.write(image_np)

        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break


    cap.release()
    cv2.destroyAllWindows()

我不太清楚它是如何boxes工作的。有人可以向我解释这一行吗:mid_x = (boxes[0][i][3] + boxes[0][i][1]) / 2?我知道 3 和 1 索引代表x_min, x_max,但我不确定为什么我只遍历 box[0] 以及i代表什么。

解决方案正如 ievbu 建议的那样,我需要将中点计算从其标准化值转换为帧的值。我找到了一个 cv2 函数,它返回宽度和高度,并使用这些值将我的中点转换为像素位置。

frame_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
frame_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))

...
cv2.putText(image_np, '.', (int(mid_x*frame_w), int(mid_y*frame_h)), cv2.FONT_HERSHEY_PLAIN, 2, (0,255,0), 3)

标签: pythonopencvtensorflow

解决方案


框以更高的维度返回,因为您可以提供多个图像,然后该维度将代表每个单独的图像(对于一个输入图像,您使用 扩展维度np.expand_dims)。您可以看到,为了可视化,它已被删除,如果您只处理 1 个图像np.squeeze,您可以手动删除它。表示 box 数组中 box 的索引,您需要该索引来访问您分析的 box 的类和分数。boxes[0]i

文本位置不正确,因为返回的框坐标已标准化,您必须将它们转换为匹配完整图像大小。以下是如何转换它们的示例:

(im_width, im_height, _) = frame.shape
xmin, ymin, xmax, ymax = box
(xmin, xmax, ymin, ymax) = (xmin * im_width, xmax * im_width,
                            ymin * im_height, ymax * im_height)

推荐阅读