В данной статье хочу рассказать про поиск объектов на видео с помощью Python и OpenCV. Помимо обычных видео, можно использовать и камеры.

Полный код и все исходники можно найти на моем Github.

Данный проект является продолжением моей предыдущей статьи - Поиск объектов на фото с помощью Python. Для того, чтобы не тратить много времени на ее изучение, я распишу весь процесс по новой.

Для того, чтобы написать легковесное приложение для обнаружения объектов на видео, установим необходимые библиотеки:

pip install opencv-python
pip install numpy
pip install art

Перейдем к написанию самого приложения, которое будет находить объекты на видео при помощи YOLO и отмечать их.

Скачаем с моего Github исходники и поместим в директорию Resources в проекте. Посмотрим, какие объекты сможет определять наша будущая программа:

'person', 'bicycle', 'car', 'motorbike', 'aeroplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
'elephant', 'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'sofa',
'pottedplant', 'bed', 'diningtable', 'toilet', 'tvmonitor', 'laptop', 'mouse', 'remote', 'keyboard',
'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors',
'teddy bear', 'hair drier', 'toothbrush'

Первым делом импортируем необходимые библиотеки:

import cv2
import numpy as np
from art import tprint

Напишем функции для применения YOLO. С ее помощью определяются самые вероятные классы объектов на изображении, а также координаты их границ, которые в дальнейшем будут использованы для отрисовки.

def apply_yolo_object_detection(image_to_process):
    """
    Recognition and determination of the coordinates of objects on the image
    :param image_to_process: original image
    :return: image with marked objects and captions to them
    """
height, width, _ = image_to_process.shape
blob = cv2.dnn.blobFromImage(image_to_process, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">1</span> / <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">255</span>, (<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">608</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">608</span>),
                             (<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>), swapRB=<span class="hljs-literal" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">True</span>, crop=<span class="hljs-literal" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">False</span>)
net.setInput(blob)
outs = net.forward(out_layers)
class_indexes, class_scores, boxes = ([] <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">for</span> i <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">in</span> range(<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">3</span>))
objects_count = <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>

<span class="hljs-comment" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(142, 144, 140); quotes: &quot;«&quot; &quot;»&quot;;"># Starting a search for objects in an image</span>
<span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">for</span> out <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">in</span> outs:
    <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">for</span> obj <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">in</span> out:
        scores = obj[<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">5</span>:]
        class_index = np.argmax(scores)
        class_score = scores[class_index]
        <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">if</span> class_score &gt; <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>:
            center_x = int(obj[<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>] * width)
            center_y = int(obj[<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">1</span>] * height)
            obj_width = int(obj[<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">2</span>] * width)
            obj_height = int(obj[<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">3</span>] * height)
            box = [center_x - obj_width // <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">2</span>, center_y - obj_height // <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">2</span>,
                   obj_width, obj_height]
            boxes.append(box)
            class_indexes.append(class_index)
            class_scores.append(float(class_score))

<span class="hljs-comment" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(142, 144, 140); quotes: &quot;«&quot; &quot;»&quot;;"># Selection</span>
chosen_boxes = cv2.dnn.NMSBoxes(boxes, class_scores, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0.0</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0.4</span>)
<span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">for</span> box_index <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">in</span> chosen_boxes:
    box_index = box_index
    box = boxes[box_index]
    class_index = class_indexes[box_index]

    <span class="hljs-comment" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(142, 144, 140); quotes: &quot;«&quot; &quot;»&quot;;"># For debugging, we draw objects included in the desired classes</span>
    <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">if</span> classes[class_index] <span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">in</span> classes_to_look_for:
        objects_count += <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">1</span>
        image_to_process = draw_object_bounding_box(image_to_process,
                                                    class_index, box)

final_image = draw_object_count(image_to_process, objects_count)
<span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">return</span> final_image

Добавим функцию, которая обведет найденные на изображении объекты с помощью координат границ, полученных из функции apply_yolo_object_detection:

def draw_object_bounding_box(image_to_process, index, box):
"""
Drawing object borders with captions
:param image_to_process: original image
:param index: index of object class defined with YOLO
:param box: coordinates of the area around the object
:return: image with marked objects
"""
x, y, w, h = box
start = (x, y)
end = (x + w, y + h)
color = (<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">255</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>)
width = <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">2</span>
final_image = cv2.rectangle(image_to_process, start, end, color, width)

start = (x, y - <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">10</span>)
font_size = <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">1</span>
font = cv2.FONT_HERSHEY_SIMPLEX
width = <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">2</span>
text = classes[index]
final_image = cv2.putText(final_image, text, start, font,
                          font_size, color, width, cv2.LINE_AA)

<span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">return</span> final_image

Помимо отрисовки объектов, можно добавить вывод их количества. Напишем для этого еще одну функцию:

def draw_object_count(image_to_process, objects_count):
"""
Signature of the number of found objects in the image
:param image_to_process: original image
:param objects_count: the number of objects of the desired class
:return: image with labeled number of found objects
"""
start = (<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">10</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">120</span>)
font_size = <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">1.5</span>
font = cv2.FONT_HERSHEY_SIMPLEX
width = <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">3</span>
text = <span class="hljs-string" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(113, 140, 0); quotes: &quot;«&quot; &quot;»&quot;;">"Objects found: "</span> + str(objects_count)

<span class="hljs-comment" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(142, 144, 140); quotes: &quot;«&quot; &quot;»&quot;;"># Text output with a stroke</span>
<span class="hljs-comment" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(142, 144, 140); quotes: &quot;«&quot; &quot;»&quot;;"># (so that it can be seen in different lighting conditions of the picture)</span>
white_color = (<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">255</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">255</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">255</span>)
black_outline_color = (<span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>, <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">0</span>)
final_image = cv2.putText(image_to_process, text, start, font, font_size,
                          black_outline_color, width * <span class="hljs-number" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; color: rgb(245, 135, 31); quotes: &quot;«&quot; &quot;»&quot;;">3</span>, cv2.LINE_AA)
final_image = cv2.putText(final_image, text, start, font, font_size,
                          white_color, width, cv2.LINE_AA)

<span class="hljs-keyword" style="transition: opacity 0.2s ease-in-out 0s, color 0.2s ease-in-out 0s, text-decoration 0.2s ease-in-out 0s, background-color 0.2s ease-in-out 0s, -webkit-text-decoration 0.2s ease-in-out 0s; font-weight: 700; color: rgb(137, 89, 168); quotes: &quot;«&quot; &quot;»&quot;;">return</span> final_image</code></pre><!--EndFragment-->


Напишем функцию, которая будет обрабатывать видео по кадрам и выводить результат обработки на экран:

def start_video_object_detection(video: str):
    """
    Real-time video capture and analysis
    """

    while True:
        try:
            # Capturing a picture from a video
            video_camera_capture = cv2.VideoCapture(video)
            
            while video_camera_capture.isOpened():
                ret, frame = video_camera_capture.read()
                if not ret:
                    break
                
                # Application of object recognition methods on a video frame from YOLO
                frame = apply_yolo_object_detection(frame)
                
                # Displaying the processed image on the screen with a reduced window size
                frame = cv2.resize(frame, (1920 // 2, 1080 // 2))
                cv2.imshow("Video Capture", frame)
                cv2.waitKey(1)
            
            video_camera_capture.release()
            cv2.destroyAllWindows()
    
        except KeyboardInterrupt:
            pass

Чтобы не нагружать устройство обработкой каждого кадра, можно добавить обновление экрана по нажатии любой клавиши:

def start_video_object_detection(video: str):
    """
    Real-time video capture and analysis
    """

    while True:
        try:
            # Capturing a picture from a video
            video_camera_capture = cv2.VideoCapture(video)
            
            while video_camera_capture.isOpened():
                ret, frame = video_camera_capture.read()
                if not ret:
                    break
                
                # Application of object recognition methods on a video frame from YOLO
                frame = apply_yolo_object_detection(frame)
                
                # Displaying the processed image on the screen with a reduced window size
                frame = cv2.resize(frame, (1920 // 2, 1080 // 2))
                cv2.imshow("Video Capture", frame)
                cv2.waitKey(0):
                		break
            
            video_camera_capture.release()
            cv2.destroyAllWindows()
    
        except KeyboardInterrupt:
            pass

Теперь напишем функцию main, где будем передавать аргументы в функции.

Данный блок не является обязательным, но я захотел сделать красивый вывод текста в консоль:

# Logo
    tprint("Object detection")
    tprint("by")
    tprint("paveldat")

Создадим функцию main, в которой настроим нашу сеть:

if __name__ == '__main__':
		# Loading YOLO scales from files and setting up the network
    net = cv2.dnn.readNetFromDarknet("Resources/yolov4-tiny.cfg",
                                     "Resources/yolov4-tiny.weights")
    layer_names = net.getLayerNames()
    out_layers_indexes = net.getUnconnectedOutLayers()
    out_layers = [layer_names[index - 1] for index in out_layers_indexes]

    # Loading from a file of object classes that YOLO can detect
    with open("Resources/coco.names.txt") as file:
        classes = file.read().split("\n")

    # Determining classes that will be prioritized for search in an image
    # The names are in the file coco.names.txt

    video = input("Path to video (or URL): ")
    look_for = input("What we are looking for: ").split(',')
    
    # Delete spaces
    list_look_for = []
    for look in look_for:
        list_look_for.append(look.strip())

    classes_to_look_for = list_look_for

    start_video_object_detection(video)

Программа будет запрашивать путь до видео и объекты, которые хотим найти. Вместо пути до видео можно использовать ссылку на видео с камеры. Объекты должны перечисляться через запятую, если их несколько.

Запускаем программу и тестируем.

Path to video (or URL): Result/input/example.mp4
What we are looking for: person, car, bus

Исходное видео:

Обработанное видео:

Мы проверили, как алгоритм YOLO справился с тестам. Погрешность все же есть, но в основном программа успешно находит необходимые объекты.

Комментарии (4)


  1. petlen1
    29.07.2022 13:58
    -1

    Хоть кто-то найдет второй потерянный носок)


  1. slog2
    30.07.2022 11:12

    Какие вычислительные мощности нужны для этого? Сколько fps можно выжать с Raspberry Pi 4?


    1. Pavel_Dat Автор
      30.07.2022 11:33

      Чем больше, тем лучше. Про Raspberry не могу сказать


  1. andeytihonov78
    30.07.2022 11:31
    -3

    Удачная находка для госслужб)