OpenCV Ve Python Kullanarak El İle Ses Kontrolü


    
Ufak bir el hareketi ile bilgisayarınızın sesini kontrol etmek kulağa nasıl geliyor ? Cevabınız olumlu ise bu konuda Python ve OpenCV kullanarak işinize yarayacak bir proje yapacağız. Aşağıda kütüphaneleri de kullanarak elimizi tanıtıp, birkaç kod ile bilgisayar sesini artık kontrol edebiliriz.


Kurulacak Kütüphaneler

import cv2
import mediapipe as mp
import math
import numpy as np
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume

MediaPipe Hands'in kullanılabilmesi için gerekli olan modülleri ve işlevleri sağlıyoruz.

mp_drawing = mp.solutions.drawing_utils
mp_drawing_styles = mp.solutions.drawing_styles
mp_hands = mp.solutions.hands

Ses ayarlarını kontrol etmek için Windows'ta kullanılan 'IaudioEndpointVolume' arabirimini ve bu arabirime erişmek için gerekli olan cihazları ve arabirimleri tanımlıyoruz.

devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))
volRange = volume.GetVolumeRange()
minVol, maxVol, volBar, volPer = volRange[0], volRange[1], 400, 0


Kamera çözünürlüğünü (genişlik ve yükseklik) ayarlar. `cv2.VideoCapture` ile bir kamera nesnesi oluşturulur ve bu nesne üzerinden kamera ayarları yapılarak belirtilen çözünürlüğe ayarlanır.

wCam, hCam = 640, 480
cam = cv2.VideoCapture(0)
cam.set(3, wCam)
cam.set(4, hCam)

MediaPipe Hands modelini başlatır ve belirli ayarlarla el izleme işlemine hazır hale getiriyoruz.

with mp_hands.Hands(
        model_complexity=0,
        min_detection_confidence=0.5,
        min_tracking_confidence=0.5) as hands:

Ardından bir while döngüsü başlatılır, ve bu döngü kamera (cam) açık olduğu sürece çalışır. Döngünün içinde, cam nesnesi ile kameradan bir kare okunur ve image adlı değişkene atanır. Okunan görüntü, BGR renk uzayından RGB renk uzayına dönüştürülür ve MediaPipe Hands ile işlenir.

    while cam.isOpened():
        success, image = cam.read()

        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        results = hands.process(image)
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

El izi noktaları (hand_landmarks) çizilir ve bu noktaların bağlantıları (mp_hands.HAND_CONNECTIONS) çizilir. lmList adlı bir liste oluşturulur ve el izi noktaları bu listeye eklenir. Her bir el için, el izi noktalarının ekran üzerindeki konumları hesaplanır (cx ve cy).

        if results.multi_hand_landmarks:
            for hand_landmarks in results.multi_hand_landmarks:
                mp_drawing.draw_landmarks(
                    image,
                    hand_landmarks,
                    mp_hands.HAND_CONNECTIONS,
                    mp_drawing_styles.get_default_hand_landmarks_style(),
                    mp_drawing_styles.get_default_hand_connections_style()
                )

Eğer lmList boş değilse, işaret parmağı ve orta parmağın uç noktaları (x1, y1 ve x2, y2) belirlenir ve bu noktaların etrafında daireler çizilir. Ayrıca, bu iki nokta arasındaki mesafe hesaplanır (length) ve eğer bu mesafe 50 birimden kısa ise, kullanıcının işareti yaklaştırma işareti yaptığını göstermek için kırmızı bir çizgi çizilir.

Ses seviyesi, mesafe değerine bağlı olarak np.interp fonksiyonu ile hesaplanır. Mesafe, [50, 220] aralığından ses seviyesine dönüştürülür ve bu ses seviyesi, volume.SetMasterVolumeLevel ile ayarlanır. Aynı mesafe değeri, ses seviye çubuğunun konumunu (volBar) ve yüzde cinsinden değerini (volPer) hesaplamak için kullanılır. Bu bilgiler de görüntü üzerine çizilir.

Ses seviyesi, mesafe değerine bağlı olarak np.interp fonksiyonu ile hesaplanır. Mesafe, [50, 220] aralığından ses seviyesine dönüştürülür ve bu ses seviyesi, volume.SetMasterVolumeLevel ile ayarlanır. Aynı mesafe değeri, ses seviye çubuğunun konumunu (volBar) ve yüzde cinsinden değerini (volPer) hesaplamak için kullanılır. Bu bilgiler de görüntü üzerine çizilir.

lmList = []
        if results.multi_hand_landmarks:
            myHand = results.multi_hand_landmarks[0]
            for id, lm in enumerate(myHand.landmark):
                h, w, c = image.shape
                cx, cy = int(lm.x * w), int(lm.y * h)
                lmList.append([id, cx, cy])

        if len(lmList) != 0:
            x1, y1 = lmList[4][1], lmList[4][2]
            x2, y2 = lmList[8][1], lmList[8][2]

            cv2.circle(image, (x1, y1), 15, (255, 255, 255))
            cv2.circle(image, (x2, y2), 15, (255, 255, 255))
            cv2.line(image, (x1, y1), (x2, y2), (0, 255, 0), 3)
            length = math.hypot(x2 - x1, y2 - y1)
            if length < 50:
                cv2.line(image, (x1, y1), (x2, y2), (0, 0, 255), 3)

            vol = np.interp(length, [50, 220], [minVol, maxVol])
            volume.SetMasterVolumeLevel(vol, None)#2
            volBar = np.interp(length, [50, 220], [400, 150])
            volPer = np.interp(length, [50, 220], [0, 100])
            cv2.rectangle(image, (50, 150), (85, 400), (255, 255, 255), 3)
            cv2.rectangle(image, (50, int(volBar)), (85, 400), (255, 255, 255), cv2.FILLED)
            cv2.putText(image, f'{int(volPer)} %', (40, 450), cv2.FONT_HERSHEY_COMPLEX,
                        1, (0, 0, 0), 3)

        cv2.imshow('handDetector', image)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
cam.release()

Yorumlar