首页 > 解决方案 > 如何在增加值后停止循环 x 秒

问题描述

我正在做一个足球游戏分析项目。项目目标包括跟踪球,检测和增加双方的目标。我使用颜色跟踪来跟踪球。我还尝试制作一种算法来检测球是否通过了特定的线或矩形(目标区域)并增加计数器。但它有时会增加多个目标。不知何故,只有目标检测代码应该在目标增加后停止执行 3 秒。我是 或其他任何让代码工作的东西。我尝试使用 break/continue/time.sleep(s) 但不知道该怎么做。如果有人可以查看我的代码并告诉我哪里出错了。

from collections import deque
from imutils.video import VideoStream
import numpy as np
import argparse
import cv2
import imutils
import time
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",
    help="path to the (optional) video file")
ap.add_argument("-b", "--buffer", type=int, default=64,
    help="max buffer size")
args = vars(ap.parse_args())
match_score = (0, 0)
greenLower = (36, 25, 25)
greenUpper = (70, 255,255)
pts = deque(maxlen=args["buffer"])
counter = 0
x=0
y=0
if not args.get("video", False):
    vs = VideoStream(src=1).start()
else:
    vs = cv2.VideoCapture(args["video"])
time.sleep(2.0)
while True:
    frame = vs.read()
    frame = frame[1] if args.get("video", False) else frame
    if frame is None:
        break
    frame = imutils.resize(frame, width=640, height=480)
    blurred = cv2.GaussianBlur(frame, (11, 11), 0)
    hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv, greenLower, greenUpper)
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)
    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    center = None
    cv2.rectangle(frame,(0,0),(640,360),(0,255,255),7)
    cv2.rectangle(frame,(8,135),(14,225),(255,0,0),2)
    cv2.rectangle(frame,(623,140),(630,230),(255,0,0),2)
    if len(cnts) > 0:
        c = max(cnts, key=cv2.contourArea)
        ((x, y), radius) = cv2.minEnclosingCircle(c)
        M = cv2.moments(c)
        center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
        if radius > 5:
            cv2.circle(frame, (int(x), int(y)), int(radius),
                (0, 255, 255), 2)
            cv2.circle(frame, center, 5, (0, 0, 255), -1)
    pts.appendleft(center)
    for i in range(1, len(pts)):
        if pts[i - 1] is None or pts[i] is None:
            continue
        thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5)
        cv2.line(frame, pts[i - 1], pts[i], (0, 0, 255), thickness)

    for i in range(1, len(pts)):
        if pts[i - 1] == pts[i] :
            if (8 < x < 14 and 135 < y < 225) :
                match_score = (match_score[0] + 1, match_score[1])
                break
            if (623 < x < 630 and 140 < y < 230) :
                match_score = (match_score[0], match_score[1] + 1)
                break
    cv2.putText(frame, "dx: {}, dy: {}".format(dX, dY),
    (10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX,
    0.5, (0, 0, 255), 1)

    cv2.putText(frame, str(x) + " , " + str(y),
        (10, frame.shape[0] - 20), cv2.FONT_HERSHEY_SIMPLEX,
        0.5, (0, 0, 255), 1)

    cv2.putText(frame, str(match_score[0]) + " - " + str(match_score[1]), (260, 60), 
        cv2.FONT_HERSHEY_SIMPLEX, 1, (120, 255, 50), 2)
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF
    counter += 1
    if key == ord("q"):
        break
if not args.get("video", False):
    vs.stop()
else:
    vs.release()
cv2.destroyAllWindows()

在这里测试和工作是我们桌上足球的一些视频剪辑。此剪辑包含正确检测到的右侧球门 https://drive.google.com/open?id=1Y7Dzzfx_V0fsDZRZAC4d0MuEpSnKnodI

这是一个有多个目标的剪辑,如果这段视频的代码运行良好,那么我可以实时进行。https://drive.google.com/open?id=1vtUjw2jpDHvAvo4jI_W1UpJWPT1jYWGr

我也对任何其他可以满足我项目目标的技术/算法持开放态度。

标签: pythonloopsopencv

解决方案


停止运行x几秒钟适用于实时视频流,但不适用于预先录制的视频。在后者中,您可能希望将固定时间替换为通过的帧数,具体取决于帧速率。

也就是说,您可以last_goal_time像这样实现时间标志:

from datetime import datetime, timedelta

# initialization at beginning of code
last_goal_time = datetime.now()

# inside the while loop
while True:
    current_time = datetime.now()

    # check for time difference, if less than 3 seconds, continue
    # you may want to grab the frame before this
    if (current_time - last_goal_time).total_seconds() < 3:
        continue

    # 3 seconds passed
    frame = vs.read()

    ### other code goes here

    # here I guess when goal detected
    for i in range(1, len(pts)):
        if pts[i - 1] == pts[i] :
            # update last_goal_time
            last_goal_time = current_time

            # rest of code is unchanged
            if (8 < x < 14 and 135 < y < 225) :
                match_score = (match_score[0] + 1, match_score[1])
                break
            if (623 < x < 630 and 140 < y < 230) :
                match_score = (match_score[0], match_score[1] + 1)
                break

推荐阅读