大佬教程收集整理的这篇文章主要介绍了有没有办法可以计算 OpenCV 中球的反弹?,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我使用本指南制作了一个球跟踪程序:https://www.pyimagesearch.com/2015/09/14/ball-tracking-with-opencv/
我想问一下,是否有一种方法可以告诉我某个球在特定时间内反弹了多少次。甚至任何我可以用来计算球在地面上的反弹次数的方法,因为我打算使用该程序来跟踪进行篮球运球训练的人。提前谢谢你:)
我想做类似的事情:https://youtu.be/OMXYvkryF1I at 2:26
如果有帮助,这是我的代码:
# import the necessary packages from collections import deque #List like data structure will keep prev positions of ball #can make a Trail of the ball from it import numpy as np import argparse import imutils #this is that guys List of Opencv stuff he uses - got resizing and all - can use pip to get it #$ pip install --upgrade imutils import cv2 import time # construct the argument parse and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-v","--vIDeo",Help="C:/Object_detection/models-master/research/object_detection/test_images/multi_angle.mp4") #can put path to vIDeo here. That is if it is there #if not there the program will just use the webcam ap.add_argument("-b","--buffer",type=int,default=64,Help="max buffer size") # this tells max size of deque which is the List with points args = vars(ap.parse_args()) ##Put lower & upper boundarIEs of colour #colourLow = (0,135,30) #colourHigh = (19,255,255) #Put lower & upper boundarIEs of colour colourLow = (0,30) colourHigh = (19,255) pts = deque(maxlen=args["buffer"]) #initialises our deque points # if a vIDeo path was not supplIEd,grab the reference # to the webcam # item that tells if we using a vIDeo or webcam if not args.get("vIDeo",falsE): cap = cv2.VIDeoCapture(0) #imutils.VIDeo stream item works good with webcam # otherwise,grab a reference to the vIDeo file else: cap = cv2.VIDeoCapture(args["vIDeo"]) #this is if the vIDeo is supplIEd #Loop for vIDeo frame capturing while True: #calls the read method in our capture module ret,frame = cap.read() #if we were running a vIDeo from external source and no other frame was taken again for processing #it means we reached end of vIDeo so we break out of loop if frame is None: break frame = imutils.resize(frame,wIDth=800) #smaller frames means faster processing so we resize blurred = cv2.GaussianBlur(frame,(11,11),0) #blur reduces picture noise to allow us to see stuff more clearly hsv = cv2.cvtcolor(frame,cv2.color_BGR2HSV) # converTing frame to HSV # we Now masking to get the desired colour only # we do erosion,dilation and removal of blobs mask = cv2.inRange(hsv,colourLow,colourHigh) #locates our object in the frame mask = cv2.erode(mask,None,iterations=2) #erosion mask = cv2.dilate(mask,iterations=2) #removal of blobs # Will draw outline of ball and find (x,y) center of ball cnts = cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2] #this makes sure contour will work on all opencv items center = None #make the coords of the ball 0 at first if len(cnts) > 0: # only proceed if at least one contour was found # finds largest contour mask,then uses this to get minimum enclosing circle and center 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"])) #this & above line get centre coords # only proceed if the radius meets a minimum size if (radius > 30): # draw the circle and centroID on the frame,# then @R_801_9531@e the List of tracked points cv2.circle(frame,(int(X),int(y)),int(radius),(0,255),2) cv2.circle(frame,center,5,-1) # @R_801_9531@e List of points pts.appendleft(center) # loop over set of points for i in range(1,len(pts)): #if we don't have tracked points we should ignore them if pts[i - 1] is None or pts[i] is None: conTinue ickk = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5) def drawline(img,pt1,pt2,color,thickness=ickk,style='dotted',gap=20): dist =((pt1[0]-pt2[0])**2+(pt1[1]-pt2[1])**2)**.5 pts= [] for i in np.arange(0,dist,gap): r=i/dist x=int((pt1[0]*(1-r)+pt2[0]*r)+.5) y=int((pt1[1]*(1-r)+pt2[1]*r)+.5) p = (x,y) pts.append(p) if style=='dotted': for p in pts: cv2.circle(img,p,thickness,-1) else: s=pts[0] e=pts[0] i=0 for p in pts: s=e e=p if i%2==1: cv2.line(img,s,e,thickness) i+=1 #if we do we will draw point connecTing line #gotta define the thickness first thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5) #cv2.line(frame,pts[i - 1],pts[i],thickness) drawline(frame,thickness) # show the frame to our screen cv2.imshow("Frame",framE) key = cv2.waitKey(1) & 0xFF # if the 'q' key is pressed,stop the loop if key == ord("q"): break # cleanup the camera and close any open windows cap.release() cv2.destroyAllwindows()
@H_618_13@解决方法
我设置了一个模拟来展示我在评论中所说的内容。基本上,每次相机拍照时(无论您的相机以何种 fps 运行),您都可以获得球的位置。使用该位置,您可以估计速度(位置变化除以时间)。如果该速度的方向突然发生变化,那么您可以将其视为反弹。
此代码的绝大部分用于设置模拟,出于您的目的可以安全地忽略。这是相关的代码块
# check if it's time for a snapshot camera_timer += dt; # time since last snapshot if camera_timer > (1.0 / camera_fps): # estimate velocity est_vel[0] = (ball_pos[0] - prev_pos[0]) / camera_timer; est_vel[1] = (ball_pos[1] - prev_pos[1]) / camera_timer; # check if the sign of the velocity has changed if sign(est_vel[0]) != sign(prev_est_vel[0]) or sign(est_vel[1]) != sign(prev_est_vel[1]): # check for bounces from large change in velocity dvx = abs(est_vel[0] - prev_est_vel[0]); dvy = abs(est_vel[1] - prev_est_vel[1]); change_vel = math.sqrt(dvx*dvx + dvy*dvy); if change_vel > bounce_thresh: bounce_count += 1; # @R_801_9531@e previous state trackers prev_est_vel = est_vel[:]; prev_pos = ball_pos[:]; # reset camera timer camera_timer = 0; snap = True;
@H_618_13@如果您想自己玩模拟游戏,这就是全部内容
import cv2 import numpy as np import time import math # get mouse click click_pos = None; click = false; def mouseClick(event,x,y,flags,param): # hook to globals global click_pos; global click; # check for left mouseclick if event == cv2.EVENT_LBUTTONDOWN: click = True; click_pos = (x,y); # return sign of number def sign(val): if val > 0: return 1; if val < 0: return -1; return 0; # create blank image res = (600,600,3); bg = np.zeros(res,np.uint8); display = np.zeros(res,np.uint8); # set up click callBACk cv2.namedWindow("Display"); cv2.setMouseCallBACk("Display",mouseClick); click_force = 1000; # font stuff font = cv2.FONT_HERSHEY_SIMPLEX; fontScale = 1; fontColor = (255,100,0); thickness = 2; # make a ball ball_radius = 20; ball_pos = [300,300]; ball_vel = [0,0]; # set physics drag = 0.98; bounce_mult = 0.95; grav = -9.8; # acceleration in pixels per second time_scale = 5.0; # register click animations click_anims = []; anim_dur = 0.25; # seconds anim_radius = 20; # pixels # track bounces prev_pos = ball_pos[:]; est_vel = [0,0]; prev_est_vel = [0,0]; bounce_count = 0; bounce_thresh = 10; # velocity must have a sudden change greater than this magnitude to count camera_fps = 24; # we'll only take snapshots at this speed camera_timer = 0; # time since last snapshot snap = false; pic_count = 0; # loop done = false; prev_time = time.time(); while not done: # refresh display display = np.copy(bg); # @R_801_9531@e timestep now_time = time.time(); dt = now_time - prev_time; dt *= time_scale; prev_time = now_time; # @R_801_9531@e physics # position ball_pos[0] += ball_vel[0] * dt; ball_pos[1] += ball_vel[1] * dt; # velocity ball_vel[1] -= grav * dt; drag_mult = (1 - ((1 - drag) * dt)); ball_vel[0] *= drag_mult; ball_vel[1] *= drag_mult; # check for mouse click if click: # register animation click = false; click_anims.append([time.time(),click_pos[:]]); # get dist dx = ball_pos[0] - click_pos[0]; dy = ball_pos[1] - click_pos[1]; dist = math.sqrt(dx*dx + dy*dy); # clamp dist if Dist < 1: dist = 1; # get force attenuation # force = click_force / (dist*dist); # too much force = click_force / dist; # get angle and get axial force angle = math.atan2(dy,dX); xforce = math.cos(anglE) * force; yforce = math.sin(anglE) * force; # apply force ball_vel[0] += xforce; ball_vel[1] += yforce; # check for bounce # left if ball_pos[0] - ball_radius < 0: ball_pos[0] = 0 + ball_radius; ball_vel[0] *= -bounce_mult; # right if ball_pos[0] + ball_radius > res[0]: ball_pos[0] = res[0] - ball_radius; ball_vel[0] *= -bounce_mult; # up # +y-axis is down in OpenCV if ball_pos[1] - ball_radius < 0: ball_pos[1] = 0 + ball_radius; ball_vel[1] *= -bounce_mult; # down if ball_pos[1] + ball_radius > res[1]: ball_pos[1] = res[1] - ball_radius; ball_vel[1] *= -bounce_mult; # check if it's time for a snapshot camera_timer += dt; # time since last snapshot if camera_timer > (1.0 / camera_fps): # estimate velocity est_vel[0] = (ball_pos[0] - prev_pos[0]) / camera_timer; est_vel[1] = (ball_pos[1] - prev_pos[1]) / camera_timer; # check if the sign of the velocity has changed if sign(est_vel[0]) != sign(prev_est_vel[0]) or sign(est_vel[1]) != sign(prev_est_vel[1]): # check for bounces from large change in velocity dvx = abs(est_vel[0] - prev_est_vel[0]); dvy = abs(est_vel[1] - prev_est_vel[1]); change_vel = math.sqrt(dvx*dvx + dvy*dvy); if change_vel > bounce_thresh: bounce_count += 1; # @R_801_9531@e previous state trackers prev_est_vel = est_vel[:]; prev_pos = ball_pos[:]; # reset camera timer camera_timer = 0; snap = True; # draw bounce text cv2.putText(display,"Bounces: " + str(bounce_count),(15,40),font,fontScale,fontColor,thickness,cv2.LINE_AA); # draw ball x,y = ball_pos; cv2.circle(display,(int(X),int(y)),ball_radius,(220,150,0),-1); # draw click animations for a in range(len(click_anims)-1,-1,-1): # get lifetime life = now_time - click_anims[a][0]; if life > anim_dur: del click_anims[a]; else: # draw mult = life / anim_dur; radius = int(anim_radius * mult); if radius > 0: val = 255 - int(255 * mult); color = [val,val,val]; cv2.circle(display,click_anims[a][1],radius,color,2); # show cv2.imshow("Display",display); key = cv2.waitKey(1); # # if snapshot,save a picture # if snap: # snap = false; # cv2.imwrite("bouncy/" + str(pic_count).zfill(5) + ".png",display); # pic_count += 1; # check keypresses done = key == ord('q');
@H_618_13@大佬总结
以上是大佬教程为你收集整理的有没有办法可以计算 OpenCV 中球的反弹?全部内容,希望文章能够帮你解决有没有办法可以计算 OpenCV 中球的反弹?所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。