File size: 3,482 Bytes
91fb4ef
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import cv2
import numpy as np
from pathlib import Path
from PIL import Image
import pillow_avif
import logging
from config import NORMALIZE_IMAGES_TO, JPEG_QUALITY

logger = logging.getLogger(__name__)

def normalize_image(input_path: Path, output_path: Path) -> bool:
    """Convert image to normalized format (PNG or JPEG) and optionally remove black bars
    
    Args:
        input_path: Source image path
        output_path: Target path
        
    Returns:
        bool: True if successful, False otherwise
    """
    try:
        # Open image with PIL
        with Image.open(input_path) as img:
            # Convert to RGB if needed
            if img.mode in ('RGBA', 'LA'):
                background = Image.new('RGB', img.size, (255, 255, 255))
                if img.mode == 'RGBA':
                    background.paste(img, mask=img.split()[3])
                else:
                    background.paste(img, mask=img.split()[1])
                img = background
            elif img.mode != 'RGB':
                img = img.convert('RGB')
            
            # Convert to numpy for black bar detection
            img_np = np.array(img)
            
            # Detect black bars
            top, bottom, left, right = detect_black_bars(img_np)
            
            # Crop if black bars detected
            if any([top > 0, bottom < img_np.shape[0] - 1, 
                   left > 0, right < img_np.shape[1] - 1]):
                img = img.crop((left, top, right, bottom))
            
            # Save as configured format
            if NORMALIZE_IMAGES_TO == 'png':
                img.save(output_path, 'PNG', optimize=True)
            else:  # jpg
                img.save(output_path, 'JPEG', quality=JPEG_QUALITY, optimize=True)
            return True
            
    except Exception as e:
        logger.error(f"Error converting image {input_path}: {str(e)}")
        return False

def detect_black_bars(img: np.ndarray) -> tuple[int, int, int, int]:
    """Detect black bars in image
    
    Args:
        img: numpy array of image (HxWxC)
        
    Returns:
        Tuple of (top, bottom, left, right) crop coordinates
    """
    # Convert to grayscale if needed
    if len(img.shape) == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    else:
        gray = img
        
    # Threshold to detect black regions
    threshold = 20
    black_mask = gray < threshold
    
    # Find black bars by analyzing row/column means
    row_means = np.mean(black_mask, axis=1)
    col_means = np.mean(black_mask, axis=0)
    
    # Detect edges where black bars end (95% threshold)
    black_threshold = 0.95
    
    # Find top and bottom crops
    top = 0
    bottom = img.shape[0]
    
    for i, mean in enumerate(row_means):
        if mean > black_threshold:
            top = i + 1
        else:
            break
            
    for i, mean in enumerate(reversed(row_means)):
        if mean > black_threshold:
            bottom = img.shape[0] - i - 1
        else:
            break
    
    # Find left and right crops
    left = 0
    right = img.shape[1]
    
    for i, mean in enumerate(col_means):
        if mean > black_threshold:
            left = i + 1
        else:
            break
            
    for i, mean in enumerate(reversed(col_means)):
        if mean > black_threshold:
            right = img.shape[1] - i - 1
        else:
            break
            
    return top, bottom, left, right