python-3.x - 如何实时跟踪视频中两个对象相交的时间?
问题描述
我正在制作一个刷牙应用程序,我想在其中跟踪一个人刷牙的时间。为此,我构建了一个牙刷跟踪器,一个口腔跟踪器,还开发了一个算法来确定牙刷是否在嘴里(我假设这意味着这个人正在刷牙)。
现在,我只需要添加一个计时器,它可以实时计算人们刷牙的时间,并将其显示在视频源上。如果用户暂停刷牙,定时器也应该暂停;如果用户恢复刷牙,定时器也应该恢复。我怎么做这个?
我检测何时刷牙的逻辑如下:
- 提取牙刷边界框的顶点
- 提取嘴巴的最左、最上、最右和最下点,并提取它们的坐标
- 找出这两个矩形是否重叠(我正在使用一个名为的库
shapely
- 如果您有一个不需要使用库的更原始的解决方案,那就太好了) - 如果它们重叠,则启动计时器;如果不是,请暂停计时器。这是我无法弄清楚如何做的步骤,以及我需要帮助的地方。
这大致是我的代码的样子:
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))
解决方案
答案还将包含一些干净的代码建议,您在最终实现它时可能会忽略这些建议。但我想向您展示我的首选方式。因此,您将需要 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
根据需要使用此值。
推荐阅读
- redux - 从reduxjs通过调度和getstate后反应HOC组件不起作用
- haskell - 模式同义词签名:必需与提供的约束
- spring-boot - Jasypt en/decrypt 成功 生产失败
- python - 如何为 ecs_patterns.ApplicationLoadBalancedFargateService 自定义监听器规则
- mysql - 无法使用 Internet 连接到 AWS RDS MySQL 数据库 - 但热点有效
- iphone - Charles 代理 - 无法启用 SSL 代理(查看分析日志)
- angular - Ngx-datatable 不显示数据
- microsoft-graph-api - Microsoft Graph Explorer 中的列表标签需要哪些权限?
- firefox - 我可以忽略 Firefox DevTools SameSite cookie 属性警告吗?
- python - 如何将 input() 发送到用户可以访问和更改的文件?