MediaPipe ile özel el hareketleri tanıyan bir sistem geliştirme
Merhaba!
Belirli el işaretlerini (gesture) tanıyıp bunları komuta çeviren bir sistem, sunum kontrolü, erişilebilirlik uygulamaları, hatta oyun kontrolü için pratik bir teknoloji. Bu konuda MediaPipe ile özel gesture tanıma sistemi geliştirdim.
MediaPipe, elin 21 anahtar noktasını (landmark) gerçek zamanlı tespit ediyor. Bu noktaların birbirine göre GEOMETRİK ilişkisini analiz ederek (parmaklar açık mı kapalı mı, hangi açıda), belirli işaretleri tanımlayabiliyoruz.
Python:
import cv2
import mediapipe as mp
import numpy as np
import math
mp_eller = mp.solutions.hands
mp_cizim = mp.solutions.drawing_utils
eller = mp_eller.Hands(
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
def mesafe_hesapla(p1, p2):
return math.sqrt((p1.x - p2.x)**2 + (p1.y - p2.y)**2)
def parmak_acik_mi(landmarklar, parmak_ucu_idx, parmak_eklem_idx):
"""Parmak ucu, eklem noktasından yukarıda mı (açık mı)?"""
return landmarklar[parmak_ucu_idx].y < landmarklar[parmak_eklem_idx].y
def el_isaretini_tani(landmarklar) -> str:
"""
Landmark pozisyonlarını analiz ederek bilinen
el işaretlerinden hangisi olduğunu tespit eder
"""
# Parmak açık/kapalı durumları
bas_parmak_acik = landmarklar[4].x < landmarklar[3].x # Başparmak yatay kontrol
isaret_acik = parmak_acik_mi(landmarklar, 8, 6)
orta_acik = parmak_acik_mi(landmarklar, 12, 10)
yuzuk_acik = parmak_acik_mi(landmarklar, 16, 14)
serce_acik = parmak_acik_mi(landmarklar, 20, 18)
parmaklar = [bas_parmak_acik, isaret_acik, orta_acik, yuzuk_acik, serce_acik]
acik_parmak_sayisi = sum(parmaklar)
# ─── İŞARET TANIMA KURALLARI ────────────────────
if acik_parmak_sayisi == 0:
return "✊ YUMRUK"
elif acik_parmak_sayisi == 5:
return "🖐️ AÇIK EL"
elif isaret_acik and orta_acik and not yuzuk_acik and not serce_acik:
return "✌️ ZAFER İŞARETİ"
elif isaret_acik and not orta_acik and not yuzuk_acik and not serce_acik:
return "☝️ İŞARET PARMAĞI"
elif bas_parmak_acik and not isaret_acik and not orta_acik and \
not yuzuk_acik and not serce_acik:
# Başparmak yönüne göre başparmak yukarı/aşağı ayırt et
if landmarklar[4].y < landmarklar[2].y:
return "👍 BAŞPARMAK YUKARI"
else:
return "👎 BAŞPARMAK AŞAĞI"
elif bas_parmak_acik and isaret_acik and not orta_acik and \
not yuzuk_acik and serce_acik:
return "🤟 SEVGİ İŞARETİ"
# Başparmak ve işaret parmağı arası mesafe kontrolü — "OK" işareti
basisaret_mesafe = mesafe_hesapla(landmarklar[4], landmarklar[8])
if basisaret_mesafe < 0.05 and orta_acik and yuzuk_acik and serce_acik:
return "👌 OK İŞARETİ"
return "❓ BİLİNMEYEN İŞARET"
# ─── KOMUT EŞLEŞTİRME — İŞARETİ EYLEME ÇEVİRME ──────
ISARET_KOMUT_HARITASI = {
"🖐️ AÇIK EL": "duraklat",
"✊ YUMRUK": "oynat",
"☝️ İŞARET PARMAĞI": "sonraki_slayt",
"✌️ ZAFER İŞARETİ": "onceki_slayt",
"👍 BAŞPARMAK YUKARI": "ses_ac",
"👎 BAŞPARMAK AŞAĞI": "sessize_al",
}
def komut_calistir(isaret: str):
komut = ISARET_KOMUT_HARITASI.get(isaret)
if komut:
print(f"🎯 Komut çalıştırılıyor: {komut}")
# Gerçek projede burada gerçek eylem tetiklenir
# (sunum yazılımı API'si, medya player kontrolü vb.)
# ─── ANA DÖNGÜ ──────────────────────────────────────
kamera = cv2.VideoCapture(0)
onceki_isaret = None
kararlilik_sayaci = 0
KARARLILIK_ESIGI = 5 # Aynı işaretin 5 kare boyunca sabit kalması gerekiyor
print("👋 El işareti tanıma sistemi başladı — Q ile çık")
while True:
ret, kare = kamera.read()
if not ret:
break
kare = cv2.flip(kare, 1)
kare_rgb = cv2.cvtColor(kare, cv2.COLOR_BGR2RGB)
sonuclar = eller.process(kare_rgb)
tespit_edilen_isaret = "El algılanmadı"
if sonuclar.multi_hand_landmarks:
for el_landmarklari in sonuclar.multi_hand_landmarks:
mp_cizim.draw_landmarks(kare, el_landmarklari, mp_eller.HAND_CONNECTIONS)
tespit_edilen_isaret = el_isaretini_tani(el_landmarklari.landmark)
# Kararlılık kontrolü — titremeyi/yanlış tetiklemeyi önle
if tespit_edilen_isaret == onceki_isaret:
kararlilik_sayaci += 1
else:
kararlilik_sayaci = 0
onceki_isaret = tespit_edilen_isaret
if kararlilik_sayaci == KARARLILIK_ESIGI:
komut_calistir(tespit_edilen_isaret)
cv2.putText(kare, tespit_edilen_isaret, (10, 40),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('El Isareti Tanima', kare)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
kamera.release()
cv2.destroyAllWindows()
Hangi işaretleri tanımladınız, ne amaçla kullandınız?