File size: 3,906 Bytes
b42373a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import os
import json

CONFIG_PATH = "config.json"

def load_config():
    if os.path.exists(CONFIG_PATH):
        with open(CONFIG_PATH) as f:
            return json.load(f)
    return {
        "preprocessing": {
            "clahe_clip": 3.0,
            "clahe_grid": 8,
            "bilateral_d": 9,
            "bilateral_sigma": 75,
            "adaptive_blocksize": 21,
            "adaptive_c": 8
        }
    }


def correct_rotation(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) if len(img.shape) == 3 else img
    edges = cv2.Canny(gray, 50, 150)
    lines = cv2.HoughLinesP(edges, 1, np.pi/180, 50, minLineLength=30, maxLineGap=10)
    if lines is None:
        return img
    angles = [np.degrees(np.arctan2(l[0][3]-l[0][1], l[0][2]-l[0][0])) for l in lines]
    if abs(np.median(angles)) > 45:
        img = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
    return img


def preprocess_chassis(image_path, save_comparison=False, output_dir="results"):
    config = load_config()
    p = config["preprocessing"]

    img = cv2.imread(image_path)
    if img is None:
        raise ValueError(f"Could not load image: {image_path}")

    original = img.copy()
    img = correct_rotation(img)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    clahe = cv2.createCLAHE(
        clipLimit=p["clahe_clip"],
        tileGridSize=(p["clahe_grid"], p["clahe_grid"])
    )
    enhanced = clahe.apply(gray)

    v0 = cv2.cvtColor(enhanced, cv2.COLOR_GRAY2BGR)

    filtered = cv2.bilateralFilter(enhanced, p["bilateral_d"],
                                   p["bilateral_sigma"], p["bilateral_sigma"])
    v1 = cv2.cvtColor(filtered, cv2.COLOR_GRAY2BGR)

    _, otsu = cv2.threshold(filtered, 0, 255,
                            cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    v2 = cv2.cvtColor(otsu, cv2.COLOR_GRAY2BGR)

    bs = p["adaptive_blocksize"]
    bs = bs if bs % 2 == 1 else bs + 1
    adaptive = cv2.adaptiveThreshold(
        filtered, 255,
        cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
        cv2.THRESH_BINARY,
        blockSize=bs, C=p["adaptive_c"]
    )
    v3 = cv2.cvtColor(adaptive, cv2.COLOR_GRAY2BGR)

    pad = p.get("padding", 20)
    def add_padding(im):
        return cv2.copyMakeBorder(im, pad, pad, pad, pad,
                                  cv2.BORDER_CONSTANT, value=(255, 255, 255))

    variations = [add_padding(v) for v in [v0, v1, v2, v3]]

    if save_comparison:
        os.makedirs(output_dir, exist_ok=True)
        fname = os.path.splitext(os.path.basename(image_path))[0]
        h = 200

        def resize_h(im, height):
            r = height / im.shape[0]
            return cv2.resize(im, (int(im.shape[1] * r), height))

        def add_label(im, label):
            out = im.copy() if len(im.shape) == 3 else cv2.cvtColor(im, cv2.COLOR_GRAY2BGR)
            cv2.putText(out, label, (10, 25), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
            return out

        def to_bgr(p):
            return p if len(p.shape) == 3 else cv2.cvtColor(p, cv2.COLOR_GRAY2BGR)

        panels = [add_label(resize_h(cv2.cvtColor(original, cv2.COLOR_BGR2GRAY), h), "Original")]
        labels = ["CLAHE", "Bilateral", "Otsu", "Adaptive"]
        for i, var in enumerate(variations):
            g = cv2.cvtColor(var, cv2.COLOR_BGR2GRAY)
            panels.append(add_label(resize_h(g, h), labels[i]))

        comparison = np.hstack([to_bgr(p) for p in panels])
        cv2.imwrite(os.path.join(output_dir, f"{fname}_comparison.jpg"), comparison)
        print(f"  Saved comparison -> {output_dir}/{fname}_comparison.jpg")

    return variations


if __name__ == "__main__":
    import sys
    if len(sys.argv) < 2:
        print("Usage: python preprocess.py <image_path>")
    else:
        variations = preprocess_chassis(sys.argv[1], save_comparison=True)
        print(f"Generated {len(variations)} variations — check results/")