在图像处理领域,OpenCV库的出现无疑是一场革命。从图像分类到目标检测,不仅可以利用 OpenCV 库实现许多酷炫的功能,还能构建出一流的应用程序。今天,将实现一个既有趣又实用的功能——图像的虚拟缩放,这种功能在手机或电脑上都很常见,但在这里将实现在实时帧中对所需图像的虚拟缩放。
本项目将使用 OpenCV 库以及另一个名为 CVZone 的库来实现虚拟缩放。CVZone 是一个基于 OpenCV 和 MediaPipe 构建的库,它简化了工作。它内置了一些非常实用的功能,如手部跟踪、面部标记检测、姿态估计等,这些功能只需几行代码即可实现。
首先,来看一个使用 CVZone 的手部检测器的演示代码。首先,安装所需的库。可以使用以下命令安装,或者逐个安装。
pip install -r requirements.txt
或
pip install opencv-python==3.4.11.43
pip install cvzone==1.5.3
现在,让检测手部。
import cv2
from cvzone.HandTrackingModule import HandDetector
# 从摄像头获取输入
frame = cv2.VideoCapture(0)
frame.set(3, 1280)
frame.set(4, 720)
# 初始化手部检测模块,设置一定的置信度
handDetector = HandDetector(detectionCon=0.8)
# 循环
while True:
# 从摄像头读取帧
res, img = frame.read()
# 检测手部,默认情况下可以检测到两只手
hands = handDetector.findHands(img)
# 显示输出
cv2.imshow("Sample CVZone output", img)
cv2.waitKey(1)
首先,需要导入所需的模块,即 cv2 和 cvzone.HandTrackingModule 中的 HandDetector。然后,使用OpenCV的 VideoCapture 函数从摄像头获取输入,并设置窗口的高度和宽度,初始化手部检测模块,并设置一定的检测置信度。在循环中,从摄像头读取输入帧,并将帧传递给手部检测模块的方法 findHands,该方法将返回检测到的手部列表以及图像。然后显示图像。
目标是构建一个项目,其中屏幕上有一张图像,使用OpenCV和手势实现虚拟缩放,即如果双手的食指和拇指都向上,并且双手分开,则放大图像;如果双手的食指和拇指都向上,并且双手靠近,则缩小图像。基于此,将制定一些步骤。
步骤包括:初始化摄像头输入,设置输出窗口的高度和宽度,初始化手部检测模块,声明用于计算距离、缩放范围、中心 X 和中心 Y 的变量,读取输入帧,检测手部,读取用于缩放操作的图像,检查是否检测到两只手,检查食指和拇指是否向上,计算双手之间的距离并调整图像至双手中心,计算新的高度和宽度,然后调整图像大小,显示输出。
按照前一节提到的要求安装所需的库。现在,让开始。首先,导入所需的模块。这里只需要 cv2 和 cvzone 的手部检测模块。导入库后,使用 cv2.VideoCapture(0) 从摄像头获取输入,其中 0 是摄像头 ID。然后设置输出窗口的宽度和高度。这里设置为 1280 x 720。
import cv2
from cvzone.HandTrackingModule import HandDetector
# 从摄像头获取输入
frame = cv2.VideoCapture(0)
frame.set(3, 1280)
frame.set(4, 720)
接下来,初始化手部检测模块(handDetector),设置检测置信度为 0.8,并在 while 循环中使用它来检测手部。声明 4 个变量,一个用于存储初始距离,初始值为 None,一个用于缩放范围,初始值为 0,另外两个用于捕获缩放对象的中心 X 和中心 Y,并设置一些随机值。在代码中,这些变量分别是 distStart、zoom_range、cx、cy。
# 初始化手部检测模块
handDetector = HandDetector(detectionCon=0.8)
distStart = None
zoom_range = 0
cx, cy = 500, 500
while True:
# 读取输入帧
res, img = frame.read()
# 检测手部
hands, img = handDetector.findHands(img)
# 要缩放的图像
new_img = cv2.imread('resized_test.jpg')
# 如果检测到两只手
if len(hands) == 2:
print("开始缩放...")
print(handDetector.fingersUp(hands[0]))
print(handDetector.fingersUp(hands[1]))
if handDetector.fingersUp(hands[0]) == [1, 1, 0, 0, 0] and handDetector.fingersUp(hands[1]) == [1, 1, 0, 0, 0]:
# print("开始缩放...")
lmList1 = hands[0]['lmList']
lmList2 = hands[1]['lmList']
# 点 8 是食指的指尖
if distStart is None:
# 长度,信息,图像 = handDetector.findDistance(lmList1[8], lmList2[8], img)
# 绘制右手食指和拇指与左手之间的连接点
length, info, img = handDetector.findDistance(hands[0]['center'], hands[1]['center'], img)
# print(length)
distStart = length
length, info, img = handDetector.findDistance(hands[0]['center'], hands[1]['center'], img)
# 信息提供中心 x 和中心 y
# 计算缩放范围
zoom_range = int((length - distStart) // 2)
# 计算中心点,以便可以将缩放图像放置在中心
cx, cy = info[4:]
print(zoom_range)
else:
distStart = None