Как точно получить ограничивающую рамку для объекта, обнаруженного с помощью API Tensorflow Object Detection? - PullRequest
0 голосов
/ 17 июня 2019

Я пытаюсь понять, как найти местоположение ограничительной рамки при обнаружении объекта. Я использовал Tensorflow Object Detection API для обнаружения мыши в окне. Просто для проверки того, как получить координаты ограничивающего прямоугольника, когда мышь обнаружена, я хочу напечатать «ЭТО МЫШЬ» прямо над ее головой. Тем не менее, моя в настоящее время печатает несколько дюймов вне килтера Например, вот скриншот из видео моего обнаружения объекта.

screenshot

Вот соответствующий фрагмент кода:

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, но я не уверен, почему я перебираю только блоки [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)

1 Ответ

0 голосов
/ 18 июня 2019

Ящики возвращаются в более высоком измерении, потому что вы можете дать несколько изображений, и тогда это измерение будет представлять каждое отдельное изображение (для одного входного изображения вы расширяете измерение с помощью np.expand_dims). Вы можете видеть, что для визуализации он удаляется с помощью np.squeeze, и вы можете удалить его вручную, просто взяв boxes[0], если обрабатываете только 1 изображение. 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...