Используйте медиапайп для выполнения отметки руки。получатьотметка После рук мы можем выполнять некоторые приложения, такие как отображение, использование жестов для выполнения некоторых элементов управления и т. д. В этой статье описывается использование opencv и mediapipe для обнаружения и отображения рук в камере (или видео), а также их маркировки и последующего применения отметки. руки управляют компьютером.
opencv-python
:Визуальная тематика。Чтение, запись и обработка изображений ивидео。
mediapipe
:MediapipeдаGoogleПлатформа обработки мультимедиа с открытым исходным кодом。В этой статье используется версия0.10.2
。
Установите их с помощью pip:
pip install opencv-python
pip install mediapipe
Введение с официального сайта mediapipe: Локальное машинное обучение поддерживает распространенные визуальные задачи: обнаружение целей, классификация изображений, сегментация, отслеживание рук, распознавание жестов и т. д. Предоставляет интерфейсы Andorid, JS и Python. Официальный сайт: https://developers.google.com/mediapipe.
Используйте opencv для вызова камеры, чтения изображения и отображения его.
import cv2
cap = cv2.VideoCapture(0) # Получите камеру, вместо этого вы также можете импортировать из видеофайла
while True:
success, img = cap.read() # Читать картинки из камеры
# Обработать изображение ...
cv2.imshow("image", img)
cv2.waitKey(1)
Чтобы показать количество изображений, обрабатываемых в секунду (fps), вычислите интервал между двумя кадрами:
...
import time
previous_time = 0
current_time = 0
cap = cv2.VideoCapture(0) # Получить камеру
while True:
success, img = cap.read() # Читать картинки из камеры
# Обработать изображение ...
current_time = time.time()
fps = 1 / (current_time - previous_time) # Получить интервал между двумя дисплеями
previous_time = current_time
cv2.putText(img, str(round(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 2)
cv2.imshow("image", img)
cv2.waitKey(1)
Использование медиапайпа относительно просто. Вам нужно всего лишь создать экземпляр соответствующего объекта и передать изображение для получения результата.
import time
import cv2
import mediapipe as mp
cap = cv2.VideoCapture(0)
mp_hands = mp.solutions.hands
hands = mp_hands.Hands()
mp_draw = mp.solutions.drawing_utils # для рисования
pTime = 0
cTime = 0
while True:
success, img = cap.read()
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # Формат opencv по умолчанию — BGR, который необходимо преобразовать в RGB. Mediapipe справится с этим.
results = hands.process(imgRGB) # Вызовите метод процесса, чтобы обработать изображение и обнаружить руку.
if results.multi_hand_landmarks:
# results.multi_hand_landmarks — это список, каждый элемент которого представляет руку. Каждая рука имеет 20 маркеров положения.
for hand_landmark in results.multi_hand_landmarks:
mp_draw.draw_landmarks(img, hand_landmark, mp_hands.HAND_CONNECTIONS)
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(img, str(round(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 2)
cv2.imshow("image", img)
cv2.waitKey(1)
Каждая рука имеет 20 координат, обозначающих различные части руки (например, пальцы, пятку ладони...).
Чтобы облегчить повторное использование, мы записали часть обнаружения рук в класс:
import time
import cv2
import mediapipe as mp
class HandDetector():
def __init__(self, mode=False, max_hands=2, detection_conf=0.5, track_conf=0.5):
self.mode = mode
self.maxHands = max_hands
self.detection_conf = detection_conf
self.track_conf = track_conf
self.mp_hands = mp.solutions.hands
self.hands = self.mp_hands.Hands(self.mode, self.maxHands, 1, self.detection_conf, self.track_conf)
self.mp_draw = mp.solutions.drawing_utils
def find_hands(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.mp_draw.draw_landmarks(img, handLms, self.mp_hands.HAND_CONNECTIONS)
return img
def find_position(self, img, hand_number=0, draw=True):
lm_list = []
if self.results.multi_hand_landmarks:
hand_landmarks = self.results.multi_hand_landmarks[hand_number]
for id, lm in enumerate(hand_landmarks.landmark):
h, w, c = img.shape
cx, cy = int(lm.x * w), int(lm.y * h)
lm_list.append([id, cx, cy])
if draw:
cv2.circle(img, (cx, cy), 7, (255, 0, 255), cv2.FILLED)
return lm_list
def main():
pTime = 0
cTime = 0
cap = cv2.VideoCapture(0)
detector = HandDetector()
while True:
success, img = cap.read()
img = detector.find_hands(img)
lmList = detector.find_position(img)
if len(lmList) != 0:
print(lmList[0])
cTime = time.time()
fps = 1 / (cTime - pTime)
pTime = cTime
cv2.putText(img, str(round(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 2)
cv2.imshow("image", img)
cv2.waitKey(1)
if __name__ == '__main__':
main()
Используйте отметка, реализованную выше. рукии система, которая может изменитьсяобъембиблиотека(pycaw),Можно управлять жестамиобъем:Посчитайте кончики двух больших и указательных пальцев.расстояние,и поставьрасстояниепреобразован вобъем。также,Opencv также используется для отображения информации об объеме изображения.
# proj 1 volume hand control
import math
import time
import cv2
import numpy as np
# pycaw Для контроля объема
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
from HnadTrackingModule import HandDetector
def main():
devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = interface.QueryInterface(IAudioEndpointVolume)
vol_now = volume.GetMasterVolumeLevel()
print("vol_now=",vol_now)
vol_range = volume.GetVolumeRange()
print("vol_range=", vol_range) # vol= (-63.5, 0.0, 0.5)
vol = 0
vol_bar = 400
vol_per = 0
min_vol, max_vol = vol_range[0], vol_range[1]
w_cam, h_cam = 640, 480
p_time = 0
c_time = 0
cap = cv2.VideoCapture(0)
cap.set(3, w_cam)
cap.set(4, h_cam)
detector = HandDetector(detection_conf=0.7)
while True:
success, img = cap.read()
img = detector.find_hands(img)
lm_list = detector.find_position(img, draw=False)
if len(lm_list) != 0:
print(lm_list[4], lm_list[8]) # Кончик большого и указательного пальца
x1, y1 = lm_list[4][1], lm_list[4][2]
x2, y2 = lm_list[8][1], lm_list[8][2]
cx, cy = (x1 + x2) // 2, (y1 + y2) // 2 # середина
cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)
cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED)
cv2.circle(img, (cx, cy), 15, (255, 0, 255), cv2.FILLED)
cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255),3)
# 计算расстояние length = math.hypot(x2 - x1,y2 - y1)
# расстояниеиобъемпреобразование vol = np.interp(length, [10, 150], [min_vol, max_vol])
# объем Процентная сумма VolumeLevel не является линейной зависимостью.
level_percent = {-63.5: 0, -33.03: 10, -23.55: 20, -17.76: 30, -13.58: 40, -10.30: 50,
-7.61: 60, -5.32: 70, -3.33: 80, -1.57: 90, 0: 100}
xp = list(level_percent.keys())
fp = list(level_percent.values())
vol_per = np.interp(vol, xp, fp)
vol_bar = np.interp(vol_per, [0, 100], [400, 150])
print("length=", length) # 10 ~100
print("vol=", vol)
volume.SetMasterVolumeLevel(vol, None)
cv2.rectangle(img, (50, 150), (85, 400), (0, 255, 0), 3)
cv2.rectangle(img, (50, int(vol_bar)), (85, 400), (0, 255, 0), cv2.FILLED)
cv2.putText(img, f"{int(vol_per)} %", (40, 450), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 2)
c_time = time.time()
fps = 1 / (c_time - p_time)
p_time = c_time
cv2.putText(img, str(round(fps)), (10, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 255), 2)
cv2.imshow("image", img)
cv2.waitKey(1)
if __name__ == '__main__':
main()