python - 如何检测物体球(使用opencv跟踪)是否通过给定区域
问题描述
我正在尝试开发一个桌上足球游戏分析应用程序。我能够使用基于 opencv 颜色的跟踪来跟踪球。真正的问题是目标检测。可能的解决方案是 - 如果球通过球门上的标记区域,并且球在很长一段时间内从桌子上消失,则可以将其视为进球,并且应增加进球计数器。
我在 github 和 stackoverflow 上浏览了很多代码,但无法正确实现需求。
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 = (29, 86, 6)
greenUpper = (64, 255, 255)
pts = deque(maxlen=args["buffer"])
counter = 0
(dX, dY) = (0, 0)
direction = ""
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.line(frame,(10,135),(10,225),(255,0,0),7)
cv2.line(frame,(625,140),(625,230),(255,0,0),7)
cv2.putText(frame, str(match_score[0]) + " - " + str(match_score[1]), (260, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (120, 255, 50), 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:
# draw the circle and centroid on the frame,
# then update the list of tracked points
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
if counter >= 10 and i == 1 and pts[-10] is not None:
dX = pts[-10][0] - pts[i][0]
dY = pts[-10][1] - pts[i][1]
(dirX, dirY) = ("", "")
thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5)
cv2.line(frame, pts[i - 1], pts[i], (0, 0, 255), thickness)
cv2.putText(frame, direction, (10, 30), cv2.FONT_HERSHEY_SIMPLEX,
0.65, (0, 0, 255), 3)
cv2.putText(frame, "dx: {}, dy: {}".format(dX, dY),
(10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX,
0.5, (0, 0, 255), 1)
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/file/d/1Y7Dzzfx_V0fsDZRZAC4d0MuEpSnKnodI/view?usp=sharing https://drive.google.com/file/d/1jazU_-tdp9e-nALTqT04_U_8gj8rovSL/view?usp=sharing
python trackball.py --video test3.mp4
我完全愿意接受新的建议!
解决方案
使用投票算法来确定是否进球。在图像中找到目标的位置。如果球的跟踪位置在球门内,则增加票数。如果一个目标有几票,则计算该目标。
这种投票方法将有助于消除错误的跟踪值。
# Find the ball position (an x,y coordinate)
x, y = ball_position
# Find the goal position (a rectangle)
goal_x, goal_y, width, height = 0, 400, 50, 170
# Is the ball inside the goal?
if x>goal_x and p<goal_x+width and y>goal_y and y<goal_y+height: votes += 1
else: votes -= .1
if votes < 0: votes = 0
if votes > 7: print('goal!')
推荐阅读
- php - 如何使用 php cleandata 和 sanitize 函数从 HTML 表单中成功插入记录
- amazon-web-services - 使用 AWS CLI 将文件从本地上传到 s3,无需硬编码凭证(访问 ID 和秘密访问密钥)
- php - 循环直到请求响应消息等于php中的“true”
- reactjs - 为什么命名函数作为第一个参数传递给 useEffect 不是必要的依赖项?
- c++ - 如何在 C++ 中检查对象的类型(它们属于哪个类)
- tensorflow - tiny-yolo-v3 在 GPU 上的推理时间
- c# - ASP.Net XUnit 检查对象列表是否包含特定对象
- jmeter - Jmeter - 使用变量:从 JDBC 请求到 JSR223 PostProcessor
- google-cloud-functions - 可调用的 HTTPS 函数和带参数的 HTTPS 函数有什么区别?
- php - 修改值时,array_walk 未按预期工作