← Back to list

Mit welchem Auge blinzeln Sie mehr? Ich habe ein Python-Tool gebaut, um das herauszufinden

Haben Sie sich jemals gefragt, ob Sie mehr mit dem linken oder dem rechten Auge blinzeln? Als Computer-Vision-Enthusiast habe ich…

Mert · 2025-04-12 22:01 · 2 claps · 5.4 min read
#computer-vision #mediapipe #opencv #numpy #pygame
Open on Medium ↗
Wiki topics: RAG · RAG & Retrieval DH · Digital Health & Health Tech

Mit welchem Auge blinzeln Sie mehr? Ich habe ein Python-Tool gebaut, um das herauszufinden

Haben Sie sich jemals gefragt, ob Sie mehr mit dem linken oder dem rechten Auge blinzeln? Als Computer-Vision-Enthusiast habe ich beschlossen, diese Frage mit einem lustigen Projekt zu beantworten, das OpenCV und MediaPipe verwendet, um zu verfolgen und zu zählen, wie oft jedes Auge geschlossen ist. Dieser Blog wird Sie Schritt für Schritt durch den gesamten Prozess führen, den Code erklären und Ihnen zeigen, wie Sie das Projekt selbst bauen können.

Demo of Counting the Eye Blinker

Demo of Counting the Eye Blinker

Motivation

Die Idee kam mir, als ich über Methoden zur Erkennung von Blinzeln in Müdigkeitsstudien las. Ich stieß auf eine Methode, die das Augen-Aspekt-Verhältnis (EAR) zur Erkennung des Augenschlusses verwendet, und dachte, es wäre interessant, die Blinzler pro Auge zu zählen. Die Blinzelerkennung wird in der Regel bei Fahrerwarnsystemen oder bei der medizinischen Überwachung eingesetzt, aber ich wollte einfach experimentieren und mehr über die Echtzeitverfolgung von Gesichtsmerkmalen lernen.

Schritt 1: Installation der erforderlichen Bibliotheken

pip install opencv-python mediapipe pygame numpy

Schritt 2: Importieren der Bibliotheken

In zwei Dateien werden wir diese Bibliotheken verwenden:

  • cv2 (OpenCV) für Kamera und Bildverarbeitung
  • mediapipe für die Erkennung von Gesichtsmerkmalen
  • pygame um einen Ton abzuspielen, wenn ein Blinken erkannt wird
  • numpy für die Entfernungsberechnung

Schritt 3: Erstellen des FaceMeshModuls (Erkennung von Gesichtsmerkmalen)

Um Gesichtsmerkmale zu erkennen und die Punkte um die Augen zu extrahieren, verwenden wir das FaceMesh-Modell von MediaPipe.

# File: FaceMeshModule.py
import cv2
import mediapipe as mp

GREEN = (0, 255, 0)  # color used for drawing points

class FaceMeshDetector:
    def __init__(self, static_image_mode=False, max_num_faces=1, refine_landmarks=False, min_detection_con=0.5,
                 min_tracking_con=0.5):
        # Initialize FaceMesh with selected options
        self.mpFaceMesh = mp.solutions.face_mesh
        self.faceMesh = self.mpFaceMesh.FaceMesh(static_image_mode, max_num_faces, refine_landmarks,
                                                 min_detection_con, min_tracking_con)
        # Coordinates for the 6 key points around each eye
        self.LEFT_IRIS = [362, 385, 387, 263, 373, 380]
        self.RIGHT_IRIS = [33, 160, 158, 133, 153, 144]
        self.BOTH_IRISES = self.LEFT_IRIS + self.RIGHT_IRIS
    def findMeshIrises(self, img, draw=True, color=GREEN):
        # Convert the BGR image to RGB
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # Process the image to detect facial landmarks
        results = self.faceMesh.process(img_rgb)
        eye_landmarks = []
        faces = []
        if results.multi_face_landmarks:
            for faceLms in results.multi_face_landmarks:
                eye_landmarks = []
                face = []
                for i, lm in enumerate(faceLms.landmark):
                    if i in self.BOTH_IRISES:
                        h, w, _ = img.shape
                        x, y = int(lm.x * w), int(lm.y * h)
                        eye_landmarks.append((x, y))
                        if draw:
                            cv2.circle(img, (x, y), 1, color, -1)
                        face.append([x, y])
                faces.append(face)
        return img, faces, eye_landmarks

Schritt 4: Berechnung des Augen-Aspekt-Verhältnisses (EAR)

Um festzustellen, ob das Auge geschlossen ist, berechnen wir das Augen-Aspekt-Verhältnis anhand des euklidischen Abstands zwischen bestimmten Augenmerkpunkten.

# Calculate distance between two 2D points
def get_distance(point1, point2):
    distance = []
    for p1, p2 in zip(point1, point2):
        distance.append((p2 - p1) ** 2)
    return np.sqrt(np.sum(distance))

# Calculate Eye Aspect Ratio using 6 key eye points
def get_eye_aspect_ratio(p1, p2, p3, p4, p5, p6):
    # EAR formula: (||p2 - p6|| + ||p3 - p5||) / (2 * ||p1 - p4||)
    distance_p2_6 = get_distance(p2, p6)
    distance_p3_5 = get_distance(p3, p5)
    distance_p1_4 = get_distance(p1, p4)
    ear = (distance_p2_6 + distance_p3_5) / (2 * distance_p1_4)
    return ear

Schritt 5: Blinzelerkennung und Zähler

Die Hauptschleife liest von der Webcam, erkennt Orientierungspunkte, berechnet die EAR und zählt, wenn sich ein Auge unterhalb eines Schwellenwerts (0,15) schließt.

# File: Eyeblinker.py
import cv2
import numpy as np
import time
from FaceMeshModule import FaceMeshDetector
import pygame

pygame.init()
# # you can download it here: https://pixabay.com/sound-effects/click-124467/
click_sound = pygame.mixer.Sound(r"ThePathToTheSound")
colour = (0, 255, 0)
if __name__ == "__main__":
    cap = cv2.VideoCapture(0)  # Start webcam
    p_time = 0  # For FPS calculation
    detector = FaceMeshDetector(refine_landmarks=True)
    left_eye_counter = 0
    right_eye_counter = 0
    left_eye_opened = True
    right_eye_opened = True
    while True:
        success, img = cap.read()
        h, w, _ = img.shape
        c_time = time.time()
        fps = 1 / (c_time - p_time)
        p_time = c_time
        try:
            # Detect eye landmarks
            img, faces, eye_landmarks = detector.findMeshIrises(img, draw=True, color=colour)
            left_p = eye_landmarks[6:]   # Left eye landmarks
            right_p = eye_landmarks[:6]  # Right eye landmarks
            # Calculate EAR for both eyes
            left_eye_ear = get_eye_aspect_ratio(left_p[1], left_p[4], left_p[5], left_p[0], left_p[2], left_p[3])
            right_eye_ear = get_eye_aspect_ratio(right_p[0], right_p[5], right_p[4], right_p[1], right_p[3], right_p[2])
            # If EAR is below threshold, register blink only once while eye is closed
            if left_eye_ear < 0.15 and left_eye_opened:
                left_eye_counter += 1
                left_eye_opened = False
                pygame.mixer.Sound.play(click_sound)
            if left_eye_ear > 0.15:
                left_eye_opened = True
            if right_eye_ear < 0.15 and right_eye_opened:
                right_eye_counter += 1
                right_eye_opened = False
            if right_eye_ear > 0.15:
                right_eye_opened = True
        except Exception:
            pass
        # Show results on screen
        cv2.putText(img, f'FPS: {int(fps)}', (20, 70), cv2.FONT_HERSHEY_PLAIN, 3, colour, 1)
        cv2.putText(img, f'Left EyeCounter: {left_eye_counter}', (20, h // 2), cv2.FONT_HERSHEY_PLAIN, 1, colour, 1)
        cv2.putText(img, f'Right EyeCounter: {right_eye_counter}', (20, h // 2 + 50), cv2.FONT_HERSHEY_PLAIN, 1, colour, 1)
        cv2.imshow("Image", img)
        # Press 'q' to quit
        key = cv2.waitKey(1)
        if key == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()

Vollständiger Quellcode

Zu Ihrer Erleichterung finden Sie hier den vollständigen Code für beide Dateien:

FaceMeshModule.py

import cv2
import mediapipe as mp

GREEN = (0, 255, 0)

class FaceMeshDetector:
    def __init__(self, static_image_mode=False, max_num_faces=1, refine_landmarks=False, min_detection_con=0.5,
                 min_tracking_con=0.5):
        self.static_image_mode = static_image_mode
        self.max_num_faces = max_num_faces
        self.refine_landmarks = refine_landmarks
        self.min_detection_con = min_detection_con
        self.min_tracking_con = min_tracking_con
        self.mpDraw = mp.solutions.drawing_utils
        self.mpFaceMesh = mp.solutions.face_mesh
        self.faceMesh = self.mpFaceMesh.FaceMesh(self.static_image_mode, self.max_num_faces, self.refine_landmarks,
                                                 self.min_detection_con, self.min_tracking_con)
        # coordiantes we need for EAR, for more info see this paper:
        # https://vision.fe.uni-lj.si/cvww2016/proceedings/papers/05.pdf
        self.LEFT_IRIS = [362, 385, 387, 263, 373, 380]
        self.RIGHT_IRIS = [33, 160, 158, 133, 153, 144]
        self.BOTH_IRISES = self.LEFT_IRIS + self.RIGHT_IRIS
    def findMeshIrises(self, img, draw=True, color=GREEN):
        img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        results = self.faceMesh.process(img_rgb)
        eye_landmarks = []
        faces = []
        if results.multi_face_landmarks:
            for faceLms in results.multi_face_landmarks:
                eye_landmarks = []
                face = []
                for i, lm in enumerate(faceLms.landmark):
                    if i in self.BOTH_IRISES:
                        h, w, ic = img.shape
                        x, y = int(lm.x * w), int(lm.y * h)
                        eye_landmarks.append((x, y))
                        # cv2.putText(img, str(id), (x, y), cv2.FONT_HERSHEY_PLAIN, 1, GREEN, 1)
                        if draw:
                            cv2.circle(img, (x, y), 1, color, -1)
                        face.append([x, y])
                faces.append(face)
        return img, faces, eye_landmarks

Eyeblinker.py

import cv2
import numpy as np
import time
from FaceMeshModule import FaceMeshDetector
import pygame

pygame.init()
# you can download it here: https://pixabay.com/sound-effects/click-124467/
click_sound = pygame.mixer.Sound(
    r"C:\Users\Kleve\Downloads\click-124467.mp3")
GREEN = (0, 255, 0)
BLUE = (255, 0, 0)
RED = (0, 0, 255)
colour = GREEN

def get_distance(point1, point2):
    """
    calculate Euclidean distance between point1 and point2
    :param point1: (x, y, z) landmark of point1
    :param point2: (x, y, z) landmark of point2
    :return: Euclidean distance between point1 and point2
    """
    distance = []
    for p1, p2 in zip(point1, point2):
        distance.append((p2 - p1) ** 2)
    return np.sqrt(np.sum(distance))

def get_eye_aspect_ratio(p1, p2, p3, p4, p5, p6):
    distance_p2_6 = get_distance(p2, p6)
    distance_p3_5 = get_distance(p3, p5)
    distance_p1_4 = get_distance(p1, p4)
    ear = (distance_p2_6 + distance_p3_5) / (2 * distance_p1_4)
    return ear

if __name__ == "__main__":
    cap = cv2.VideoCapture(0)
    pTime = 0
    detector = FaceMeshDetector(refine_landmarks=True)
    left_eye_counter = 0
    right_eye_counter = 0
    left_eye_opened = True
    right_eye_opened = True
    while True:
        success, img = cap.read()
        h, w, _ = img.shape
        cTime = time.time()
        fps = 1 / (cTime - pTime)
        pTime = cTime
        try:
            img, faces, eye_landmarks = detector.findMeshIrises(img, draw=True, color=colour)
            left_p = eye_landmarks[6:]
            right_p = eye_landmarks[:6]
            left_eye_ear = get_eye_aspect_ratio(left_p[1], left_p[4], left_p[5],
                                                left_p[0], left_p[2], left_p[3])
            right_eye_ear = get_eye_aspect_ratio(right_p[0], right_p[5], right_p[4],
                                                 right_p[1], right_p[3], right_p[2])
            avg_ear = (left_eye_ear + right_eye_ear) / 2.0
            if left_eye_ear < 0.15 and left_eye_opened:
                left_eye_counter += 1
                left_eye_opened = False
                pygame.mixer.Sound.play(click_sound)
            if left_eye_ear > 0.15:
                left_eye_opened = True
            if right_eye_ear < 0.15 and right_eye_opened:
                right_eye_counter += 1
                right_eye_opened = False
            if right_eye_ear > 0.15:
                right_eye_opened = True
        except Exception:
            pass
        cv2.putText(img, f'FPS: {int(fps)}', (20, 70), cv2.FONT_HERSHEY_PLAIN, 3, colour, 1)
        cv2.putText(img, f'Left EyeCounter: {left_eye_counter}', (20, h // 2), cv2.FONT_HERSHEY_PLAIN, 1, colour, 1)
        cv2.putText(img, f'Right EyeCounter: {right_eye_counter}', (20, h // 2 + 50), cv2.FONT_HERSHEY_PLAIN, 1, colour,
                    1)
        cv2.imshow("Image", img)
        key = cv2.waitKey(1)
        if key == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()

Abschließende Gedanken

Dieses Projekt half mir, Gesichtsmerkmale und die Mathematik hinter der Augenerkennung mit EAR zu verstehen. Es hat Spaß gemacht, eine einfache Idee in ein funktionierendes Echtzeit-Tool zu verwandeln, und es hat meine Kenntnisse in OpenCV und MediaPipe vertieft.

Wenn du neugierig bist, was du sonst noch damit machen kannst, kannst du das:

  • Blinkdauer verfolgen
  • Schätzung des Ermüdungsgrads hinzufügen
  • Visualisierung von Blinzelmustern im Zeitverlauf
  • Erweitern Sie es für die Arbeit auf dem Handy oder im Web

Fühlen Sie sich frei, das Projekt auf GitHub zu forken und es selbst auszuprobieren!

Vielen Dank fürs Lesen! Wenn dir dieser Beitrag gefallen hat oder du Fragen hast, lass es mich in den Kommentaren wissen 😊.


메타데이터
post_id
ffa5e2cc8f44
slug
mit-welchem-auge-blinzeln-sie-mehr-ich-habe-ein-python-tool-gebaut-um-das-herauszufinden-ffa5e2cc8f44
url
https://medium.com/@Mert.A/mit-welchem-auge-blinzeln-sie-mehr-ich-habe-ein-python-tool-gebaut-um-das-herauszufinden-ffa5e2cc8f44
canonical_url
https://medium.com/@Mert.A/mit-welchem-auge-blinzeln-sie-mehr-ich-habe-ein-python-tool-gebaut-um-das-herauszufinden-ffa5e2cc8f44
author_url
https://medium.com/@Mert.A
status
ok
fetched_at
2026-07-20 08:15:26