训练完电赛滚球题,刚比完数据赛,总结一下用到的一些图像处理算法
(写到后面觉得好长,数据赛的写在另一篇博客https://blog.csdn.net/qq_45615475/article/details/112860120)
阈值提取
#定义各类颜色阈值范围
import numpy as np
#黑色
lower_black=np.array([0,0,0])
upper_black=np.array([180,255,46])
#灰色
lower_gray=np.array([0,0,46])
upper_gray=np.array([180,43,220])
#白色
lower_white=np.array([0,0,221])
upper_white=np.array([180,30,255])
#红色
lower_red1=np.array([0,43,46])
upper_red1=np.array([10,255,255])
lower_red2=np.array([156,43,46])
upper_red2=np.array([180,255,255])
#橙色
lower_orange=np.array([11,43,46])
upper_orange=np.array([25,255,255])
#黄色
lower_yellow=np.array([26,43,46])
upper_yellow=np.array([34,255,255])
#青色
lower_qin=np.array([78,43,46])
upper_qin=np.array([99,255,255])
#蓝色
lower_blue=np.array([100,43,46])
upper_blue=np.array([124,255,255])
#紫色
lower_purple=np.array([125,43,46])
upper_purple=np.array([155,255,255])
img_path='Test/Test1.png'
img=cv2.imread(img_path)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)#转换为HSV空间
mask = cv2.inRange(hsv, lower_red, upper_red)#根据阈值提取红色,想提取其他颜色就改为对应阈值即可
二值化
gray_img = cv2.cvtColor(cropped, cv2.COLOR_BGRA2GRAY)#图像灰度化
ret,thresh = cv2.threshold(gray_img,80,255,cv2.THRESH_BINARY)#需要设置提取阈值
霍夫圆检测
小球识别一开始用的方案,但太耗时,最后还是直接色块检测
lower = np.array([0, 0, 0]) # 设定颜色的阈值下限
upper = np.array([120, 120, 120]) # 设定颜色的阈值上限
# 消除噪声
mask = cv2.inRange(hsv, lower, upper) # 设定掩膜取值范围
#bila = cv2.bilateralFilter(mask, 10, 200, 200) # 双边滤波消除噪声
#opening = cv2.morphologyEx(bila, cv2.MORPH_OPEN, kernel) # 形态学开运算
#closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel) # 形态学开运算
#edges = cv2.Canny(closing, 50, 100) # 边缘识别
edges = cv2.Canny(mask, 50, 100) # 边缘识别
circles = cv2.HoughCircles(
edges, cv2.cv.CV_HOUGH_GRADIENT, 1, 100, param1=100, param2=10, minRadius=10, maxRadius=500)
if circles is not None: # 如果识别出圆
for circle in circles[0]:
# 获取圆的坐标与半径
x = int(circle[0])
y = int(circle[1])
r = int(circle[2])
cv2.circle(frame, (x, y), r, (0, 0, 255), 3) # 标记圆
cv2.circle(frame, (x, y), 3, (255, 255, 0), -1) # 标记圆心
text = 'x: '+str(x)+' y: '+str(y)
cv2.putText(frame, text, (10, 30), font, 1, (0, 255, 0), 2) # 显示圆心位置
else:
# 如果识别不出,显示圆心不存在
cv2.putText(frame, 'x: None y: None', (10, 30), font, 1, (0, 255, 0), 2)
#输入图像,输出画圆的图像
def Get_Circles(frame):
gray = cv2.cvtColor(frame, cv2.COLOR_BGRA2GRAY)
img = cv2.medianBlur(gray, 7)
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 50, param1=100, param2=30, minRadius=70, maxRadius=200)#霍夫圆检测
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0, :]: # 在图片上画圆和圆心
cv2.circle(frame, (i[0], i[1]), i[2], (0, 255, 0), 2)
cv2.circle(frame, (i[0], i[1]), 2, (0, 0, 255), 3)
return frame
#找红球
def Get_Red_Circles(frame):
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, lower_red, upper_red)
res = cv2.bitwise_and(frame, frame, mask=mask)
gray = cv2.cvtColor(res, cv2.COLOR_BGRA2GRAY)
img = cv2.medianBlur(gray, 7)
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 50, param1=100, param2=30, minRadius=70, maxRadius=200)#霍夫圆检测
if circles is not None:
circles = np.uint16(np.around(circles))
for i in circles[0, :]: # 在图片上画圆和圆心
cv2.circle(frame, (i[0], i[1]), i[2], (0, 255, 0), 2)
cv2.circle(frame, (i[0], i[1]), 2, (0, 0, 255), 3)
return frame
色块检测
cnts = cv2.findContours(thresh1.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] #轮廓检测
#如果存在轮廓
if len(cnts) > 0:
#找到面积最大的轮廓
c = max(cnts, key = cv2.contourArea)
#确定面积最大的轮廓的外接圆
((center_x, center_y), radius) = cv2.minEnclosingCircle(c)
#计算轮廓的矩
# M = cv2.moments(c)
#计算质心
cv2.circle(frame, (int(center_x), int(center_y)), int(radius), (0, 255, 255), 2)
cv2.circle(frame, None, 5, (0, 0, 255), -1)
print('红色色块的中心坐标',(int(center_x),int(center_y)))
#通过二值化和色块检测得到小球坐标
lower_red=np.array([156,43,46])
upper_red=np.array([180,255,255])
def Binary_Get_Ball(frame,show,area,thr):
cropped = frame[area[0]:area[1], area[2]:area[3]] #(上,下)(左,右)
gray_img = cv2.cvtColor(cropped, cv2.COLOR_BGRA2GRAY)#图像灰度化
ret,thresh=cv2.threshold(gray_img,thr[0],thr[1],cv2.THRESH_BINARY)
thresh=255-thresh
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2] #轮廓检测
#如果存在轮廓
if len(cnts) > 0:
#找到面积最大的轮廓
c = max(cnts, key = cv2.contourArea)
#确定面积最大的轮廓的外接圆
((center_x, center_y), radius) = cv2.minEnclosingCircle(c)
if (show==True):
cv2.circle(cropped, (int(center_x), int(center_y)), int(radius), (0, 255, 255), 2)
cv2.circle(cropped, None, 5, (0, 0, 255), -1)
print('红色色块的中心坐标',(int(center_x),int(center_y)))
else:
center_x=0
center_y=0
radius=0
return center_x,center_y,radius,cropped
电赛滚球题最终方案
可见我另一篇文章https://blog.csdn.net/qq_45615475/article/details/112859548
形态学开运算/闭运算
好像有以下代码可以执行
opening = cv2.morphologyEx(bila, cv2.MORPH_OPEN, kernel) # 形态学开运算
closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel) # 形态学闭运算
但我一般都是直接膨胀腐蚀(闭运算)或者腐蚀膨胀(开运算)看每一步的效果效果
#iterations为整数,可调,越大效果越强
no_img1 = cv2.dilate(no_img1, None, iterations=1)#膨胀
no_img1 = cv2.erode(no_img1, None, iterations=1)#腐蚀
滤波
双边滤波消除噪声
bila = cv2.bilateralFilter(mask, 10, 200, 200) # 双边滤波消除噪声 #
高斯滤波
中值模糊
img = cv.medianBlur(gay_img, 7) # 进行中值模糊,去噪点
edges = cv2.Canny(closing, 50, 100) # 边缘识别
图像变换
gay_img = cv.cvtColor(planets, cv.COLOR_BGRA2GRAY)#图像灰度化
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)#转换为HSV空间
透视变换
def PersTrans(frame,Center,frame_points): #透视变换,输入为图像
rows,cols,channel = frame.shape
src_points = np.float32([Center[0],Center[1],Center[2],Center[3]])
dst_points = np.float32([[0,0],[cols-1,0],[0,rows-1],[cols-1,rows-1]])
projective_martix = cv2.getPerspectiveTransform(src_points,dst_points)
projective_image = cv2.warpPerspective(frame,projective_martix,(cols,rows))
return projective_image,projective_martix
图像截取部分
cropped = img[30:440, 140:540] #(上,下)(左,右)