File size: 4,201 Bytes
88eaee2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import gradio as gr
import cv2
import numpy as np

# from panorama import stitch_images


def process_images(image_files, crop, y_start, y_end, x_start, x_end):
    if not image_files:
        return "No images uploaded.", None

    # Extract the first element of each tuple if it's a tuple
    extracted_images = []
    for item in image_files:
        if isinstance(item, tuple):
            # If item is (img, None), extract 'img' only
            img = item[0]
        else:
            # If for some reason it's not a tuple, assume it's already the image
            img = item

        # Check if img is not None and is a numpy array
        if img is not None and isinstance(img, np.ndarray):
            extracted_images.append(img)

    # If after extraction no valid images found
    if not extracted_images:
        return "No valid images found for stitching.", None

    try:
        # Define crop coordinates
        if crop:
            crop_coords = (int(y_start), int(y_end), int(x_start), int(x_end))
        else:
            crop_coords = None

        # Initialize OpenCV's Stitcher
        stitcher = cv2.Stitcher_create()

        # Perform stitching
        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 a gradio Error to avoid returning image outputs as text
        raise gr.Error(f"Error during stitching: {str(e)}")


# Define Gradio interface using Blocks for better layout control
with gr.Blocks(title="Creating Panorama using OpenCV") 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):
        with gr.Column():
            image_upload = gr.Gallery(
                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")
    #     examples = [
    #         [["./Apollo-8-Launch.png", "./times_square.jpg"], True, 90, 867, 1, 2000],
    #     ]

    # with gr.Row():
    #     gr.Examples(
    #         examples=examples,
    #         inputs=[image_upload, crop_checkbox, y_start, y_end, x_start, x_end],
    #         label="Load Example Images",
    #     )

    # Disable cropping input fields if checkbox is not selected
    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])

    # Define the button click event
    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.
        """
    )

# Launch the Gradio interface
demo.launch(show_error=True)