首页 > 解决方案 > 如何实时跟踪视频中两个对象相交的时间?

问题描述

我正在制作一个刷牙应用程序,我想在其中跟踪一个人刷牙的时间。为此,我构建了一个牙刷跟踪器,一个口腔跟踪器,还开发了一个算法来确定牙刷是否在嘴里(我假设这意味着这个人正在刷牙)。

现在,我只需要添加一个计时器,它可以实时计算人们刷牙的时间,并将其显示在视频源上。如果用户暂停刷牙,定时器也应该暂停;如果用户恢复刷牙,定时器也应该恢复。我怎么做这个?

我检测何时刷牙的逻辑如下:

这大致是我的代码的样子:

from shapely.geometry import Polygon
import cv2, face_recognition, time

brush_time = 0
video_capture = cv2.VideoCapture(0)

while True:
    ret, frame = video_capture.read()

    '''
    Code for extracting the toothbrush's coordinates (using Yolo),
    and the mouth's coordinates (using the face_recognition library)
    ...
    ...
    ...
    '''

    p1 = Polygon([(mouth_left_x, mouth_left_y), (mouth_top_x, mouth_top_y), (mouth_right_x, mouth_right_y), (mouth_bottom_x, mouth_bottom_y)])
    p2 = Polygon([(brush_top_left_x, brush_top_left_y), (brush_top_right_x, brush_top_right_y), (brush_bottom_left_x, brush_bottom_left_y), (brush_bottom_right_x, brush_bottom_right_y)])

    if p1.intersects(p2):
        
        ##############################################
        # This is where I want the timer logic to be #
        # start_time = time.time()                   #
        # end_time = ????                            #
        ##############################################

        brush_time = end_time - start_time
        text = 'Brushed teeth for {} seconds'.format(str(brush_time))

标签: python-3.xopencvdeep-learningcomputer-visionface-recognition

解决方案


答案还将包含一些干净的代码建议,您在最终实现它时可能会忽略这些建议。但我想向您展示我的首选方式。因此,您将需要 2 个辅助类。第一类的职责是给我们一个布尔值来判断这个人是否在刷牙。尝试仅在此类中封装重叠的矩形逻辑等。为了简单起见,我将对随机刷入和刷出持续时间进行硬编码。

class BrushDetector:
    def is_brushing(self, curr_frame_idx: int, frame) -> bool:
        """
        You provide the implementation here to detect whether the individual is holding brush inside his/her mouth.
        For sake of simplicity, I will simply hard-code the time when this shall return true in the attached video.
        """
        if 50 < curr_frame_idx < 100:
            return True
        if 150 < curr_frame_idx < 200:
            return True
        if 250 < curr_frame_idx < 300:
            return True
        return False

现在我们建立另一个记录刷入和刷出实例的类。这个类的职责是为我们提供总刷机时间。这个类的逻辑可以构建为:

import datetime

class BrushRecorder:
    def __init__(self):
        self._start_time_ms = None
        self._total_time_ms = datetime.timedelta(0, 0, 0, 0, 0, 0, 0)

    def register_brush_in(self):
        if self._start_time_ms is None:
            self._start_time_ms = datetime.datetime.now()

    def register_brush_out(self):
        if self._start_time_ms is None:
            return

        delta = datetime.datetime.now() - self._start_time_ms
        self._total_time_ms += delta
        self._start_time_ms = None

    def get_brushing_time(self):
        if self._start_time_ms is None:
            return self._total_time_ms.microseconds / 1000
        else:
            return (self._total_time_ms + datetime.datetime.now() - self._start_time_ms).microseconds / 1000

现在我们已经构建了两个核心类。让我们进入图像读取部分并尝试将所有部分整合在一起。

if __name__ == "__main__":
    video_stream = cv2.VideoCapture("path/to/stream/brush.mp4")
    recorder = BrushRecorder()
    detector = BrushDetector()
    frame_idx = 0
    while video_stream.isOpened():
        ret, frame = video_stream.read()
        if not ret:
            break

        if detector.is_brushing(frame_idx, frame):
            recorder.register_brush_in()
        else:
            recorder.register_brush_out()
        brushing_time = recorder.get_brushing_time()
        print(frame_idx, brushing_time)
        frame_idx += 1
    video_stream.release()

在上面的代码片段中,我刚刚将刷机时间记录到控制台,但您也可以cv2.putText在每一帧上使用 GUI 或brushing_time根据需要使用此值。


推荐阅读