| import gradio as gr |
| import cv2 |
| import numpy as np |
|
|
| |
|
|
|
|
| def process_images(image_files, crop, y_start, y_end, x_start, x_end): |
| if not image_files: |
| return "No images uploaded.", None |
|
|
| |
| extracted_images = [] |
| for item in image_files: |
| if isinstance(item, tuple): |
| |
| img = item[0] |
| else: |
| |
| img = item |
|
|
| |
| if img is not None and isinstance(img, np.ndarray): |
| extracted_images.append(img) |
|
|
| |
| if not extracted_images: |
| return "No valid images found for stitching.", None |
|
|
| try: |
| |
| if crop: |
| crop_coords = (int(y_start), int(y_end), int(x_start), int(x_end)) |
| else: |
| crop_coords = None |
|
|
| |
| stitcher = cv2.Stitcher_create() |
|
|
| |
| status, panorama = stitcher.stitch(extracted_images) |
|
|
| if status != cv2.Stitcher_OK: |
| raise RuntimeError(f"Stitching failed with status code {status}.") |
|
|
| if crop: |
| y_start, y_end, x_start, x_end = crop_coords |
| cropped_panorama = panorama[y_start:y_end, x_start:x_end] |
| return panorama, cropped_panorama |
|
|
| return panorama, None |
|
|
| except Exception as e: |
| |
| raise gr.Error(f"Error during stitching: {str(e)}") |
|
|
|
|
| |
| with gr.Blocks(title="Creating Panorama using OpenCV", theme=gr.themes.Soft()) as demo: |
| gr.Markdown("# Creating Panorama using OpenCV") |
| gr.Markdown("Upload the series of images sequentially and get the perfect Panorama!") |
|
|
| with gr.Row(equal_height=True): |
| |
| examples = [ |
| "./scene/scene1.jpg", |
| "./scene/scene2.jpg", |
| "./scene/scene3.jpg", |
| "./scene/scene4.jpg", |
| "./scene/scene5.jpg", |
| "./scene/scene6.jpg", |
| "./scene/scene7.jpg", |
| "./scene/scene8.jpg", |
| ] |
| with gr.Column(): |
| image_upload = gr.Gallery( |
| value=examples, |
| columns=4, |
| label="Upload Images", |
| file_types=["image"], |
| format="jpeg", |
| type="numpy", |
| ) |
| crop_checkbox = gr.Checkbox(label="Apply Cropping to Panorama", value=False) |
| with gr.Row(): |
| y_start = gr.Number(label="Crop Y Start", value=90, interactive=True) |
| y_end = gr.Number(label="Crop Y End", value=867, interactive=True) |
| with gr.Row(): |
| x_start = gr.Number(label="Crop X Start", value=1, interactive=True) |
| x_end = gr.Number(label="Crop X End", value=2000, interactive=True) |
| stitch_button = gr.Button("Stitch Images") |
| with gr.Row(): |
| with gr.Column(): |
| stitched_output = gr.Image(label="Stitched Panorama") |
| cropped_output = gr.Image(label="Cropped Panorama") |
|
|
|
|
| |
| def toggle_crop_inputs(crop): |
| return gr.update(visible=crop), gr.update(visible=crop), gr.update(visible=crop), gr.update(visible=crop) |
|
|
| crop_checkbox.change(fn=toggle_crop_inputs, inputs=[crop_checkbox], outputs=[y_start, y_end, x_start, x_end]) |
|
|
| |
| stitch_button.click( |
| fn=process_images, |
| inputs=[image_upload, crop_checkbox, y_start, y_end, x_start, x_end], |
| outputs=[stitched_output, cropped_output], |
| ) |
|
|
| gr.Markdown( |
| """ |
| **Note**: |
| - Ensure that the uploaded images have overlapping regions for successful stitching. |
| - Cropping coordinates should be within the dimensions of the stitched panorama. |
| """ |
| ) |
|
|
| |
| demo.launch(show_error=True) |
|
|