@@ -3323,3 +3323,113 @@ def video_to_images(
3323
3323
# Release the video capture object
3324
3324
cap .release ()
3325
3325
print (f"Finished saving { saved_frame_count } images to { output_dir } " )
3326
+
3327
+
3328
+ def show_image_gui (path : str ) -> None :
3329
+ """Show an interactive GUI to explore images.
3330
+ Args:
3331
+ path (str): The path to the image file or directory containing images.
3332
+ """
3333
+
3334
+ from PIL import Image
3335
+ from ipywidgets import interact , IntSlider
3336
+ import matplotlib
3337
+
3338
+ def setup_interactive_matplotlib ():
3339
+ """Sets up ipympl backend for interactive plotting in Jupyter."""
3340
+ # Use the ipympl backend for interactive plotting
3341
+ try :
3342
+ import ipympl
3343
+
3344
+ matplotlib .use ("module://ipympl.backend_nbagg" )
3345
+ except ImportError :
3346
+ print ("ipympl is not installed. Falling back to default backend." )
3347
+
3348
+ def load_images_from_folder (folder ):
3349
+ """Load all images from the specified folder."""
3350
+ images = []
3351
+ filenames = []
3352
+ for filename in sorted (os .listdir (folder )):
3353
+ if filename .endswith ((".png" , ".jpg" , ".jpeg" , ".bmp" , ".gif" )):
3354
+ img = Image .open (os .path .join (folder , filename ))
3355
+ img_array = np .array (img )
3356
+ images .append (img_array )
3357
+ filenames .append (filename )
3358
+ return images , filenames
3359
+
3360
+ def load_single_image (image_path ):
3361
+ """Load a single image from the specified image file path."""
3362
+ img = Image .open (image_path )
3363
+ img_array = np .array (img )
3364
+ return [img_array ], [
3365
+ os .path .basename (image_path )
3366
+ ] # Return as lists for consistency
3367
+
3368
+ # Check if the input path is a file or a directory
3369
+ if os .path .isfile (path ):
3370
+ images , filenames = load_single_image (path )
3371
+ elif os .path .isdir (path ):
3372
+ images , filenames = load_images_from_folder (path )
3373
+ else :
3374
+ print ("Invalid path. Please provide a valid image file or directory." )
3375
+ return
3376
+
3377
+ total_images = len (images )
3378
+
3379
+ if total_images == 0 :
3380
+ print ("No images found." )
3381
+ return
3382
+
3383
+ # Set up interactive plotting
3384
+ setup_interactive_matplotlib ()
3385
+
3386
+ fig , ax = plt .subplots ()
3387
+ fig .canvas .toolbar_visible = True
3388
+ fig .canvas .header_visible = False
3389
+ fig .canvas .footer_visible = True
3390
+
3391
+ # Display the first image initially
3392
+ im_display = ax .imshow (images [0 ])
3393
+ ax .set_title (f"Image: { filenames [0 ]} " )
3394
+ plt .tight_layout ()
3395
+
3396
+ # Function to update the image when the slider changes (for multiple images)
3397
+ def update_image (image_index ):
3398
+ im_display .set_data (images [image_index ])
3399
+ ax .set_title (f"Image: { filenames [image_index ]} " )
3400
+ fig .canvas .draw ()
3401
+
3402
+ # Function to show pixel information on click
3403
+ def onclick (event ):
3404
+ if event .xdata is not None and event .ydata is not None :
3405
+ col = int (event .xdata )
3406
+ row = int (event .ydata )
3407
+ pixel_value = images [current_image_index ][
3408
+ row , col
3409
+ ] # Use current image index
3410
+ ax .set_title (
3411
+ f"Image: { filenames [current_image_index ]} - X: { col } , Y: { row } , Pixel Value: { pixel_value } "
3412
+ )
3413
+ fig .canvas .draw ()
3414
+
3415
+ # Track the current image index (whether from slider or for single image)
3416
+ current_image_index = 0
3417
+
3418
+ # Slider widget to choose between images (only if there is more than one image)
3419
+ if total_images > 1 :
3420
+ slider = IntSlider (min = 0 , max = total_images - 1 , step = 1 , description = "Image" )
3421
+
3422
+ def on_slider_change (change ):
3423
+ nonlocal current_image_index
3424
+ current_image_index = change ["new" ] # Update current image index
3425
+ update_image (current_image_index )
3426
+
3427
+ slider .observe (on_slider_change , names = "value" )
3428
+ fig .canvas .mpl_connect ("button_press_event" , onclick )
3429
+ interact (update_image , image_index = slider )
3430
+ else :
3431
+ # If there's only one image, no need for a slider, just show pixel info on click
3432
+ fig .canvas .mpl_connect ("button_press_event" , onclick )
3433
+
3434
+ # Show the plot
3435
+ plt .show ()
0 commit comments