ocr / augment.py
borreooo's picture
Add project files
b42373a
Raw
History Blame Contribute Delete
4.72 kB
import os
import cv2
import json
import numpy as np
import albumentations as A
from barcode_scanner import scan_all_barcodes
BARCODE_DIR = "images/barcode"
CHASSIS_DIR = "images/chassis"
OUTPUT_DIR = "images/chassis_augmented"
GT_PATH = "ground_truth.json"
AUGMENTS_PER_IMAGE = 25
def get_augmentation_pipeline():
return A.Compose([
A.OneOf([
A.RandomBrightnessContrast(
brightness_limit=0.4,
contrast_limit=0.4,
p=1.0
),
A.RandomGamma(gamma_limit=(60, 140), p=1.0),
A.CLAHE(clip_limit=4.0, p=1.0),
], p=0.9),
A.OneOf([
A.RandomShadow(
shadow_roi=(0, 0, 1, 1),
num_shadows_lower=1,
num_shadows_upper=2,
shadow_dimension=4,
p=1.0
),
A.RandomSunFlare(
flare_roi=(0, 0, 1, 0.5),
angle_lower=0,
src_radius=80,
p=1.0
),
], p=0.5),
A.OneOf([
A.MotionBlur(blur_limit=(3, 7), p=1.0),
A.GaussianBlur(blur_limit=(3, 5), p=1.0),
A.MedianBlur(blur_limit=3, p=1.0),
], p=0.4),
A.OneOf([
A.GaussNoise(var_limit=(10, 50), p=1.0),
A.ISONoise(color_shift=(0.01, 0.05), intensity=(0.1, 0.5), p=1.0),
A.MultiplicativeNoise(multiplier=(0.9, 1.1), p=1.0),
], p=0.6),
A.OneOf([
A.Perspective(scale=(0.02, 0.08), p=1.0),
A.ShiftScaleRotate(
shift_limit=0.05,
scale_limit=0.1,
rotate_limit=10,
border_mode=cv2.BORDER_REPLICATE,
p=1.0
),
A.ElasticTransform(
alpha=30,
sigma=5,
alpha_affine=5,
border_mode=cv2.BORDER_REPLICATE,
p=1.0
),
], p=0.7),
A.OneOf([
A.ImageCompression(quality_lower=60, quality_upper=95, p=1.0),
A.Downscale(scale_min=0.5, scale_max=0.9, p=1.0),
], p=0.3),
A.OneOf([
A.CoarseDropout(
max_holes=8,
max_height=2,
max_width=30,
min_holes=2,
fill_value=128,
p=1.0
),
A.GridDistortion(num_steps=5, distort_limit=0.1, p=1.0),
], p=0.4),
])
def augment_dataset():
os.makedirs(OUTPUT_DIR, exist_ok=True)
print("[1/3] Loading ground truth from barcodes...")
ground_truths = scan_all_barcodes(BARCODE_DIR)
ground_truths = {k: v for k, v in ground_truths.items() if v}
print(f" Got {len(ground_truths)} labeled pairs")
chassis_files = sorted([
f for f in os.listdir(CHASSIS_DIR)
if f.lower().endswith(('.jpg', '.jpeg', '.png'))
and os.path.splitext(f)[0] in ground_truths
])
print(f" Found {len(chassis_files)} chassis images with labels")
pipeline = get_augmentation_pipeline()
augmented_gt = {}
total = 0
print(f"\n[2/3] Augmenting — {AUGMENTS_PER_IMAGE} variations per image...")
for fname in chassis_files:
key = os.path.splitext(fname)[0]
label = ground_truths[key]
img_path = os.path.join(CHASSIS_DIR, fname)
img = cv2.imread(img_path)
if img is None:
print(f" [SKIP] Could not read {fname}")
continue
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
orig_name = f"{key}_orig.jpg"
cv2.imwrite(os.path.join(OUTPUT_DIR, orig_name), img)
augmented_gt[orig_name] = label
total += 1
for i in range(AUGMENTS_PER_IMAGE):
try:
augmented = pipeline(image=img_rgb)["image"]
aug_bgr = cv2.cvtColor(augmented, cv2.COLOR_RGB2BGR)
aug_name = f"{key}_aug{i:03d}.jpg"
cv2.imwrite(os.path.join(OUTPUT_DIR, aug_name), aug_bgr)
augmented_gt[aug_name] = label
total += 1
except Exception as e:
print(f" [WARN] Augmentation failed for {fname} variation {i}: {e}")
print(f" {key} -> {AUGMENTS_PER_IMAGE + 1} images (label: {label})")
with open(GT_PATH, "w") as f:
json.dump(augmented_gt, f, indent=2)
print(f"\n[3/3] Done!")
print(f" Total images generated : {total}")
print(f" Saved to : {OUTPUT_DIR}/")
print(f" Ground truth saved to : {GT_PATH}")
print(f"\nNext step: use these images to fine-tune PaddleOCR")
if __name__ == "__main__":
augment_dataset()