aysenur-mank's picture
feat: done
99bf888
"""
El Hareketiyle Müzik Kontrol Uygulaması
Gradio + MediaPipe + Audio Player
Hugging Face Spaces için optimize edilmiş
"""
import gradio as gr
import cv2
import numpy as np
from collections import deque
import time
import os
from pathlib import Path
# MediaPipe
import mediapipe as mp
mpHands = mp.solutions.hands
mpDraw = mp.solutions.drawing_utils
print("✓ MediaPipe yüklendi!")
# Müzik dosyalarını bul
MUSIC_DIR = Path(__file__).parent / "music"
MUSIC_FILES = []
if MUSIC_DIR.exists():
for ext in ['*.mp3', '*.wav', '*.ogg']:
MUSIC_FILES.extend(list(MUSIC_DIR.glob(ext)))
MUSIC_FILES = sorted(MUSIC_FILES)
print(f"✓ {len(MUSIC_FILES)} müzik dosyası bulundu!")
else:
print("⚠ music/ klasörü bulunamadı")
class MusicController:
"""Müzik durumunu takip eden sınıf"""
def __init__(self):
self.current_index = 0
self.is_playing = False
self.music_files = MUSIC_FILES
def get_current_track(self):
if self.music_files:
return str(self.music_files[self.current_index])
return None
def get_current_name(self):
if self.music_files:
return self.music_files[self.current_index].stem
return "Müzik yok"
def next_track(self):
if self.music_files:
self.current_index = (self.current_index + 1) % len(self.music_files)
return self.get_current_track(), self.get_current_name()
def play(self):
self.is_playing = True
def pause(self):
self.is_playing = False
class HandGestureDetector:
"""El hareketlerini algılayan sınıf"""
def __init__(self):
self.hands = mpHands.Hands(
static_image_mode=False,
max_num_hands=1,
min_detection_confidence=0.7,
min_tracking_confidence=0.7
)
self.tipIds = [4, 8, 12, 16, 20]
self.position_history = deque(maxlen=10)
self.last_swipe_time = 0
self.last_gesture_time = 0
def fingersUp(self, lmList):
"""Hangi parmaklar yukarıda"""
fingers = []
if len(lmList) < 21:
return [0, 0, 0, 0, 0]
# Başparmak
if lmList[self.tipIds[0]][1] < lmList[self.tipIds[0] - 1][1]:
fingers.append(1)
else:
fingers.append(0)
# Diğer 4 parmak
for id in range(1, 5):
if lmList[self.tipIds[id]][2] < lmList[self.tipIds[id] - 2][2]:
fingers.append(1)
else:
fingers.append(0)
return fingers
def detect(self, frame):
"""El algıla ve gesture döndür"""
if frame is None:
return None, None, "Kamera bekleniyor..."
# BGR'ye çevir (Gradio RGB verir)
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
frame = cv2.flip(frame, 1) # Ayna
imgRGB = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
results = self.hands.process(imgRGB)
gesture = None
gesture_text = "👋 El gösterin"
current_time = time.time()
h, w = frame.shape[:2]
if results.multi_hand_landmarks:
for handLms in results.multi_hand_landmarks:
# El çiz
mpDraw.draw_landmarks(frame, handLms, mpHands.HAND_CONNECTIONS)
# Landmark listesi
lmList = []
for id, lm in enumerate(handLms.landmark):
cx, cy = int(lm.x * w), int(lm.y * h)
lmList.append([id, cx, cy])
if len(lmList) >= 21:
fingers = self.fingersUp(lmList)
totalFingers = sum(fingers)
wrist_x = lmList[0][1]
# Swipe algılama
self.position_history.append((wrist_x, current_time))
if len(self.position_history) >= 6:
positions = list(self.position_history)
x_diff = positions[-1][0] - positions[0][0]
time_diff = positions[-1][1] - positions[0][1]
if time_diff < 0.35 and abs(x_diff) > 120:
if current_time - self.last_swipe_time > 1.0:
gesture = "swipe"
self.last_swipe_time = current_time
self.position_history.clear()
# Gesture algılama
if gesture is None and current_time - self.last_gesture_time > 0.5:
if totalFingers >= 4:
gesture = "palm"
self.last_gesture_time = current_time
elif fingers[1] == 1 and sum(fingers[2:]) == 0:
gesture = "index"
self.last_gesture_time = current_time
# Görsel ve metin
if gesture == "palm":
cv2.putText(frame, "DURDUR", (50, 80),
cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 4)
gesture_text = "✋ DURDUR"
elif gesture == "index":
cv2.putText(frame, "OYNAT", (50, 80),
cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 0), 4)
gesture_text = "☝️ OYNAT"
elif gesture == "swipe":
direction = ">>>" if x_diff > 0 else "<<<"
cv2.putText(frame, f"SONRAKI {direction}", (50, 80),
cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 165, 0), 3)
gesture_text = "👋 SONRAKİ"
else:
gesture_text = f"🖐️ {totalFingers} parmak"
# Debug
cv2.putText(frame, f"Parmak: {totalFingers}", (10, h - 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
# BGR -> RGB (Gradio için)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
return frame, gesture, gesture_text
# Global instances
detector = HandGestureDetector()
music_ctrl = MusicController()
def process_frame(frame, current_audio):
"""Gradio için frame işleme"""
processed_frame, gesture, gesture_text = detector.detect(frame)
audio_file = current_audio
track_name = music_ctrl.get_current_name()
status = gesture_text
# Gesture'a göre aksiyon
if gesture == "swipe":
audio_file, track_name = music_ctrl.next_track()
status = f"👋 SONRAKİ: {track_name}"
elif gesture == "palm":
music_ctrl.pause()
status = f"✋ DURAKLATILDI: {track_name}"
elif gesture == "index":
music_ctrl.play()
status = f"☝️ ÇALIYOR: {track_name}"
return processed_frame, audio_file, f"🎵 {track_name}", status
def start_music():
"""İlk müziği başlat"""
track = music_ctrl.get_current_track()
name = music_ctrl.get_current_name()
music_ctrl.play()
return track, f"🎵 {name}", f"☝️ ÇALIYOR: {name}"
def next_track():
"""Sonraki şarkıya geç"""
track, name = music_ctrl.next_track()
return track, f"🎵 {name}"
# Müzik listesi HTML
def get_music_list_html():
if not MUSIC_FILES:
return "<p>Müzik dosyası bulunamadı</p>"
html = "<div style='background:#1a1a2e; padding:10px; border-radius:10px;'>"
for i, f in enumerate(MUSIC_FILES):
icon = "▶️" if i == music_ctrl.current_index else "🎵"
html += f"<p style='color:white; margin:5px 0;'>{icon} {i+1}. {f.stem}</p>"
html += "</div>"
return html
# Gradio arayüzü
with gr.Blocks(
title="🎵 El Hareketiyle Müzik Kontrol",
theme=gr.themes.Soft(),
css="""
.music-info {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 15px;
border-radius: 10px;
color: white;
text-align: center;
font-size: 1.2em;
}
"""
) as demo:
gr.Markdown("""
# 🎵 El Hareketiyle Müzik Kontrol
Elinizi kameraya göstererek müzik kontrol edin!
""")
# Mevcut audio state
current_audio = gr.State(value=music_ctrl.get_current_track())
with gr.Row():
# Sol: Kamera
with gr.Column(scale=2):
gr.Markdown("### 📷 Kamera")
webcam = gr.Image(
sources=["webcam"],
streaming=True,
label="Kamera Girişi",
height=400
)
output_image = gr.Image(
label="🎯 El Algılama",
interactive=False,
height=400
)
# Sağ: Kontroller ve Müzik
with gr.Column(scale=1):
gr.Markdown("### 🎹 El Hareketleri")
gr.Markdown("""
| Hareket | Eylem |
|---------|-------|
| ✋ Avuç aç | **DURDUR** |
| ☝️ İşaret parmağı | **OYNAT** |
| 👋 El savur | **SONRAKİ** |
""")
gr.Markdown("---")
gr.Markdown("### 🎵 Müzik Çalar")
# Başlat butonu
start_btn = gr.Button("▶️ Müziği Başlat", variant="primary", size="lg")
next_btn = gr.Button("⏭️ Sonraki", size="lg")
# Şarkı adı
track_name = gr.Markdown(
value=f"🎵 {music_ctrl.get_current_name()}",
elem_classes=["music-info"]
)
# Audio player
audio_player = gr.Audio(
value=music_ctrl.get_current_track(),
label="🔊 Çalan Şarkı",
autoplay=False,
show_download_button=False
)
# Durum
status = gr.Textbox(
label="📊 Durum",
value="▶️ Müziği başlatmak için butona tıklayın",
interactive=False
)
gr.Markdown("---")
gr.Markdown("### 📋 Şarkı Listesi")
music_list = gr.HTML(value=get_music_list_html())
# Event handlers
start_btn.click(
fn=start_music,
outputs=[audio_player, track_name, status]
)
next_btn.click(
fn=next_track,
outputs=[audio_player, track_name]
)
# Webcam stream
webcam.stream(
fn=process_frame,
inputs=[webcam, current_audio],
outputs=[output_image, audio_player, track_name, status]
)
if __name__ == "__main__":
demo.launch()