Project

General

Profile

Feature #1123 » alpha_blending.py

Final code with uniformed method names - Andifallih Noor MALELA, 10/31/2024 03:42 PM

 
1
import tkinter as tk
2

    
3
from tkinter import filedialog, messagebox
4

    
5
from tkinter import ttk
6

    
7
import configparser
8

    
9
import cv2
10

    
11
import numpy as np
12

    
13
import os
14

    
15
import logging
16

    
17
from PIL import Image, ImageTk
18

    
19
# Setup logging
20

    
21
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
22

    
23
# ConfigReader class definition
24

    
25
class ConfigReader:
26

    
27
    def __init__(self, config_path=None):
28
        # Assume some initialization using config_path
29
        self.config_path = config_path
30
        # Add other initialization logic here
31
        self.config_parser = configparser.ConfigParser()
32
        if config_path is not None and os.path.exists(config_path):
33
            self.config_parser.read(config_path)
34

    
35
    def getImageName(self):
36

    
37
        return str(self.config_parser['DEFAULT']['image_name'])
38

    
39
    def getProjectedImageWidth(self):
40

    
41
        return int(self.config_parser['DEFAULT']['projected_image_width'])
42

    
43
    def getProjectedOverlapWidth(self):
44

    
45
        return int(self.config_parser['DEFAULT']['projected_overlap_width'])
46

    
47
    def getGamma(self):
48

    
49
        return float(self.config_parser['DEFAULT']['gamma'])
50

    
51
    def getImageSide(self):
52

    
53
        return int(self.config_parser['DEFAULT']['image_side'])
54

    
55
    def getTransparencyFactor(self):
56

    
57
        return float(self.config_parser['DEFAULT'].get('transparency_factor', 1.0))
58

    
59
    def setParameters(self, parameters):
60
        # The parameters is a dictionary with key-value pairs
61
        if 'DEFAULT' not in self.config_parser:
62
            self.config_parser['DEFAULT'] = {}
63
        
64
        for key, value in parameters.items():
65
            self.config_parser['DEFAULT'][key] = str(value)
66

    
67
    def saveConfig(self, path):
68
        with open(path, 'w') as configfile:
69
            self.config_parser.write(configfile)
70

    
71

    
72
# MainDisplay class definition
73

    
74
class MainDisplay:
75

    
76
    def readImage(self, image_path):
77

    
78
        # Loads an image from the specified path with 3 channels (BGR)
79

    
80
        image = cv2.imread(image_path, cv2.IMREAD_COLOR)
81

    
82
        if image is None:
83

    
84
            logging.error(f"Error loading image at {image_path}")
85

    
86
        else:
87

    
88
            logging.info(f"Loaded image {image_path} with shape: {image.shape}")
89

    
90
        return image
91

    
92
    def setImage(self, image):
93

    
94
        # Placeholder for image processing if necessary
95

    
96
        # Here you can modify or prepare the image before displaying
97

    
98
        logging.info(f"Setting image with shape: {image.shape}")
99

    
100
        return image
101

    
102
# MaskCreator class definition
103

    
104
class MaskCreator:
105

    
106
    def __init__(self, image, transparency_factor):
107

    
108
        self.__image = image
109

    
110
        self.__alpha_gradient = None
111

    
112
        self.__gamma_corrected = None
113

    
114
        self.result_image = None
115

    
116
        self.__mask = None
117

    
118
        self.transparency_factor = transparency_factor
119

    
120
    def smoothstep(self, edge0, edge1, x):
121

    
122
        # Smoothstep function for smoother transition (non-linear gradient)
123

    
124
        x = np.clip((x - edge0) / (edge1 - edge0), 0, 1)
125

    
126
        return x * x * (3 - 2 * x)
127

    
128
    def createMask(self, image_side, mask_width, image_width):
129

    
130
        self.__mask = self.__image.shape[1] * mask_width // image_width
131

    
132
        gradient = np.linspace(0, 1, self.__mask)
133

    
134
        # Apply smoothstep to create a smoother gradient
135

    
136
        smooth_gradient = self.smoothstep(0, 1, gradient)
137

    
138
        # Apply transparency factor to adjust the strength of the blending
139

    
140
        smooth_gradient = smooth_gradient * self.transparency_factor
141

    
142
        if image_side == 1:
143

    
144
            # Gradient from transparent to opaque (middle to right)
145

    
146
            self.__alpha_gradient = smooth_gradient
147

    
148
        elif image_side == 0:
149

    
150
            # Gradient from opaque to transparent (left to middle)
151

    
152
            self.__alpha_gradient = smooth_gradient[::-1]  # Reverse for the left side
153

    
154
    def gammaCorrection(self, gamma):
155

    
156
        # Apply gamma correction
157

    
158
        inv_gamma = 1.0 / gamma
159

    
160
        table = np.array([((i / 255.0) ** inv_gamma) * 255
161

    
162
                          for i in np.arange(256)]).astype("uint8")
163

    
164
        self.__gamma_corrected = cv2.LUT(self.__image, table)
165

    
166
        logging.info(f"Applied gamma correction with gamma={gamma}")
167

    
168
        # Save gamma corrected image for inspection
169

    
170
        cv2.imwrite("gamma_corrected.png", self.__gamma_corrected)
171

    
172
    def alphaBlending(self, image_side):
173

    
174
        """
175

    
176
        Applies alpha blending on the gamma-corrected image.
177

    
178
        Combines the gamma-corrected part of the image with a black background using the alpha gradient mask.
179

    
180
        """
181

    
182
        # Initialize result_image to be the gamma-corrected image
183

    
184
        self.result_image = self.__gamma_corrected.copy()
185

    
186
        if image_side == 1:  # Right side
187

    
188
            # Create a region of interest (ROI) where blending will occur (right side of the image)
189

    
190
            roi = self.result_image[:, :self.__mask].astype(np.float32)
191

    
192
            # Create black background for blending
193

    
194
            black_background = np.zeros_like(roi, dtype=np.float32)
195

    
196
            # Apply the alpha mask to blend gamma-corrected image with black background
197

    
198
            alpha = self.__alpha_gradient.reshape(1, -1, 1).astype(np.float32)
199

    
200
            blended = (alpha * roi + (1 - alpha) * black_background)
201

    
202
            blended = np.clip(blended, 0, 255).astype(np.uint8)
203

    
204
            # Place the blended region back in the result image
205

    
206
            self.result_image[:, :self.__mask] = blended
207

    
208
            logging.info(f"Applied alpha blending on the right side with mask width {self.__mask}")
209

    
210
            # Save blended region for debugging
211

    
212
            cv2.imwrite("blended_right_side.png", blended)
213

    
214
        elif image_side == 0:  # Left side
215

    
216
            # Create a region of interest (ROI) where blending will occur (left side of the image)
217

    
218
            roi = self.result_image[:, -self.__mask:].astype(np.float32)
219

    
220
            # Create black background for blending
221

    
222
            black_background = np.zeros_like(roi, dtype=np.float32)
223

    
224
            # Apply the alpha mask to blend gamma-corrected image with black background
225

    
226
            alpha = self.__alpha_gradient.reshape(1, -1, 1).astype(np.float32)
227

    
228
            blended = (alpha * roi + (1 - alpha) * black_background)
229

    
230
            blended = np.clip(blended, 0, 255).astype(np.uint8)
231

    
232
            # Place the blended region back in the result image
233

    
234
            self.result_image[:, -self.__mask:] = blended
235

    
236
            logging.info(f"Applied alpha blending on the left side with mask width {self.__mask}")
237

    
238
            # Save blended region for debugging
239

    
240
            cv2.imwrite("blended_left_side.png", blended)
241

    
242

    
243
def processImage(image_path, params, main_display):
244
    """
245
    Processes an image based on the provided parameters.
246

    
247
    Args:
248
        image_path (str): Path to the image file.
249
        params (dict): Parameters for image processing.
250
        main_display (MainDisplay): Instance of MainDisplay for image operations.
251

    
252
    Returns:
253
        tuple: Processed image and its corresponding name.
254
    """
255

    
256
    # Retrieve parameters from params dictionary
257
    mask_width = params.get('projected_overlap_width')
258
    image_width = params.get('projected_image_width')
259
    gamma = params.get('gamma')
260
    image_side = params.get('image_side')
261
    transparency_factor = params.get('transparency_factor')
262

    
263
    # Determine image side name
264
    if image_side == 0:
265
        image_name = 'left'
266
    elif image_side == 1:
267
        image_name = 'right'
268
    else:
269
        logging.error(f"Invalid ImageSide value. Use 0 for left image, 1 for right image.")
270
        return None, None
271

    
272
    # Load image
273
    image = main_display.readImage(image_path)
274

    
275
    if image is None:
276
        logging.error(f"Image loading failed for {image_path}. Skipping...")
277
        return None, None
278

    
279
    # Initialize result image
280
    result_image = main_display.setImage(image).copy()
281
    cv2.imwrite("initial_result_image.png", result_image)  # Save initial image
282

    
283
    # Initialize MaskCreator
284
    mask_creator = MaskCreator(image, transparency_factor)
285

    
286
    # Apply image modifications
287
    mask_creator.createMask(image_side, mask_width, image_width)
288
    mask_creator.gammaCorrection(gamma)
289
    mask_creator.result_image = result_image
290
    mask_creator.alphaBlending(image_side)
291

    
292
    # Save final result for inspection
293
    cv2.imwrite("final_result_image.png", mask_creator.result_image)
294

    
295
    return mask_creator.result_image, image_name
296

    
297

    
298
def saveImage(image, name):
299

    
300
    """
301

    
302
    Save the processed image to the project folder.
303

    
304
    Args:
305

    
306
        image (np.ndarray): The image to be saved.
307

    
308
        name (str): Name of the image (left or right).
309

    
310
    """
311

    
312
    # Define the output path
313

    
314
    output_dir = os.path.join(os.getcwd(), "processed_images")
315

    
316
    os.makedirs(output_dir, exist_ok=True)
317

    
318
    # Create the output file name
319

    
320
    output_path = os.path.join(output_dir, f"processed_image_{name}.png")
321

    
322
    # Save the image
323

    
324
    cv2.imwrite(output_path, image)
325

    
326
    logging.info(f"Saved processed image: {output_path}")
327

    
328
# GUI Application class definition
329

    
330
class ImageProcessingApp:
331
    def __init__(self, root):
332
        self.root = root
333
        self.root.title("Image Processing Application")
334

    
335
        # Initialize variables
336
        self.left_image_path = "" 
337
        self.right_image_path = "" 
338
        self.left_params = {}
339
        self.right_params = {}
340
        self.processed_images = {}
341

    
342
        # Create notebook (tabs)
343
        self.notebook = ttk.Notebook(root)
344
        self.notebook.pack(expand=True, fill='both')
345

    
346
        # Create frames for each tab
347
        self.tab_left = ttk.Frame(self.notebook)
348
        self.tab_right = ttk.Frame(self.notebook)
349
        self.tab_settings = ttk.Frame(self.notebook)
350
        self.tab_preview = ttk.Frame(self.notebook)
351

    
352
        self.notebook.add(self.tab_left, text='Left Image')
353
        self.notebook.add(self.tab_right, text='Right Image')
354
        self.notebook.add(self.tab_settings, text='Settings')
355
        self.notebook.add(self.tab_preview, text='Preview')
356

    
357
        # Setup each tab
358
        self.setupLeftTab()
359
        self.setupRightTab()
360
        self.setupSettingsTab()
361
        self.setupPreviewTab()
362

    
363
        # Process and Save Button
364
        self.process_button = tk.Button(root, text="Process and Save Images", command=self.processAndSave)
365
        self.process_button.pack(pady=10)
366

    
367
        # Progress Bar
368
        self.progress_bar = ttk.Progressbar(root, orient="horizontal", length=400, mode="determinate")
369
        self.progress_bar.pack(pady=10)
370

    
371
    def setupLeftTab(self):
372
        frame = self.tab_left
373

    
374
        # Select Image Button
375
        btn_select = tk.Button(frame, text="Select Left Image", command=self.selectLeftImage)
376
        btn_select.pack(pady=5)
377

    
378
        # Display selected image path
379
        self.left_image_label = tk.Label(frame, text="No image selected", wraplength=300, anchor="w", justify="left")
380
        self.left_image_label.pack(padx=10, pady=5)
381

    
382
        # Parameters for left image
383
        params_frame = tk.LabelFrame(frame, text="Left Image Parameters", padx=10, pady=10)
384
        params_frame.pack(padx=10, pady=10, fill="x")
385

    
386
        # Projected Image Width
387
        tk.Label(params_frame, text="Projected Image Width:").grid(row=0, column=0, sticky="e")
388
        self.left_projected_image_width = tk.Entry(params_frame)
389
        self.left_projected_image_width.insert(0, "800")
390
        self.left_projected_image_width.grid(row=0, column=1, pady=2, sticky="w")
391

    
392
        # Projected Overlap Width
393
        tk.Label(params_frame, text="Projected Overlap Width:").grid(row=1, column=0, sticky="e")
394
        self.left_projected_overlap_width = tk.Entry(params_frame)
395
        self.left_projected_overlap_width.insert(0, "100")
396
        self.left_projected_overlap_width.grid(row=1, column=1, pady=2, sticky="w")
397

    
398
        # Gamma
399
        tk.Label(params_frame, text="Gamma:").grid(row=2, column=0, sticky="e")
400
        self.left_gamma = tk.Entry(params_frame)
401
        self.left_gamma.insert(0, "1.0")
402
        self.left_gamma.grid(row=2, column=1, pady=2, sticky="w")
403

    
404
        # Image Side
405
        tk.Label(params_frame, text="Image Side:").grid(row=3, column=0, sticky="e")
406
        self.left_image_side = tk.IntVar(value=0)  # Default to left
407
        tk.Radiobutton(params_frame, text="Left", variable=self.left_image_side, value=0).grid(row=3, column=1, sticky="w")
408
        tk.Radiobutton(params_frame, text="Right", variable=self.left_image_side, value=1).grid(row=3, column=1, padx=60, sticky="w")
409

    
410
        # Transparency Factor
411
        tk.Label(params_frame, text="Transparency Factor:").grid(row=4, column=0, sticky="e")
412
        self.left_transparency_factor = tk.Entry(params_frame)
413
        self.left_transparency_factor.insert(0, "1.0")
414
        self.left_transparency_factor.grid(row=4, column=1, pady=2, sticky="w")
415

    
416
    def setupRightTab(self):
417
        frame = self.tab_right
418

    
419
        # Select Image Button
420
        btn_select = tk.Button(frame, text="Select Right Image", command=self.selectRightImage)
421
        btn_select.pack(pady=5)
422

    
423
        # Display selected image path
424
        self.right_image_label = tk.Label(frame, text="No image selected", wraplength=300, anchor="w", justify="left")
425
        self.right_image_label.pack(padx=10, pady=5)
426

    
427
        # Parameters for right image
428
        params_frame = tk.LabelFrame(frame, text="Right Image Parameters", padx=10, pady=10)
429
        params_frame.pack(padx=10, pady=10, fill="x")
430

    
431
        # Projected Image Width
432
        tk.Label(params_frame, text="Projected Image Width:").grid(row=0, column=0, sticky="e")
433
        self.right_projected_image_width = tk.Entry(params_frame)
434
        self.right_projected_image_width.insert(0, "800")
435
        self.right_projected_image_width.grid(row=0, column=1, pady=2, sticky="w")
436

    
437
        # Projected Overlap Width
438
        tk.Label(params_frame, text="Projected Overlap Width:").grid(row=1, column=0, sticky="e")
439
        self.right_projected_overlap_width = tk.Entry(params_frame)
440
        self.right_projected_overlap_width.insert(0, "100")
441
        self.right_projected_overlap_width.grid(row=1, column=1, pady=2, sticky="w")
442

    
443
        # Gamma
444
        tk.Label(params_frame, text="Gamma:").grid(row=2, column=0, sticky="e")
445
        self.right_gamma = tk.Entry(params_frame)
446
        self.right_gamma.insert(0, "1.0")
447
        self.right_gamma.grid(row=2, column=1, pady=2, sticky="w")
448

    
449
        # Image Side
450
        tk.Label(params_frame, text="Image Side:").grid(row=3, column=0, sticky="e")
451
        self.right_image_side = tk.IntVar(value=1)  # Default to right
452
        tk.Radiobutton(params_frame, text="Left", variable=self.right_image_side, value=0).grid(row=3, column=1, sticky="w")
453
        tk.Radiobutton(params_frame, text="Right", variable=self.right_image_side, value=1).grid(row=3, column=1, padx=60, sticky="w")
454

    
455
        # Transparency Factor
456
        tk.Label(params_frame, text="Transparency Factor:").grid(row=4, column=0, sticky="e")
457
        self.right_transparency_factor = tk.Entry(params_frame)
458
        self.right_transparency_factor.insert(0, "1.0")
459
        self.right_transparency_factor.grid(row=4, column=1, pady=2, sticky="w")
460

    
461
    def setupSettingsTab(self):
462
        frame = self.tab_settings
463

    
464
        # Configurations can be saved or loaded here
465
        saveConfig_btn = tk.Button(frame, text="Save Configuration", command=self.saveConfiguration)
466
        saveConfig_btn.pack(pady=10)
467

    
468
        load_config_btn = tk.Button(frame, text="Load Configuration", command=self.loadConfiguration)
469
        load_config_btn.pack(pady=10)
470

    
471
    def setupPreviewTab(self):
472
        frame = self.tab_preview
473

    
474
        # Labels to display images
475
        self.original_image_label = tk.Label(frame, text="Original Image")
476
        self.original_image_label.pack(side="left", padx=10, pady=10)
477

    
478
        self.processed_image_label = tk.Label(frame, text="Processed Image")
479
        self.processed_image_label.pack(side="right", padx=10, pady=10)
480

    
481
    def selectLeftImage(self):
482
        path = filedialog.askopenfilename(title="Select Left Image",
483
                                          filetypes=[("Image files", "*.png *.jpg *.jpeg *.bmp")])
484
        if path:
485
            self.left_image_path = path
486
            self.left_image_label.config(text=os.path.basename(path))
487
            logging.info(f"Selected left image: {path}")
488

    
489
    def selectRightImage(self):
490
        path = filedialog.askopenfilename(title="Select Right Image",
491
                                          filetypes=[("Image files", "*.png *.jpg *.jpeg *.bmp")])
492
        if path:
493
            self.right_image_path = path
494
            self.right_image_label.config(text=os.path.basename(path))
495
            logging.info(f"Selected right image: {path}")
496

    
497
    def saveConfiguration(self):
498
        config = ConfigReader()
499

    
500
        # Left Image Parameters
501
        if self.left_image_path:
502
            config.setParameters({
503
                'image_name': self.left_image_path,
504
                'projected_image_width': self.left_projected_image_width.get(),
505
                'projected_overlap_width': self.left_projected_overlap_width.get(),
506
                'gamma': self.left_gamma.get(),
507
                'image_side': self.left_image_side.get(),
508
                'transparency_factor': self.left_transparency_factor.get()
509
            })
510

    
511
        # Right Image Parameters
512
        if self.right_image_path:
513
            config.setParameters({
514
                'image_name': self.right_image_path,
515
                'projected_image_width': self.right_projected_image_width.get(),
516
                'projected_overlap_width': self.right_projected_overlap_width.get(),
517
                'gamma': self.right_gamma.get(),
518
                'image_side': self.right_image_side.get(),
519
                'transparency_factor': self.right_transparency_factor.get()
520
            })
521

    
522
        # Save to file
523
        save_path = filedialog.asksaveasfilename(title="Save Configuration",
524
                                                 defaultextension=".ini",
525
                                                 filetypes=[("INI files", "*.ini")])
526
        if save_path:
527
            config.saveConfig(save_path)
528
            messagebox.showinfo("Success", f"Configuration saved to {save_path}")
529
            logging.info(f"Configuration saved to {save_path}")
530

    
531
    def loadConfiguration(self):
532
        load_path = filedialog.askopenfilename(title="Load Configuration",
533
                                               filetypes=[("INI files", "*.ini")])
534
        if load_path and os.path.exists(load_path):
535
            config = ConfigReader(load_path)
536

    
537
            # Load left image parameters
538
            self.left_image_path = config.getImageName()
539
            if self.left_image_path and os.path.exists(self.left_image_path):
540
                self.left_image_label.config(text=os.path.basename(self.left_image_path))
541
            self.left_projected_image_width.delete(0, tk.END)
542
            self.left_projected_image_width.insert(0, config.getProjectedImageWidth())
543
            self.left_projected_overlap_width.delete(0, tk.END)
544
            self.left_projected_overlap_width.insert(0, config.getProjectedOverlapWidth())
545
            self.left_gamma.delete(0, tk.END)
546
            self.left_gamma.insert(0, config.getGamma())
547
            self.left_image_side.set(config.getImageSide())
548
            self.left_transparency_factor.delete(0, tk.END)
549
            self.left_transparency_factor.insert(0, config.getTransparencyFactor())
550

    
551
            # Load right image parameters
552
            self.right_image_path = config.getImageName()
553
            if self.right_image_path and os.path.exists(self.right_image_path):
554
                self.right_image_label.config(text=os.path.basename(self.right_image_path))
555
            self.right_projected_image_width.delete(0, tk.END)
556
            self.right_projected_image_width.insert(0, config.getProjectedImageWidth())
557
            self.right_projected_overlap_width.delete(0, tk.END)
558
            self.right_projected_overlap_width.insert(0, config.getProjectedOverlapWidth())
559
            self.right_gamma.delete(0, tk.END)
560
            self.right_gamma.insert(0, config.getGamma())
561
            self.right_image_side.set(config.getImageSide())
562
            self.right_transparency_factor.delete(0, tk.END)
563
            self.right_transparency_factor.insert(0, config.getTransparencyFactor())
564

    
565
            messagebox.showinfo("Success", f"Configuration loaded from {load_path}")
566
            logging.info(f"Configuration loaded from {load_path}")
567
        else:
568
            messagebox.showerror("Error", "Failed to load configuration.")
569

    
570
    def processAndSave(self):
571
        # Validate inputs
572
        if not self.left_image_path or not self.right_image_path:
573
            messagebox.showerror("Error", "Please select both left and right images.")
574
            return
575

    
576
        # Collect parameters for left image
577
        left_params = {
578
            'image_name': self.left_image_path,
579
            'projected_image_width': int(self.left_projected_image_width.get()),
580
            'projected_overlap_width': int(self.left_projected_overlap_width.get()),
581
            'gamma': float(self.left_gamma.get()),
582
            'image_side': self.left_image_side.get(),
583
            'transparency_factor': float(self.left_transparency_factor.get())
584
        }
585

    
586
        # Collect parameters for right image
587
        right_params = {
588
            'image_name': self.right_image_path,
589
            'projected_image_width': int(self.right_projected_image_width.get()),
590
            'projected_overlap_width': int(self.right_projected_overlap_width.get()),
591
            'gamma': float(self.right_gamma.get()),
592
            'image_side': self.right_image_side.get(),
593
            'transparency_factor': float(self.right_transparency_factor.get())
594
        }
595

    
596
        # Initialize main display
597
        main_display = MainDisplay()
598

    
599
        # Process left image
600
        self.progress_bar["value"] = 0
601
        self.root.update_idletasks()
602
        left_processed, left_name = processImage(self.left_image_path, left_params, main_display)
603
        if left_processed is not None and left_name is not None:
604
            self.processed_images[left_name] = left_processed
605
            saveImage(left_processed, left_name)
606
            self.progress_bar["value"] += 50
607
            self.root.update_idletasks()
608

    
609
        # Process right image
610
        right_processed, right_name = processImage(self.right_image_path, right_params, main_display)
611
        if right_processed is not None and right_name is not None:
612
            self.processed_images[right_name] = right_processed
613
            saveImage(right_processed, right_name)
614
            self.progress_bar["value"] += 50
615
            self.root.update_idletasks()
616

    
617
        # Display images
618
        self.displayPreview()
619

    
620
        # Finalize progress
621
        self.progress_bar["value"] = 100
622
        self.root.update_idletasks()
623
        messagebox.showinfo("Processing Complete", "Images processed and saved successfully.")
624

    
625
    def displayPreview(self):
626
        # Display the first processed image as preview
627
        if self.processed_images:
628
            # For simplicity, display the first image
629
            name, img = next(iter(self.processed_images.items()))
630
            img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
631
            pil_img = Image.fromarray(img_rgb)
632
            pil_img = pil_img.resize((400, 300), Image.ANTIALIAS)
633
            img_tk = ImageTk.PhotoImage(pil_img)
634
            self.processed_image_label.config(image=img_tk)
635
            self.processed_image_label.image = img_tk
636

    
637
            # Load and display original image
638
            original_img = cv2.imread(self.left_image_path if name == 'left' else self.right_image_path, cv2.IMREAD_COLOR)
639
            if original_img is not None:
640
                original_rgb = cv2.cvtColor(original_img, cv2.COLOR_BGR2RGB)
641
                pil_original = Image.fromarray(original_rgb)
642
                pil_original = pil_original.resize((400, 300), Image.ANTIALIAS)
643
                original_tk = ImageTk.PhotoImage(pil_original)
644
                self.original_image_label.config(image=original_tk)
645
                self.original_image_label.image = original_tk
646

    
647
    def displayImage(self, processed_images):
648
        # This method can be expanded to display multiple images if needed
649
        pass
650

    
651
def main():
652

    
653
    root = tk.Tk()
654

    
655
    app = ImageProcessingApp(root)
656

    
657
    root.mainloop()
658

    
659
if __name__ == "__main__":
660

    
661
    main()
(3-3/3)