在计算机视觉领域,手部追踪技术是一项重要的应用。通过结合OpenCV和MediaPipe库,可以构建出许多实时工作的应用程序,主要用于图像和视频处理。OpenCV是一个开源的计算机视觉和机器学习软件库,它提供了多种编程接口,用于图像和视频分析。MediaPipe则是一个用于构建音频、视频或任何时间序列数据的框架,它可以帮助构建各种媒体处理功能的管道。
MediaPipe的一些主要应用包括多手追踪、面部检测、目标检测与追踪、3D目标检测与追踪(Objectron)、自动视频裁剪管道(AutoFlip)等。MediaPipe使用单次手掌检测模型,一旦检测到手掌,就会在检测到的手掌区域执行精确的关键点定位,定位21个3D手掌坐标。MediaPipe管道利用多个模型,例如手掌检测模型,该模型从完整图像中返回定向的手边界框。裁剪后的图像区域被送入由手掌检测器定义的手部地标模型,并返回高保真度的3D手部关键点。
接下来,将实现手部追踪模型。首先,安装所需的模块:
pip install opencv-python
pip install mediapipe
然后,检查网络摄像头的工作情况。以下是一个简单的代码示例,用于检测网络摄像头是否连接到计算机,并在输出窗口的左上角显示每秒帧数(fps)。
import cv2
import time
cap = cv2.VideoCapture(0)
pTime = 0
while True:
> success, img = cap.read()
> imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
> cTime = time.time()
> fps = 1 / (cTime - pTime)
> pTime = cTime
> cv2.putText(img, f'FPS:{int(fps)}', (20, 70), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
> cv2.imshow("Test", img)
cv2.waitKey(1)
现在,让开始实现。导入所需的模块并初始化所需的变量。
import cv2
import mediapipe as mp
import time
cap = cv2.VideoCapture(0)
mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,
max_num_hands=2,
min_detection_confidence=0.5,
min_tracking_confidence=0.5)
mpDraw = mp.solutions.drawing_utils
pTime = 0
cTime = 0
在上述代码中,声明了一个名为“hands”的对象,用于检测手部,在默认情况下,如果查看“Hands()”类,将检测到手的数量设置为2,最小检测置信度设置为0.5,最小跟踪置信度设置为0.5。将使用“mpDraw”来绘制关键点。
现在,让编写一个while循环来执行代码。
while True:
> success, img = cap.read()
> imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
> results = hands.process(imgRGB)
> if results.multi_hand_landmarks:
> for handLms in results.multi_hand_landmarks:
> for id, lm in enumerate(handLms.landmark):
> h, w, c = img.shape
> cx, cy = int(lm.x * w), int(lm.y * h)
> cv2.circle(img, (cx, cy), 3, (255, 0, 255), cv2.FILLED)
> mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
> cTime = time.time()
> fps = 1 / (cTime - pTime)
> pTime = cTime
> cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
> cv2.imshow("Image", img)
> cv2.waitKey(1)
在上述代码中,从网络摄像头读取帧,并将图像转换为RGB。然后使用“hands.process()”函数在帧中检测手部。一旦手部被检测到,将定位关键点,然后使用cv2.circle突出显示关键点,并使用mpDraw.draw_landmarks连接关键点。
以下是完整的代码:
import cv2
import mediapipe as mp
import time
cap = cv2.VideoCapture(0)
mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,
max_num_hands=2,
min_detection_confidence=0.5,
min_tracking_confidence=0.5)
mpDraw = mp.solutions.drawing_utils
pTime = 0
cTime = 0
while True:
> success, img = cap.read()
> imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
> results = hands.process(imgRGB)
> if results.multi_hand_landmarks:
> for handLms in results.multi_hand_landmarks:
> for id, lm in enumerate(handLms.landmark):
> h, w, c = img.shape
> cx, cy = int(lm.x * w), int(lm.y * h)
> cv2.circle(img, (cx, cy), 3, (255, 0, 255), cv2.FILLED)
> mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)
> cTime = time.time()
> fps = 1 / (cTime - pTime)
> pTime = cTime
> cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
> cv2.imshow("Image", img)
> cv2.waitKey(1)
输出将是:
手部追踪模型输出
现在,让创建一个手部追踪模块,以便可以在其他项目中使用它。创建一个新的Python文件,首先让创建一个名为handDetector的类,其中包含两个成员函数,分别命名为findHands和findPosition。函数findHands将接受一个RGB图像,并在帧中检测手部并定位关键点并绘制地标,函数findPosition将提供手部的位置和ID。然后是主函数,其中初始化模块,并编写一个while循环来运行模型。在这里,可以将此设置或模块导入到任何其他相关项目中。
import cv2
import mediapipe as mp
import time
class handDetector():
def __init__(self, mode = False, maxHands = 2, detectionCon = 0.5, trackCon = 0.5):
self.mode = mode
self.maxHands = maxHands
self.detectionCon = detectionCon
self.trackCon = trackCon
self.mpHands = mp.solutions.hands
self.hands = self.mpHands.Hands(self.mode, self.maxHands, self.detectionCon, self.trackCon)
self.mpDraw = mp.solutions.drawing_utils
def findHands(self,img, draw = True):
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
self.results = self.hands.process(imgRGB)
if self.results.multi_hand_landmarks:
for handLms in self.results.multi_hand_landmarks:
if draw:
self.mpDraw.draw_landmarks(img, handLms, self.mpHands.HAND_CONNECTIONS)
return img
def findPosition(self, img, handNo = 0, draw = True):
lmlist = []
if self.results.multi_hand_landmarks:
myHand = self.results.multi_hand_landmarks[handNo]
for id, lm in enumerate(myHand.landmark):
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
lmlist.append([id, cx, cy])
if draw:
cv2.circle(img, (cx, cy), 3, (255, 0, 255), cv2.FILLED)
return lmlist
def main():
pTime = 0
cTime = 0
cap = cv2.VideoCapture(0)
detector = handDetector()
while True:
success, img = cap.read()
img = detector.findHands(img)
lmlist = detector.findPosition(img)
if len(lmlist) != 0:
print(lmlist[4])
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(img, str(int(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 3)
cv2.imshow("Image", img)
cv2.waitKey(1)
if __name__ == "__main__":
main()
输出将与上面所示相同,并跟踪手部的位置。完整的代码也可以在以下位置找到:
参考:
LinkedIn:感谢关注。
博客大赛
手部追踪
S
Syed Abdul Gaffar
热衷于挑战的刺激,解决复杂问题,并打造创新的AI解决方案,为社会带来改变。无论是优化还是构建可持续的AI生态系统,相信利用AI的力量为更大的利益服务。让集思广益,合作,一次改变世界,一次一个字节。