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…
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
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 Bildverarbeitungmediapipefür die Erkennung von Gesichtsmerkmalenpygameum einen Ton abzuspielen, wenn ein Blinken erkannt wirdnumpyfü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