Python YOLOv4人体检测如何按1分钟首次、后每3分钟打印结果?
问题原因
你用schedule模块的思路完全不对,schedule是基于操作系统的实际运行时间调度任务的,你需要的是按照视频自身的时间轴节点打印检测结果,两者逻辑完全不匹配,而且你把整个视频处理函数传给schedule调度,会导致重复执行整个视频检测流程,当然达不到预期。
解决思路
直接通过视频帧率和当前已处理的帧数计算当前对应的视频时间点,按规则判断是否需要打印即可,不需要引入额外的调度模块。打印规则逻辑:
- 第一个打印节点为视频时间1分钟(60秒)
- 之后每间隔3分钟(180秒)触发一次打印
- 每次触发打印后更新下一个打印节点的时间,避免重复打印同一节点
修正后完整代码
from imutils.video import VideoStream from imutils.video import FPS import numpy as np import argparse import imutils import time import cv2 from collections import OrderedDict import matplotlib.pyplot as plt import datetime file = "test2" input_path = "C:/Users/asmita.nandi/Downloads/" + file + ".mp4" output_path = "C:/Users/asmita.nandi/Downloads/" + file + ".avi" net = cv2.dnn.readNet("C:/Users/asmita.nandi/Downloads/custom-yolov4-tiny_human-608 (1).cfg", "C:/Users/asmita.nandi/Downloads/custom-yolov4-tiny-detector_human.weights") labelsPath = "C:/Users/asmita.nandi/Downloads/human_label.txt" def event(input, output, net, labelsPath): LABELS = open(labelsPath).read().strip().split("\n") np.random.seed(1) cmap = plt.get_cmap('tab20b') colors = [cmap(i)[:3] for i in np.linspace(0, 1, 6)] CONF_THRESH, NMS_THRESH = 0.25, 0.25 vs = cv2.VideoCapture(input) fp = vs.get(cv2.CAP_PROP_FPS) writer = None W = None H = None totalFrames = 0 TotalHuman = 0 # 新增:打印时间控制变量,首次打印在60秒(1分钟),之后每隔180秒(3分钟)打印 next_print_time = 60 # 新增:初始化FPS计数器,修复原代码未初始化的bug fps = FPS().start() while True: frame = vs.read() frame = frame[1] if input else frame if input is not None and frame is None: break (H, W) = frame.shape[:2] if W is None or H is None: (H, W) = frame.shape[:2] if output is not None and writer is None: fourcc = cv2.VideoWriter_fourcc(*"MJPG") writer = cv2.VideoWriter(output, fourcc, fp, (W, H), True) ln = net.getLayerNames() ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()] blob = cv2.dnn.blobFromImage(frame, 1 / 255.0, (608, 608), swapRB=True, crop=False) net.setInput(blob) layerOutputs = net.forward(ln) boxes = [] confidences = [] classIDs = [] (H, W) = frame.shape[:2] # 循环处理检测结果 for output in layerOutputs: for detection in output: scores = detection[5:] classID = np.argmax(scores) confidence = scores[classID] if confidence > CONF_THRESH: box = detection[0:4] * np.array([W, H, W, H]) (centerX, centerY, width, height) = box.astype("int") x = int(centerX - (width / 2)) y = int(centerY - (height / 2)) boxes.append([x, y, int(width), int(height)]) confidences.append(float(confidence)) classIDs.append(classID) idxs = cv2.dnn.NMSBoxes(boxes, confidences, CONF_THRESH, NMS_THRESH) human_count = 0 if len(idxs) > 0: for i in idxs.flatten(): (x, y) = (boxes[i][0], boxes[i][1]) (w, h) = (boxes[i][2], boxes[i][3]) color = colors[classIDs[i]] color = [i * 255 for i in color] class_name = LABELS[classIDs[i]] cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2) cv2.putText(frame, class_name, (x, y - 10), 0, 0.5, color, 2) # 统计当前帧人类数量 if class_name == "Human": human_count += 1 # 新增:判断是否到打印时间点 current_video_time = totalFrames / fp if current_video_time >= next_print_time: print(f"检测到的人数:{human_count}") # 更新下一个打印时间点 next_print_time += 180 if writer is not None: writer.write(frame) key = cv2.waitKey(1) & 0xFF if key == ord("q"): break totalFrames += 1 fps.update() fps.stop() print("[INFO] elapsed time: {:.2f}".format(fps.elapsed())) print(f"总处理帧数:{totalFrames}") if writer is not None: writer.release() if not input: vs.stop() else: vs.release() cv2.destroyAllWindows() # 直接运行检测函数,不需要schedule调度 event(input_path, output_path, net, labelsPath)
修改点说明
- 移除了所有schedule相关的导入和调度代码,避免逻辑冲突
- 新增打印时间控制变量,根据视频时间轴节点触发打印,完全符合你要求的1分钟首次打印、之后每隔3分钟打印的规则
- 修正了原代码的缩进错误(原代码中NMS处理、帧写入、按键检测等逻辑的缩进全部错误,导致无法正常运行)
- 修正了FPS未初始化的bug
- 修正了人数统计的逻辑错误,现在可以正确统计单帧内的人类数量
- 保留了原有的检测、画框、视频输出的全部逻辑,仅调整了打印规则
内容的提问来源于stack exchange,提问作者Asmita Nandi
相关产品推荐
相关产品推荐

