程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了有没有办法可以计算 OpenCV 中球的反弹?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决有没有办法可以计算 OpenCV 中球的反弹??

开发过程中遇到有没有办法可以计算 OpenCV 中球的反弹?的问题如何解决?下面主要结合日常开发的经验,给出你关于有没有办法可以计算 OpenCV 中球的反弹?的解决方法建议,希望对你解决有没有办法可以计算 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 运行),您都可以获得球的位置。使用该位置,您可以估计速度(位置变化除以时间)。如果该速度的方向突然发生变化,那么您可以将其视为反弹。

有没有办法可以计算 OpenCV 中球的反弹?

此代码的绝大部分用于设置模拟,出于您的目的可以安全地忽略。这是相关的代码块

    # 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,请注明来意。
标签: