Project

General

Profile

Code » History » Version 7

Faiq Sayyidan SETIAWAN, 10/31/2024 02:16 PM

1 1 Faiq Sayyidan SETIAWAN
---
2
3 6 Faiq Sayyidan SETIAWAN
*[[/|Home]]*   |   *[[Team Members]]*   |   *[[Project Description]]*   |   *[[Code]]*   |   *[[UML Diagrams]]*   |   *[[Results]]*   |
4 1 Faiq Sayyidan SETIAWAN
5
---
6 2 Faiq Sayyidan SETIAWAN
7
h1=. <pre>
8 3 Faiq Sayyidan SETIAWAN
Code </pre>
9 4 Faiq Sayyidan SETIAWAN
10
h2. alpha_blending_v2.py: everything
11
12
<pre><code class="python">
13
import tkinter as tk
14
15
from tkinter import filedialog, messagebox
16
17
from tkinter import ttk
18
19
import configparser
20
21
import cv2
22
23
import numpy as np
24
25
import os
26
27
import logging
28
29
from PIL import Image, ImageTk
30
31
# Setup logging
32
33
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
34
35
# ConfigReader class definition
36
37
class ConfigReader:
38
39 7 Faiq Sayyidan SETIAWAN
    def __init__(self, config_path=None):
40
        # Assume some initialization using config_path
41
        self.config_path = config_path
42
        # Add other initialization logic here
43 1 Faiq Sayyidan SETIAWAN
        self.config_parser = configparser.ConfigParser()
44 7 Faiq Sayyidan SETIAWAN
        if config_path is not None and os.path.exists(config_path):
45
            self.config_parser.read(config_path)
46 4 Faiq Sayyidan SETIAWAN
47
    def getImageName(self):
48
49
        return str(self.config_parser['DEFAULT']['image_name'])
50
51
    def getProjectedImageWidth(self):
52
53
        return int(self.config_parser['DEFAULT']['projected_image_width'])
54
55
    def getProjectedOverlapWidth(self):
56
57
        return int(self.config_parser['DEFAULT']['projected_overlap_width'])
58
59
    def getGamma(self):
60
61
        return float(self.config_parser['DEFAULT']['gamma'])
62
63
    def getImageSide(self):
64
65
        return int(self.config_parser['DEFAULT']['image_side'])
66
67 1 Faiq Sayyidan SETIAWAN
    def getTransparencyFactor(self):
68
69
        return float(self.config_parser['DEFAULT'].get('transparency_factor', 1.0))
70
71 7 Faiq Sayyidan SETIAWAN
    def setParameters(self, parameters):
72
        # The parameters is a dictionary with key-value pairs
73
        if 'DEFAULT' not in self.config_parser:
74
            self.config_parser['DEFAULT'] = {}
75
        
76
        for key, value in parameters.items():
77
            self.config_parser['DEFAULT'][key] = str(value)
78
79
    def save_config(self, path):
80
        with open(path, 'w') as configfile:
81
            self.config_parser.write(configfile)
82
83
84 4 Faiq Sayyidan SETIAWAN
# MainDisplay class definition
85
86
class MainDisplay:
87
88
    def readImage(self, image_path):
89
90
        # Loads an image from the specified path with 3 channels (BGR)
91
92
        image = cv2.imread(image_path, cv2.IMREAD_COLOR)
93
94
        if image is None:
95
96
            logging.error(f"Error loading image at {image_path}")
97
98
        else:
99
100
            logging.info(f"Loaded image {image_path} with shape: {image.shape}")
101
102
        return image
103
104
    def setImage(self, image):
105
106
        # Placeholder for image processing if necessary
107
108
        # Here you can modify or prepare the image before displaying
109
110
        logging.info(f"Setting image with shape: {image.shape}")
111
112
        return image
113
114
# MaskCreator class definition
115
116
class MaskCreator:
117
118
    def __init__(self, image, transparency_factor):
119
120
        self.__image = image
121
122
        self.__alpha_gradient = None
123
124
        self.__gamma_corrected = None
125
126
        self.result_image = None
127
128
        self.__mask = None
129
130
        self.transparency_factor = transparency_factor
131
132
    def smoothstep(self, edge0, edge1, x):
133
134
        # Smoothstep function for smoother transition (non-linear gradient)
135
136
        x = np.clip((x - edge0) / (edge1 - edge0), 0, 1)
137
138
        return x * x * (3 - 2 * x)
139
140
    def create_mask(self, image_side, mask_width, image_width):
141
142
        self.__mask = self.__image.shape[1] * mask_width // image_width
143
144
        gradient = np.linspace(0, 1, self.__mask)
145
146
        # Apply smoothstep to create a smoother gradient
147
148
        smooth_gradient = self.smoothstep(0, 1, gradient)
149
150
        # Apply transparency factor to adjust the strength of the blending
151
152
        smooth_gradient = smooth_gradient * self.transparency_factor
153
154
        if image_side == 1:
155
156
            # Gradient from transparent to opaque (middle to right)
157
158
            self.__alpha_gradient = smooth_gradient
159
160
        elif image_side == 0:
161
162
            # Gradient from opaque to transparent (left to middle)
163
164
            self.__alpha_gradient = smooth_gradient[::-1]  # Reverse for the left side
165
166
    def gammaCorrection(self, gamma):
167
168
        # Apply gamma correction
169
170
        inv_gamma = 1.0 / gamma
171
172
        table = np.array([((i / 255.0) ** inv_gamma) * 255
173
174
                          for i in np.arange(256)]).astype("uint8")
175
176
        self.__gamma_corrected = cv2.LUT(self.__image, table)
177
178
        logging.info(f"Applied gamma correction with gamma={gamma}")
179
180
        # Save gamma corrected image for inspection
181
182
        cv2.imwrite("gamma_corrected.png", self.__gamma_corrected)
183
184
    def alpha_blending(self, image_side):
185
186
        """
187
188
        Applies alpha blending on the gamma-corrected image.
189
190
        Combines the gamma-corrected part of the image with a black background using the alpha gradient mask.
191
192
        """
193
194
        # Initialize result_image to be the gamma-corrected image
195
196
        self.result_image = self.__gamma_corrected.copy()
197
198
        if image_side == 1:  # Right side
199
200
            # Create a region of interest (ROI) where blending will occur (right side of the image)
201
202
            roi = self.result_image[:, :self.__mask].astype(np.float32)
203
204
            # Create black background for blending
205
206
            black_background = np.zeros_like(roi, dtype=np.float32)
207
208
            # Apply the alpha mask to blend gamma-corrected image with black background
209
210
            alpha = self.__alpha_gradient.reshape(1, -1, 1).astype(np.float32)
211
212
            blended = (alpha * roi + (1 - alpha) * black_background)
213
214
            blended = np.clip(blended, 0, 255).astype(np.uint8)
215
216
            # Place the blended region back in the result image
217
218
            self.result_image[:, :self.__mask] = blended
219
220
            logging.info(f"Applied alpha blending on the right side with mask width {self.__mask}")
221
222
            # Save blended region for debugging
223
224
            cv2.imwrite("blended_right_side.png", blended)
225
226
        elif image_side == 0:  # Left side
227
228
            # Create a region of interest (ROI) where blending will occur (left side of the image)
229
230
            roi = self.result_image[:, -self.__mask:].astype(np.float32)
231
232
            # Create black background for blending
233
234
            black_background = np.zeros_like(roi, dtype=np.float32)
235
236
            # Apply the alpha mask to blend gamma-corrected image with black background
237
238
            alpha = self.__alpha_gradient.reshape(1, -1, 1).astype(np.float32)
239
240
            blended = (alpha * roi + (1 - alpha) * black_background)
241
242
            blended = np.clip(blended, 0, 255).astype(np.uint8)
243
244
            # Place the blended region back in the result image
245
246
            self.result_image[:, -self.__mask:] = blended
247
248
            logging.info(f"Applied alpha blending on the left side with mask width {self.__mask}")
249 1 Faiq Sayyidan SETIAWAN
250
            # Save blended region for debugging
251
252
            cv2.imwrite("blended_left_side.png", blended)
253 4 Faiq Sayyidan SETIAWAN
254
255 7 Faiq Sayyidan SETIAWAN
def process_image(image_path, params, main_display):
256 1 Faiq Sayyidan SETIAWAN
    """
257 7 Faiq Sayyidan SETIAWAN
    Processes an image based on the provided parameters.
258 1 Faiq Sayyidan SETIAWAN
259
    Args:
260 7 Faiq Sayyidan SETIAWAN
        image_path (str): Path to the image file.
261
        params (dict): Parameters for image processing.
262 4 Faiq Sayyidan SETIAWAN
        main_display (MainDisplay): Instance of MainDisplay for image operations.
263
264
    Returns:
265
        tuple: Processed image and its corresponding name.
266 1 Faiq Sayyidan SETIAWAN
    """
267 4 Faiq Sayyidan SETIAWAN
268 7 Faiq Sayyidan SETIAWAN
    # Retrieve parameters from params dictionary
269
    mask_width = params.get('projected_overlap_width')
270
    image_width = params.get('projected_image_width')
271
    gamma = params.get('gamma')
272
    image_side = params.get('image_side')
273
    transparency_factor = params.get('transparency_factor')
274 4 Faiq Sayyidan SETIAWAN
275
    # Determine image side name
276
    if image_side == 0:
277
        image_name = 'left'
278
    elif image_side == 1:
279
        image_name = 'right'
280
    else:
281 7 Faiq Sayyidan SETIAWAN
        logging.error(f"Invalid ImageSide value. Use 0 for left image, 1 for right image.")
282 4 Faiq Sayyidan SETIAWAN
        return None, None
283
284
    # Load image
285
    image = main_display.readImage(image_path)
286
287
    if image is None:
288
        logging.error(f"Image loading failed for {image_path}. Skipping...")
289
        return None, None
290
291
    # Initialize result image
292
    result_image = main_display.setImage(image).copy()
293
    cv2.imwrite("initial_result_image.png", result_image)  # Save initial image
294
295
    # Initialize MaskCreator
296
    mask_creator = MaskCreator(image, transparency_factor)
297
298
    # Apply image modifications
299 1 Faiq Sayyidan SETIAWAN
    mask_creator.create_mask(image_side, mask_width, image_width)
300
    mask_creator.gammaCorrection(gamma)
301
    mask_creator.result_image = result_image
302
    mask_creator.alpha_blending(image_side)
303
304
    # Save final result for inspection
305 4 Faiq Sayyidan SETIAWAN
    cv2.imwrite("final_result_image.png", mask_creator.result_image)
306 1 Faiq Sayyidan SETIAWAN
307
    return mask_creator.result_image, image_name
308
309 7 Faiq Sayyidan SETIAWAN
310 1 Faiq Sayyidan SETIAWAN
def save_image(image, name):
311
312
    """
313 4 Faiq Sayyidan SETIAWAN
314 1 Faiq Sayyidan SETIAWAN
    Save the processed image to the project folder.
315
316 4 Faiq Sayyidan SETIAWAN
    Args:
317 1 Faiq Sayyidan SETIAWAN
318
        image (np.ndarray): The image to be saved.
319 4 Faiq Sayyidan SETIAWAN
320 1 Faiq Sayyidan SETIAWAN
        name (str): Name of the image (left or right).
321 4 Faiq Sayyidan SETIAWAN
322 1 Faiq Sayyidan SETIAWAN
    """
323
324
    # Define the output path
325
326
    output_dir = os.path.join(os.getcwd(), "processed_images")
327
328
    os.makedirs(output_dir, exist_ok=True)
329
330
    # Create the output file name
331
332
    output_path = os.path.join(output_dir, f"processed_image_{name}.png")
333
334
    # Save the image
335
336
    cv2.imwrite(output_path, image)
337
338
    logging.info(f"Saved processed image: {output_path}")
339
340
# GUI Application class definition
341
342
class ImageProcessingApp:
343
    def __init__(self, root):
344
        self.root = root
345
        self.root.title("Image Processing Application")
346
347 7 Faiq Sayyidan SETIAWAN
        # Initialize variables
348
        self.left_image_path = "" 
349
        self.right_image_path = "" 
350
        self.left_params = {}
351
        self.right_params = {}
352
        self.processed_images = {}
353 1 Faiq Sayyidan SETIAWAN
354 7 Faiq Sayyidan SETIAWAN
        # Create notebook (tabs)
355
        self.notebook = ttk.Notebook(root)
356
        self.notebook.pack(expand=True, fill='both')
357 1 Faiq Sayyidan SETIAWAN
358 7 Faiq Sayyidan SETIAWAN
        # Create frames for each tab
359
        self.tab_left = ttk.Frame(self.notebook)
360
        self.tab_right = ttk.Frame(self.notebook)
361
        self.tab_settings = ttk.Frame(self.notebook)
362
        self.tab_preview = ttk.Frame(self.notebook)
363 1 Faiq Sayyidan SETIAWAN
364 7 Faiq Sayyidan SETIAWAN
        self.notebook.add(self.tab_left, text='Left Image')
365
        self.notebook.add(self.tab_right, text='Right Image')
366
        self.notebook.add(self.tab_settings, text='Settings')
367
        self.notebook.add(self.tab_preview, text='Preview')
368 1 Faiq Sayyidan SETIAWAN
369 7 Faiq Sayyidan SETIAWAN
        # Setup each tab
370
        self.setup_left_tab()
371
        self.setup_right_tab()
372
        self.setup_settings_tab()
373
        self.setup_preview_tab()
374 1 Faiq Sayyidan SETIAWAN
375 7 Faiq Sayyidan SETIAWAN
        # Process and Save Button
376
        self.process_button = tk.Button(root, text="Process and Save Images", command=self.process_and_save)
377
        self.process_button.pack(pady=10)
378 1 Faiq Sayyidan SETIAWAN
379 7 Faiq Sayyidan SETIAWAN
        # Progress Bar
380
        self.progress_bar = ttk.Progressbar(root, orient="horizontal", length=400, mode="determinate")
381
        self.progress_bar.pack(pady=10)
382 1 Faiq Sayyidan SETIAWAN
383 7 Faiq Sayyidan SETIAWAN
    def setup_left_tab(self):
384
        frame = self.tab_left
385 1 Faiq Sayyidan SETIAWAN
386 7 Faiq Sayyidan SETIAWAN
        # Select Image Button
387
        btn_select = tk.Button(frame, text="Select Left Image", command=self.select_left_image)
388
        btn_select.pack(pady=5)
389 1 Faiq Sayyidan SETIAWAN
390 7 Faiq Sayyidan SETIAWAN
        # Display selected image path
391
        self.left_image_label = tk.Label(frame, text="No image selected", wraplength=300, anchor="w", justify="left")
392
        self.left_image_label.pack(padx=10, pady=5)
393 1 Faiq Sayyidan SETIAWAN
394 7 Faiq Sayyidan SETIAWAN
        # Parameters for left image
395
        params_frame = tk.LabelFrame(frame, text="Left Image Parameters", padx=10, pady=10)
396
        params_frame.pack(padx=10, pady=10, fill="x")
397 1 Faiq Sayyidan SETIAWAN
398 7 Faiq Sayyidan SETIAWAN
        # Projected Image Width
399
        tk.Label(params_frame, text="Projected Image Width:").grid(row=0, column=0, sticky="e")
400
        self.left_projected_image_width = tk.Entry(params_frame)
401
        self.left_projected_image_width.insert(0, "800")
402
        self.left_projected_image_width.grid(row=0, column=1, pady=2, sticky="w")
403 1 Faiq Sayyidan SETIAWAN
404 7 Faiq Sayyidan SETIAWAN
        # Projected Overlap Width
405
        tk.Label(params_frame, text="Projected Overlap Width:").grid(row=1, column=0, sticky="e")
406
        self.left_projected_overlap_width = tk.Entry(params_frame)
407
        self.left_projected_overlap_width.insert(0, "100")
408
        self.left_projected_overlap_width.grid(row=1, column=1, pady=2, sticky="w")
409 1 Faiq Sayyidan SETIAWAN
410 7 Faiq Sayyidan SETIAWAN
        # Gamma
411
        tk.Label(params_frame, text="Gamma:").grid(row=2, column=0, sticky="e")
412
        self.left_gamma = tk.Entry(params_frame)
413
        self.left_gamma.insert(0, "1.0")
414
        self.left_gamma.grid(row=2, column=1, pady=2, sticky="w")
415 1 Faiq Sayyidan SETIAWAN
416 7 Faiq Sayyidan SETIAWAN
        # Image Side
417
        tk.Label(params_frame, text="Image Side:").grid(row=3, column=0, sticky="e")
418
        self.left_image_side = tk.IntVar(value=0)  # Default to left
419
        tk.Radiobutton(params_frame, text="Left", variable=self.left_image_side, value=0).grid(row=3, column=1, sticky="w")
420
        tk.Radiobutton(params_frame, text="Right", variable=self.left_image_side, value=1).grid(row=3, column=1, padx=60, sticky="w")
421 1 Faiq Sayyidan SETIAWAN
422 7 Faiq Sayyidan SETIAWAN
        # Transparency Factor
423
        tk.Label(params_frame, text="Transparency Factor:").grid(row=4, column=0, sticky="e")
424
        self.left_transparency_factor = tk.Entry(params_frame)
425
        self.left_transparency_factor.insert(0, "1.0")
426
        self.left_transparency_factor.grid(row=4, column=1, pady=2, sticky="w")
427 1 Faiq Sayyidan SETIAWAN
428 7 Faiq Sayyidan SETIAWAN
    def setup_right_tab(self):
429
        frame = self.tab_right
430 1 Faiq Sayyidan SETIAWAN
431 7 Faiq Sayyidan SETIAWAN
        # Select Image Button
432
        btn_select = tk.Button(frame, text="Select Right Image", command=self.select_right_image)
433
        btn_select.pack(pady=5)
434 1 Faiq Sayyidan SETIAWAN
435 7 Faiq Sayyidan SETIAWAN
        # Display selected image path
436
        self.right_image_label = tk.Label(frame, text="No image selected", wraplength=300, anchor="w", justify="left")
437
        self.right_image_label.pack(padx=10, pady=5)
438 1 Faiq Sayyidan SETIAWAN
439 7 Faiq Sayyidan SETIAWAN
        # Parameters for right image
440
        params_frame = tk.LabelFrame(frame, text="Right Image Parameters", padx=10, pady=10)
441
        params_frame.pack(padx=10, pady=10, fill="x")
442 1 Faiq Sayyidan SETIAWAN
443 7 Faiq Sayyidan SETIAWAN
        # Projected Image Width
444
        tk.Label(params_frame, text="Projected Image Width:").grid(row=0, column=0, sticky="e")
445
        self.right_projected_image_width = tk.Entry(params_frame)
446
        self.right_projected_image_width.insert(0, "800")
447
        self.right_projected_image_width.grid(row=0, column=1, pady=2, sticky="w")
448 1 Faiq Sayyidan SETIAWAN
449 7 Faiq Sayyidan SETIAWAN
        # Projected Overlap Width
450
        tk.Label(params_frame, text="Projected Overlap Width:").grid(row=1, column=0, sticky="e")
451
        self.right_projected_overlap_width = tk.Entry(params_frame)
452
        self.right_projected_overlap_width.insert(0, "100")
453
        self.right_projected_overlap_width.grid(row=1, column=1, pady=2, sticky="w")
454 1 Faiq Sayyidan SETIAWAN
455 7 Faiq Sayyidan SETIAWAN
        # Gamma
456
        tk.Label(params_frame, text="Gamma:").grid(row=2, column=0, sticky="e")
457
        self.right_gamma = tk.Entry(params_frame)
458
        self.right_gamma.insert(0, "1.0")
459
        self.right_gamma.grid(row=2, column=1, pady=2, sticky="w")
460 1 Faiq Sayyidan SETIAWAN
461 7 Faiq Sayyidan SETIAWAN
        # Image Side
462
        tk.Label(params_frame, text="Image Side:").grid(row=3, column=0, sticky="e")
463
        self.right_image_side = tk.IntVar(value=1)  # Default to right
464
        tk.Radiobutton(params_frame, text="Left", variable=self.right_image_side, value=0).grid(row=3, column=1, sticky="w")
465
        tk.Radiobutton(params_frame, text="Right", variable=self.right_image_side, value=1).grid(row=3, column=1, padx=60, sticky="w")
466 1 Faiq Sayyidan SETIAWAN
467 7 Faiq Sayyidan SETIAWAN
        # Transparency Factor
468
        tk.Label(params_frame, text="Transparency Factor:").grid(row=4, column=0, sticky="e")
469
        self.right_transparency_factor = tk.Entry(params_frame)
470
        self.right_transparency_factor.insert(0, "1.0")
471
        self.right_transparency_factor.grid(row=4, column=1, pady=2, sticky="w")
472 1 Faiq Sayyidan SETIAWAN
473 7 Faiq Sayyidan SETIAWAN
    def setup_settings_tab(self):
474
        frame = self.tab_settings
475 1 Faiq Sayyidan SETIAWAN
476 7 Faiq Sayyidan SETIAWAN
        # Configurations can be saved or loaded here
477
        save_config_btn = tk.Button(frame, text="Save Configuration", command=self.save_configuration)
478
        save_config_btn.pack(pady=10)
479 1 Faiq Sayyidan SETIAWAN
480 7 Faiq Sayyidan SETIAWAN
        load_config_btn = tk.Button(frame, text="Load Configuration", command=self.load_configuration)
481
        load_config_btn.pack(pady=10)
482 1 Faiq Sayyidan SETIAWAN
483 7 Faiq Sayyidan SETIAWAN
    def setup_preview_tab(self):
484
        frame = self.tab_preview
485 1 Faiq Sayyidan SETIAWAN
486 7 Faiq Sayyidan SETIAWAN
        # Labels to display images
487
        self.original_image_label = tk.Label(frame, text="Original Image")
488
        self.original_image_label.pack(side="left", padx=10, pady=10)
489 1 Faiq Sayyidan SETIAWAN
490 7 Faiq Sayyidan SETIAWAN
        self.processed_image_label = tk.Label(frame, text="Processed Image")
491
        self.processed_image_label.pack(side="right", padx=10, pady=10)
492 1 Faiq Sayyidan SETIAWAN
493 7 Faiq Sayyidan SETIAWAN
    def select_left_image(self):
494
        path = filedialog.askopenfilename(title="Select Left Image",
495
                                          filetypes=[("Image files", "*.png *.jpg *.jpeg *.bmp")])
496
        if path:
497
            self.left_image_path = path
498
            self.left_image_label.config(text=os.path.basename(path))
499
            logging.info(f"Selected left image: {path}")
500 1 Faiq Sayyidan SETIAWAN
501 7 Faiq Sayyidan SETIAWAN
    def select_right_image(self):
502
        path = filedialog.askopenfilename(title="Select Right Image",
503
                                          filetypes=[("Image files", "*.png *.jpg *.jpeg *.bmp")])
504
        if path:
505
            self.right_image_path = path
506
            self.right_image_label.config(text=os.path.basename(path))
507
            logging.info(f"Selected right image: {path}")
508 1 Faiq Sayyidan SETIAWAN
509 7 Faiq Sayyidan SETIAWAN
    def save_configuration(self):
510
        config = ConfigReader()
511 1 Faiq Sayyidan SETIAWAN
512 7 Faiq Sayyidan SETIAWAN
        # Left Image Parameters
513
        if self.left_image_path:
514
            config.setParameters({
515
                'image_name': self.left_image_path,
516
                'projected_image_width': self.left_projected_image_width.get(),
517
                'projected_overlap_width': self.left_projected_overlap_width.get(),
518
                'gamma': self.left_gamma.get(),
519
                'image_side': self.left_image_side.get(),
520
                'transparency_factor': self.left_transparency_factor.get()
521
            })
522 1 Faiq Sayyidan SETIAWAN
523 7 Faiq Sayyidan SETIAWAN
        # Right Image Parameters
524
        if self.right_image_path:
525
            config.setParameters({
526
                'image_name': self.right_image_path,
527
                'projected_image_width': self.right_projected_image_width.get(),
528
                'projected_overlap_width': self.right_projected_overlap_width.get(),
529
                'gamma': self.right_gamma.get(),
530
                'image_side': self.right_image_side.get(),
531
                'transparency_factor': self.right_transparency_factor.get()
532
            })
533 1 Faiq Sayyidan SETIAWAN
534 7 Faiq Sayyidan SETIAWAN
        # Save to file
535
        save_path = filedialog.asksaveasfilename(title="Save Configuration",
536
                                                 defaultextension=".ini",
537
                                                 filetypes=[("INI files", "*.ini")])
538
        if save_path:
539
            config.save_config(save_path)
540
            messagebox.showinfo("Success", f"Configuration saved to {save_path}")
541
            logging.info(f"Configuration saved to {save_path}")
542 1 Faiq Sayyidan SETIAWAN
543 7 Faiq Sayyidan SETIAWAN
    def load_configuration(self):
544
        load_path = filedialog.askopenfilename(title="Load Configuration",
545
                                               filetypes=[("INI files", "*.ini")])
546
        if load_path and os.path.exists(load_path):
547
            config = ConfigReader(load_path)
548 1 Faiq Sayyidan SETIAWAN
549 7 Faiq Sayyidan SETIAWAN
            # Load left image parameters
550
            self.left_image_path = config.getImageName()
551
            if self.left_image_path and os.path.exists(self.left_image_path):
552
                self.left_image_label.config(text=os.path.basename(self.left_image_path))
553
            self.left_projected_image_width.delete(0, tk.END)
554
            self.left_projected_image_width.insert(0, config.getProjectedImageWidth())
555
            self.left_projected_overlap_width.delete(0, tk.END)
556
            self.left_projected_overlap_width.insert(0, config.getProjectedOverlapWidth())
557
            self.left_gamma.delete(0, tk.END)
558
            self.left_gamma.insert(0, config.getGamma())
559
            self.left_image_side.set(config.getImageSide())
560
            self.left_transparency_factor.delete(0, tk.END)
561
            self.left_transparency_factor.insert(0, config.getTransparencyFactor())
562 4 Faiq Sayyidan SETIAWAN
563 7 Faiq Sayyidan SETIAWAN
            # Load right image parameters
564
            self.right_image_path = config.getImageName()
565
            if self.right_image_path and os.path.exists(self.right_image_path):
566
                self.right_image_label.config(text=os.path.basename(self.right_image_path))
567
            self.right_projected_image_width.delete(0, tk.END)
568
            self.right_projected_image_width.insert(0, config.getProjectedImageWidth())
569
            self.right_projected_overlap_width.delete(0, tk.END)
570
            self.right_projected_overlap_width.insert(0, config.getProjectedOverlapWidth())
571
            self.right_gamma.delete(0, tk.END)
572
            self.right_gamma.insert(0, config.getGamma())
573
            self.right_image_side.set(config.getImageSide())
574
            self.right_transparency_factor.delete(0, tk.END)
575
            self.right_transparency_factor.insert(0, config.getTransparencyFactor())
576 4 Faiq Sayyidan SETIAWAN
577 7 Faiq Sayyidan SETIAWAN
            messagebox.showinfo("Success", f"Configuration loaded from {load_path}")
578
            logging.info(f"Configuration loaded from {load_path}")
579
        else:
580
            messagebox.showerror("Error", "Failed to load configuration.")
581 4 Faiq Sayyidan SETIAWAN
582 7 Faiq Sayyidan SETIAWAN
    def process_and_save(self):
583
        # Validate inputs
584
        if not self.left_image_path or not self.right_image_path:
585
            messagebox.showerror("Error", "Please select both left and right images.")
586
            return
587 4 Faiq Sayyidan SETIAWAN
588 7 Faiq Sayyidan SETIAWAN
        # Collect parameters for left image
589
        left_params = {
590
            'image_name': self.left_image_path,
591
            'projected_image_width': int(self.left_projected_image_width.get()),
592
            'projected_overlap_width': int(self.left_projected_overlap_width.get()),
593
            'gamma': float(self.left_gamma.get()),
594
            'image_side': self.left_image_side.get(),
595
            'transparency_factor': float(self.left_transparency_factor.get())
596
        }
597 4 Faiq Sayyidan SETIAWAN
598 7 Faiq Sayyidan SETIAWAN
        # Collect parameters for right image
599
        right_params = {
600
            'image_name': self.right_image_path,
601
            'projected_image_width': int(self.right_projected_image_width.get()),
602
            'projected_overlap_width': int(self.right_projected_overlap_width.get()),
603
            'gamma': float(self.right_gamma.get()),
604
            'image_side': self.right_image_side.get(),
605
            'transparency_factor': float(self.right_transparency_factor.get())
606
        }
607 4 Faiq Sayyidan SETIAWAN
608 7 Faiq Sayyidan SETIAWAN
        # Initialize main display
609
        main_display = MainDisplay()
610 4 Faiq Sayyidan SETIAWAN
611 7 Faiq Sayyidan SETIAWAN
        # Process left image
612
        self.progress_bar["value"] = 0
613
        self.root.update_idletasks()
614
        left_processed, left_name = process_image(self.left_image_path, left_params, main_display)
615
        if left_processed is not None and left_name is not None:
616
            self.processed_images[left_name] = left_processed
617
            save_image(left_processed, left_name)
618
            self.progress_bar["value"] += 50
619
            self.root.update_idletasks()
620 4 Faiq Sayyidan SETIAWAN
621 7 Faiq Sayyidan SETIAWAN
        # Process right image
622
        right_processed, right_name = process_image(self.right_image_path, right_params, main_display)
623
        if right_processed is not None and right_name is not None:
624
            self.processed_images[right_name] = right_processed
625
            save_image(right_processed, right_name)
626
            self.progress_bar["value"] += 50
627
            self.root.update_idletasks()
628 4 Faiq Sayyidan SETIAWAN
629 7 Faiq Sayyidan SETIAWAN
        # Display images
630
        self.display_preview()
631 4 Faiq Sayyidan SETIAWAN
632 7 Faiq Sayyidan SETIAWAN
        # Finalize progress
633
        self.progress_bar["value"] = 100
634
        self.root.update_idletasks()
635 4 Faiq Sayyidan SETIAWAN
        messagebox.showinfo("Processing Complete", "Images processed and saved successfully.")
636
637 7 Faiq Sayyidan SETIAWAN
    def display_preview(self):
638
        # Display the first processed image as preview
639
        if self.processed_images:
640
            # For simplicity, display the first image
641
            name, img = next(iter(self.processed_images.items()))
642 4 Faiq Sayyidan SETIAWAN
            img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
643
            pil_img = Image.fromarray(img_rgb)
644 7 Faiq Sayyidan SETIAWAN
            pil_img = pil_img.resize((400, 300), Image.ANTIALIAS)
645 4 Faiq Sayyidan SETIAWAN
            img_tk = ImageTk.PhotoImage(pil_img)
646 7 Faiq Sayyidan SETIAWAN
            self.processed_image_label.config(image=img_tk)
647
            self.processed_image_label.image = img_tk
648 4 Faiq Sayyidan SETIAWAN
649 7 Faiq Sayyidan SETIAWAN
            # Load and display original image
650
            original_img = cv2.imread(self.left_image_path if name == 'left' else self.right_image_path, cv2.IMREAD_COLOR)
651
            if original_img is not None:
652
                original_rgb = cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB)
653
                pil_original = Image.fromarray(original_rgb)
654
                pil_original = pil_original.resize((400, 300), Image.ANTIALIAS)
655
                original_tk = ImageTk.PhotoImage(pil_original)
656
                self.original_image_label.config(image=original_tk)
657
                self.original_image_label.image = original_tk
658 4 Faiq Sayyidan SETIAWAN
659 7 Faiq Sayyidan SETIAWAN
    def display_image(self, processed_images):
660
        # This method can be expanded to display multiple images if needed
661
        pass
662 4 Faiq Sayyidan SETIAWAN
663
def main():
664
665
    root = tk.Tk()
666
667
    app = ImageProcessingApp(root)
668
669
    root.mainloop()
670
671
if __name__ == "__main__":
672
673 1 Faiq Sayyidan SETIAWAN
    main()
674
675
</code></pre>