| import cv2 |
| import numpy as np |
| import os |
| import sys |
| from pathlib import Path |
|
|
| |
| sys.path.append(str(Path(__file__).parent.parent)) |
|
|
| from src.utils.preprocess import GazePreprocessor |
|
|
| def create_visualization(image_path, output_path): |
| print(f"Processing image: {image_path}") |
| frame = cv2.imread(image_path) |
| if frame is None: |
| print(f"Error: Could not read image at {image_path}") |
| return False |
| |
| h, w, _ = frame.shape |
| |
| target_w = 1024 |
| scale = target_w / w |
| frame_resized = cv2.resize(frame, (target_w, int(h * scale))) |
| rh, rw, _ = frame_resized.shape |
| |
| preprocessor = GazePreprocessor(model_path='src/utils/face_landmarker.task') |
| |
| |
| landmarks = preprocessor.get_landmarks(frame) |
| if landmarks is None: |
| print("No face detected in the image.") |
| return False |
|
|
| |
| |
| left_eye_norm, _ = preprocessor.normalize_eye(frame, landmarks, 'left', target_size=(64, 32)) |
| right_eye_norm, _ = preprocessor.normalize_eye(frame, landmarks, 'right', target_size=(64, 32)) |
| |
| |
| |
| left_patches = preprocessor.extract_patches(left_eye_norm, patch_size=16) |
| right_patches = preprocessor.extract_patches(right_eye_norm, patch_size=16) |
|
|
| |
| vis_frame = frame_resized.copy() |
| |
| |
| for lm in landmarks: |
| x, y = int(lm.x * rw), int(lm.y * rh) |
| cv2.circle(vis_frame, (x, y), 1, (0, 255, 0), -1) |
| |
| |
| left_c_norm = np.mean([[landmarks[idx].x, landmarks[idx].y] for idx in preprocessor.LEFT_CORNERS], axis=0) |
| right_c_norm = np.mean([[landmarks[idx].x, landmarks[idx].y] for idx in preprocessor.RIGHT_CORNERS], axis=0) |
| |
| lc = (int(left_c_norm[0] * rw), int(left_c_norm[1] * rh)) |
| rc = (int(right_c_norm[0] * rw), int(right_c_norm[1] * rh)) |
| |
| |
| dx, dy = 80, -30 |
| cv2.arrowedLine(vis_frame, lc, (lc[0] + dx, lc[1] + dy), (0, 255, 255), 3, tipLength=0.3) |
| cv2.arrowedLine(vis_frame, rc, (rc[0] + dx, rc[1] + dy), (0, 255, 255), 3, tipLength=0.3) |
|
|
| |
| |
| def create_patch_grid(patches, size=16, display_size=120): |
| |
| grid = np.zeros((size*2, size*2), dtype=np.uint8) |
| grid[0:size, 0:size] = patches[0] |
| grid[0:size, size:size*2] = patches[1] |
| grid[size:size*2, 0:size] = patches[2] |
| grid[size:size*2, size:size*2] = patches[3] |
| |
| |
| grid_colored = cv2.cvtColor(grid, cv2.COLOR_GRAY2BGR) |
| grid_enlarged = cv2.resize(grid_colored, (display_size, display_size), interpolation=cv2.INTER_NEAREST) |
| |
| |
| cv2.rectangle(grid_enlarged, (0, 0), (display_size-1, display_size-1), (255, 255, 255), 2) |
| return grid_enlarged |
|
|
| left_grid = create_patch_grid(left_patches, size=16, display_size=160) |
| right_grid = create_patch_grid(right_patches, size=16, display_size=160) |
|
|
| |
| pad = 20 |
| |
| vis_frame[pad:pad+160, rw-160-pad:rw-pad] = right_grid |
| cv2.putText(vis_frame, "Right Eye (16x16 Patches)", (rw-160-pad, pad+160+20), |
| cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 255, 255), 1) |
|
|
| |
| vis_frame[pad:pad+160, pad:pad+160] = left_grid |
| cv2.putText(vis_frame, "Left Eye (16x16 Patches)", (pad, pad+160+20), |
| cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 255, 255), 1) |
|
|
| |
| overlay = vis_frame.copy() |
| cv2.rectangle(overlay, (0, rh-60), (rw, rh), (0, 0, 0), -1) |
| cv2.addWeighted(overlay, 0.6, vis_frame, 0.4, 0, vis_frame) |
| |
| cv2.putText(vis_frame, "LIPE V2: Dual-State Pipeline | 16x16 Patch Embedder | Landmark-Guided Gaze", |
| (30, rh-25), cv2.FONT_HERSHEY_DUPLEX, 0.6, (255, 255, 255), 1) |
|
|
| cv2.imwrite(output_path, vis_frame) |
| print(f"New visualization saved to {output_path}") |
| return True |
|
|
| if __name__ == "__main__": |
| candidates = [] |
| |
| mpii_base = Path("data/MPIIGaze/MPIIGaze/MPIIGaze/Data/Original/p00/day01") |
| if mpii_base.exists(): |
| candidates += list(mpii_base.glob("000*.jpg"))[:10] |
| |
| candidates += list(Path("data/verification").glob("sample_*.png")) |
| |
| dest = "report/image/lipe_v2_16x16_viz.png" |
| os.makedirs(os.path.dirname(dest), exist_ok=True) |
| |
| success = False |
| for src in candidates: |
| if src.exists(): |
| if create_visualization(str(src), dest): |
| success = True |
| break |
| |
| if not success: |
| print("Error: Could not create visualization.") |
|
|