网球目标检测

您所在的位置:网站首页 网球的速度怎么测出来的 网球目标检测

网球目标检测

2024-07-16 15:12| 来源: 网络整理| 查看: 265

1.问题描述

本文章实现了通过读取摄像头所拍摄的图像,实时检测图像中的网球并推算其距离、确定其方位。核心问题是如何从摄像头拍摄的画面中检测出网球,并排除干扰项。此外,为了将该方法运用在嵌入式系统上,系统的计算复杂度应当尽量减少,避免影响实时性。暂时隐藏

2.实现方法

对于网球这样的球体单色目标,可以选择霍夫变换进行圆检测,也可以通过色彩分割将网球从视频帧中分割出来。如果背景复杂,障碍物多,也可以选择训练一个专门识别网球的模型,比如常见的YOLO,这样可以提高识别的准确率。但这种方法的缺点是难以部署。下面,我将分别详细介绍这几种方法。

2.1 霍夫变换检测网球

霍夫变换检测网球的基本思想是,网球从每个方向看去基本都可以认为是圆,而任何一个圆,都可以从二维坐标系下的表达式映射到三维空间中去。也就是说,一个圆在笛卡尔坐标系下的表达式:

(x-a)²+(y-b)²=r²

可以映射为三维坐标系下的一个点(a,b,r)。那么,将一张图像映射于该三维坐标系后,该坐标系下的一个峰值可能就意味着一个圆。该方法的具体数学原理不再进行赘述,我们的首要目标是了解它的用法。如果想要了解更多有关霍夫变换的原理问题,可以搜索其他文章。

2.1.1 HoughCircles参数与返回值介绍

1、函数参数

在OpenCV中,有一个函数 cv2.HoughCircles() 就是使用的霍夫变换来检测圆。该函数共有8个参数。分别是:

image:8bit、单通道灰度图像

method:Hough变换方法,但目前只支持 cv2.HOUGH_GRADIENT

dp:累加器图像的分辨率。例如,当dp的值为1时,累加器将与源图像有相同的分辨率;当dp值设置为2时,累加器的高度和宽度都变为源图像的一半。dp的值不能小于1。

min_dist:能区分两个不同圆之间的最小值。如果该值过小,可能有很多不存在的圆被错误地检出。如果该值过大,可能会丢失一些圆。

param1:Canny边缘检测的阈值上限,下限为该值的一半。即超过阈值上限为边缘点,低于阈值下限则抛弃。中间部分视边缘是否相连而定。

param2:检测出圆质量的阈值。该值越大,检测出的圆就越接近标准的圆。该值越小,则就更容易有错误的圆被检测出来。

min_radius:限制能检测出圆的最小半径。低于该值的圆将被全部抛弃。

max_radius:限制能检测出圆的最大半径。高于该值的圆将被全部抛弃。

2、返回值

函数会返回一个numpy数组,包含了检测出所有圆的圆心坐标和半径信息。要调用出这些信息,可以通过分割数组的方式实现。例如:

circles=cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,100,param1=50,param2=70,minRadius=1,maxRadius=200) for i in circles[0,:]: cv2.circle(frame, (i[0],i[1]),i[2],(0,255,0),2)

分割后,得到的数组第一位为x坐标,第二位为y坐标,第三位为半径。得到这些数据后,结合cv2.circle()方法可以在图像上绘制圆,以便显示检测结果。

2.1.2 算法流程

先大致介绍算法流程,代码会放在2.1.3中。

(1)初始化一个VideoCapture对象,使用read()方法从摄像头中读取一帧图像;

(2)使用cvtColor()方法将图像从BGR色域转为灰度图像;

(3)使用高斯模糊对图像进行滤波,核的大小可以视情况而定。我是用的是(7,7)的核;

(4)使用HoughCircles()方法检测圆。

(5)获取圆心坐标与圆的半径,将圆在源图像上标注出来。

2.1.3 代码应用实例

由于代码是在虚拟机上的Thonny里编写的,我不知道怎么调成中文,因此注释是英文写的。另外,该程序本来是用作捡球车控制的,因此会在控制台中输出球体相对于摄像头的方向和距离。

import cv2 import numpy as np import math try: cap = cv2.VideoCapture(0) #from camera #cap = cv2.VideoCapture('./cvtest.mp4') #from video file except: exit() NoneType = None #variable for comparison RotateAngle = 0 #the angle needs to be rotate (the nearest ball) halfWidth = 0 #half of the image's width StdDiameter = 6.70 #the standard diameter of tennis ball StdPing = 4 #the standard diameter of table tennis ball FixValue = 5 #fix the calculation of real angle for vehicle to rotate while(True): ret, frame = cap.read() #capture frame by frame halfWidth = frame.shape[1]/2 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #convert frame to gray gray = cv2.GaussianBlur(gray, (7, 7), 0) #gaussianblur denoise circles = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,100,param1=50,param2=70,minRadius=1,maxRadius=200) gray = cv2.Canny(gray, 100, 300) #houghcircles find the circles, canny detect the edge binary, contours, hierarchy = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #find contours cv2.imshow('edge', binary) #show the image of contours if type(circles) != type(NoneType): #to avoid shutdown due to no circles found TimeStamp = 0 Reset = False for i in circles[0,:]: cv2.circle(frame, (i[0],i[1]),i[2],(0,255,0),2) #draw the circle cv2.circle(frame, (i[0],i[1]),2,(0,0,255),3) #draw the center of circle tanTheta = (i[0]-halfWidth)/(1.43*halfWidth) #the tan value RotateAngle = math.atan(tanTheta) #calculate the angle Distance = 850/i[2] #calculate the distance between ball and camera FixAngle = math.atan(Distance*math.sin(RotateAngle)/(Distance*math.cos(RotateAngle)+FixValue)) #calculate the fixed angle Angle = FixAngle*180/math.pi #transform from rad to degree if RotateAngle


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3