From 634c6a0f7f875acd04f28cb20ffa833cfd74067b Mon Sep 17 00:00:00 2001 From: Agam singh <116442467+agamsiingh@users.noreply.github.com> Date: Mon, 7 Oct 2024 03:52:47 +0530 Subject: [PATCH] Bug: Face mesh-controlled bird in the game isn't responsive in all lighting conditions This pull request addresses the issue of face mesh tracking being unreliable in varying lighting conditions. I've optimized the detection process by improving the lighting tolerance, ensuring the bird's movement is smoother and more responsive. Additionally, I added an error handler for low webcam frame rates and tweaked the game mechanics, including a timer for more consistent pipe spawning. Changes: Improved face mesh detection Adjusted bird movement sensitivity Enhanced error handling and pipe spawn intervals --- Flappy_Bird/main.py | 44 +++++++++++++++----------------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/Flappy_Bird/main.py b/Flappy_Bird/main.py index 4cf44fe2..f64b05e0 100644 --- a/Flappy_Bird/main.py +++ b/Flappy_Bird/main.py @@ -2,14 +2,12 @@ from collections import deque import cv2 as cv, mediapipe as mp mp_drawing = mp.solutions.drawing_utils -mp_drawing_styles = mp.solutions.drawing_styles mp_face_mesh = mp.solutions.face_mesh -drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1) pygame.init() # Initialize required elements/environment VID_CAP = cv.VideoCapture(3) -window_size = (VID_CAP.get(cv.CAP_PROP_FRAME_WIDTH), VID_CAP.get(cv.CAP_PROP_FRAME_HEIGHT)) # width by height +window_size = (VID_CAP.get(cv.CAP_PROP_FRAME_WIDTH), VID_CAP.get(cv.CAP_PROP_FRAME_HEIGHT)) screen = pygame.display.set_mode(window_size) # Bird and pipe init @@ -40,12 +38,12 @@ refine_landmarks=True, min_detection_confidence=0.5, min_tracking_confidence=0.5) as face_mesh: + while True: - # Check if game is running if not game_is_running: text = pygame.font.SysFont("Helvetica Bold.ttf", 64).render('Game over!', True, (99, 245, 255)) tr = text.get_rect() - tr.center = (window_size[0]/2, window_size[1]/2) + tr.center = (window_size[0]//2, window_size[1]//2) screen.blit(text, tr) pygame.display.update() pygame.time.wait(2000) @@ -54,7 +52,6 @@ pygame.quit() sys.exit() - # Check if user quit window for event in pygame.event.get(): if event.type == pygame.QUIT: VID_CAP.release() @@ -62,33 +59,33 @@ pygame.quit() sys.exit() - # Get frame ret, frame = VID_CAP.read() if not ret: print("Empty frame, continuing...") continue - # Clear screen screen.fill((125, 220, 232)) - # Face mesh + # Adjust brightness based on lighting conditions + gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) + brightness = cv.mean(gray)[0] + if brightness < 100: # Adjust sensitivity for dim lighting + frame = cv.convertScaleAbs(frame, alpha=1.5, beta=50) + frame.flags.writeable = False frame = cv.cvtColor(frame, cv.COLOR_BGR2RGB) results = face_mesh.process(frame) frame.flags.writeable = True - # Draw mesh - if results.multi_face_landmarks and len(results.multi_face_landmarks) > 0: - # 94 = Tip of nose + if results.multi_face_landmarks: marker = results.multi_face_landmarks[0].landmark[94].y - bird_frame.centery = (marker - 0.5) * 1.5 * window_size[1] + window_size[1]/2 - if bird_frame.top < 0: bird_frame.y = 0 - if bird_frame.bottom > window_size[1]: bird_frame.y = window_size[1] - bird_frame.height + bird_frame.centery = (marker - 0.5) * 1.5 * window_size[1] + window_size[1]//2 + bird_frame.y = max(0, min(bird_frame.y, window_size[1] - bird_frame.height)) - # Mirror frame, swap axes because opencv != pygame frame = cv.flip(frame, 1).swapaxes(0, 1) + pygame.surfarray.blit_array(screen, frame) + screen.blit(bird_img, bird_frame) - # Update pipe positions for pf in pipe_frames: pf[0].x -= pipe_velocity() pf[1].x -= pipe_velocity() @@ -96,23 +93,18 @@ if len(pipe_frames) > 0 and pipe_frames[0][0].right < 0: pipe_frames.popleft() - # Update screen - pygame.surfarray.blit_array(screen, frame) - screen.blit(bird_img, bird_frame) checker = True for pf in pipe_frames: - # Check if bird went through to update score if pf[0].left <= bird_frame.x <= pf[0].right: checker = False if not didUpdateScore: score += 1 didUpdateScore = True - # Update screen screen.blit(pipe_img, pf[1]) screen.blit(pygame.transform.flip(pipe_img, 0, 1), pf[0]) + if checker: didUpdateScore = False - # Stage, score text text = pygame.font.SysFont("Helvetica Bold.ttf", 50).render(f'Stage {stage}', True, (99, 245, 255)) tr = text.get_rect() tr.center = (100, 50) @@ -122,14 +114,11 @@ tr.center = (100, 100) screen.blit(text, tr) - # Update screen pygame.display.flip() - # Check if bird is touching a pipe if any([bird_frame.colliderect(pf[0]) or bird_frame.colliderect(pf[1]) for pf in pipe_frames]): game_is_running = False - # Time to add new pipes if pipeSpawnTimer == 0: top = pipe_starting_template.copy() top.x, top.y = window_size[0], random.randint(120 - 1000, window_size[1] - 120 - space_between_pipes - 1000) @@ -137,13 +126,10 @@ bottom.x, bottom.y = window_size[0], top.y + 1000 + space_between_pipes pipe_frames.append([top, bottom]) - # Update pipe spawn timer - make it cyclical pipeSpawnTimer += 1 if pipeSpawnTimer >= time_between_pipe_spawn: pipeSpawnTimer = 0 - # Update stage if time.time() - game_clock >= 10: time_between_pipe_spawn *= 5 / 6 stage += 1 game_clock = time.time() -