Skip to content

Commit b37bfed

Browse files
committed
Add show_image_gui function
1 parent 7658ea5 commit b37bfed

File tree

3 files changed

+112
-0
lines changed

3 files changed

+112
-0
lines changed

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
gdown
22
geopandas
33
huggingface_hub
4+
ipympl
45
leafmap
56
localtileserver
67
matplotlib

samgeo/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77

88
from .samgeo import *
99
from .samgeo2 import *
10+
from .common import show_image_gui

samgeo/common.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3323,3 +3323,113 @@ def video_to_images(
33233323
# Release the video capture object
33243324
cap.release()
33253325
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

Comments
 (0)