| |
| """ |
| SamplePreprocessor_Hindi.py β MODERATE AUGMENTATION VERSION |
| ---------------------------------------------------------- |
| Balanced augmentation that prevents overfitting WITHOUT making images unreadable. |
| |
| KEY PRINCIPLE: Model must be able to LEARN from augmented images! |
| - Apply only 1-2 augmentations per image (not 5+) |
| - Lower probabilities (20-30% instead of 40-60%) |
| - Gentler strength (Β±3Β° instead of Β±5Β°) |
| """ |
|
|
| from __future__ import division |
| from __future__ import print_function |
|
|
| import random |
| import numpy as np |
| import cv2 |
|
|
|
|
| def preprocess(img: np.ndarray, |
| imgSize: tuple, |
| dataAugmentation: bool = False) -> np.ndarray: |
| """ |
| Preprocess with MODERATE augmentation. |
| |
| Strategy: Apply 1-2 augmentations per image, not 5+ |
| This prevents overfitting while keeping images learnable. |
| """ |
|
|
| if img is None: |
| img = np.zeros([imgSize[1], imgSize[0]], dtype=np.uint8) |
|
|
| |
| if dataAugmentation: |
| |
| |
| num_augs = random.choice([0, 1, 1, 2]) |
| available_augs = ['rotate', 'brightness', 'blur', 'noise', 'scale', 'contrast'] |
| selected_augs = random.sample(available_augs, min(num_augs, len(available_augs))) |
| |
| |
| if 'rotate' in selected_augs: |
| angle = random.uniform(-3.0, 3.0) |
| h, w = img.shape |
| M = cv2.getRotationMatrix2D((w // 2, h // 2), angle, 1.0) |
| img = cv2.warpAffine(img, M, (w, h), borderMode=cv2.BORDER_REPLICATE) |
|
|
| |
| if 'brightness' in selected_augs: |
| delta = random.uniform(-20, 20) |
| img = np.clip(img.astype(np.float32) + delta, 0, 255).astype(np.uint8) |
| |
| |
| if 'contrast' in selected_augs: |
| factor = random.uniform(0.8, 1.2) |
| img = np.clip((img.astype(np.float32) - 127.5) * factor + 127.5, |
| 0, 255).astype(np.uint8) |
|
|
| |
| if 'blur' in selected_augs: |
| kernel_size = 3 |
| sigma = random.uniform(0.3, 1.0) |
| img = cv2.GaussianBlur(img, (kernel_size, kernel_size), sigma) |
|
|
| |
| if 'noise' in selected_augs: |
| std = random.uniform(3, 8) |
| noise = np.random.normal(0, std, img.shape).astype(np.float32) |
| img = np.clip(img.astype(np.float32) + noise, 0, 255).astype(np.uint8) |
|
|
| |
| if 'scale' in selected_augs: |
| scale = random.uniform(0.9, 1.1) |
| h, w = img.shape |
| new_h = max(1, int(h * scale)) |
| new_w = max(1, int(w * scale)) |
| img = cv2.resize(img, (new_w, new_h)) |
|
|
| |
| (wt, ht) = imgSize |
| (h, w) = img.shape |
|
|
| f = max(w / wt, h / ht) |
| new_w = max(1, min(wt, int(w / f))) |
| new_h = max(1, min(ht, int(h / f))) |
|
|
| img = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_AREA) |
|
|
| |
| canvas = np.ones([ht, wt], dtype=np.uint8) * 255 |
| canvas[0:new_h, 0:new_w] = img |
|
|
| |
| transposed = cv2.transpose(canvas) |
|
|
| |
| (m, s) = cv2.meanStdDev(transposed) |
| m = m[0][0] |
| s = s[0][0] |
| normalised = (transposed - m) / (s + 1e-8) |
|
|
| return normalised.astype(np.float32) |
|
|