原视频就是坤坤的视频
我们的任务就是把篮球圈出
截取图片分析:
import cv2
import numpy as np
# 读取图像
image_path = r'D:\desktop\basketball.png'
image = cv2.imread(image_path)
# 转换为HSV颜色空间
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 定义橙色(篮球)的HSV范围
lower_orange = np.array([0, 100, 100])
upper_orange = np.array([20, 255, 255])
# 创建掩码
mask = cv2.inRange(hsv, lower_orange, upper_orange)
# 查找轮廓
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 遍历所有轮廓
for contour in contours:
# 计算轮廓的边界框
x, y, w, h = cv2.boundingRect(contour)
# 绘制蓝色边框
cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)
# 显示结果图像
cv2.imshow('Result', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
思路
1,将传统的rgb转化为hsv,并定义篮球的颜色的范围
2,根据颜色范围创建掩码,即满足颜色变为白色,其余为黑色
3,查找轮廓
解析
cv2.findContours
:该函数用于从二值图像中提取轮廓信息。轮廓可以理解为图像中具有相同颜色或灰度值的连续点集的边界。
参数:
-
mask
:输入的二值图像(掩码)。cv2.RETR_EXTERNAL
:检索模式,只返回最外层的轮廓(即不包括内部轮廓)。cv2.CHAIN_APPROX_SIMPLE
:轮廓近似方法,压缩水平、垂直和对角线方向的冗余点,只保留关键点。
np.array([x, y, z])
三个值分别代表了色调(Hue)、饱和度(Saturation)和亮度(Value)
根据HSV调整的结果来确定
原数据:
调试HSV:
import cv2
import numpy as np
def nothing(x):
pass
# 通过Opencv读取图片信息
img = cv2.imread(r'D:\test\py\cv2\zhiyin\basketball.png')
rows, cols, channels = img.shape
cv2.imshow("src", img)
cv2.namedWindow('img2', 1)
# 创建6个滑条用来操作HSV3个分量的上下截取界限
cv2.createTrackbar('Hlow','img2',62,180,nothing)
cv2.createTrackbar('Hup','img2',99,180,nothing)
cv2.createTrackbar('Slow','img2',198,255,nothing)
cv2.createTrackbar('Sup','img2',255,255,nothing)
cv2.createTrackbar('Vlow','img2',150,255,nothing)
cv2.createTrackbar('Vup','img2',255,255,nothing)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
while(1):
hlow = cv2.getTrackbarPos('Hlow', 'img2')
hup = cv2.getTrackbarPos('Hup', 'img2')
slow = cv2.getTrackbarPos('Slow', 'img2')
sup = cv2.getTrackbarPos('Sup', 'img2')
vlow = cv2.getTrackbarPos('Vlow', 'img2')
vup = cv2.getTrackbarPos('Vup', 'img2')
lower_red = np.array([hlow, slow, vlow])
upper_red = np.array([hup, sup, vup])
mask = cv2.inRange(hsv, lower_red, upper_red)
img2 = cv2.bitwise_and(img, img, mask=mask)
cv2.imshow("img2", img2)
k = cv2.waitKey(1) & 0xFF
if k == 27: # ESC键退出
break
# 清理资源
cv2.destroyAllWindows()
调试后的结果
Hlow: 0 Hup: 20 Slow: 100 Sup: 255 Vlow: 100 Vup: 255
- Hlow (色调下限) = 0 和 Hup (色调上限) = 20:
- Slow (饱和度下限) = 80 和 Sup (饱和度上限) = 255:
- Vlow (亮度下限) = 130 和 Vup (亮度上限) = 255:
调整后的数据:
视频源码:
import cv2
import numpy as np
min_contour_area = 2000
# 视频文件的路径
video_path = r'D:\test\py\cv2\zhiyin\zhiyin.mp4'
# 使用OpenCV打开视频文件
cap = cv2.VideoCapture(video_path)
# 检查视频是否成功打开
if not cap.isOpened():
print("Error: Could not open video.")
else:
# 获取原始视频的宽度和高度
original_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
original_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(f"Original Video Size: {original_width}x{original_height}")
# 设置缩放比例
scale_percent = 50 # 缩小到原尺寸的50%
# 计算新的尺寸
new_width = int(original_width * scale_percent / 100)
new_height = int(original_height * scale_percent / 100)
dim = (new_width, new_height)
# 设定加速倍数
speed_factor = 3 # 加快3倍
while True:
# 逐帧读取视频
ret, frame = cap.read()
# 如果正确读取了帧,则ret为True
if not ret:
print("Reached the end of the video or an error occurred.")
break
# 调整帧的大小
resized_frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)
hsv = cv2.cvtColor(resized_frame, cv2.COLOR_BGR2HSV)
# 定义橙色(篮球)的HSV范围
lower_orange = np.array([0, 80, 130])
upper_orange = np.array([20, 255, 255])
# 创建掩码
mask = cv2.inRange(hsv, lower_orange, upper_orange)
# 查找轮廓
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 遍历所有轮廓
for contour in contours:
# 计算轮廓面积
area = cv2.contourArea(contour)
# 如果面积大于设定的阈值,则进行处理
if area > min_contour_area:
# 计算轮廓的边界框
x, y, w, h = cv2.boundingRect(contour)
# 绘制蓝色边框
cv2.rectangle(resized_frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
# 显示结果帧
cv2.imshow('Resized Video Playback', resized_frame)
# 按下 'q' 键退出
if cv2.waitKey(int(1000 / cap.get(cv2.CAP_PROP_FPS) / speed_factor)) & 0xFF == ord('q'):
break
# 完成后释放捕获对象并关闭所有OpenCV窗口
cap.release()
cv2.destroyAllWindows()
经过调整后,框定的面积增大,但是在视频中有时gege突脸的时候会误判,通过面积筛选也不能完美解决这个问题,所以在高精度的识别中就需要做取舍,降低识别面积来提高精度