| import cv2 |
| import numpy as np |
| import torch |
|
|
| def apply_phase1_hardening(patch, landmarks, apply_dropout=True, apply_denoise=True, apply_clahe=True, apply_noise=True, apply_jitter=True): |
| """ |
| Applies Domain Adaptation Phase 1 (Data Hardening) to a single sample. |
| patch: (4, H, W) numpy array, uint8 |
| landmarks: (N, 2) or (956,) numpy array |
| """ |
| processed_patch = patch.copy() |
| processed_landmarks = landmarks.copy() |
| |
| |
| if apply_dropout and np.random.rand() > 0.5: |
| h, w = processed_patch.shape[1], processed_patch.shape[2] |
| for i in range(4): |
| |
| small = cv2.resize(processed_patch[i], (8, 8), interpolation=cv2.INTER_CUBIC) |
| processed_patch[i] = cv2.resize(small, (w, h), interpolation=cv2.INTER_CUBIC) |
|
|
| |
| if apply_denoise: |
| for i in range(4): |
| processed_patch[i] = cv2.bilateralFilter(processed_patch[i], 5, 20, 20) |
|
|
| |
| if apply_clahe: |
| clahe = cv2.createCLAHE(clipLimit=1.1, tileGridSize=(4, 4)) |
| for i in range(4): |
| processed_patch[i] = clahe.apply(processed_patch[i]) |
|
|
| |
| if apply_noise and np.random.rand() > 0.5: |
| noise = np.random.normal(0, 3, processed_patch.shape).astype(np.float32) |
| processed_patch = np.clip(processed_patch.astype(np.float32) + noise, 0, 255).astype(np.uint8) |
|
|
| |
| if apply_jitter and np.random.rand() > 0.5: |
| noise_lm = np.random.normal(0, 0.003, processed_landmarks.shape).astype(np.float32) |
| processed_landmarks = processed_landmarks + noise_lm |
|
|
| return processed_patch, processed_landmarks |
|
|
| def preprocess_for_model(patch, landmarks): |
| """ |
| Final conversion to torch tensors and normalization. |
| """ |
| patch_tensor = torch.from_numpy(patch).float() / 255.0 |
| landmarks_tensor = torch.from_numpy(landmarks).float().view(-1) |
| return patch_tensor, landmarks_tensor |
|
|