File size: 6,808 Bytes
1baca7f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import torch
import gradio as gr
from PIL import Image
import os
import zipfile

# Load the YOLOv5 model (ensure the path is correct)
model = torch.hub.load(
    'ultralytics/yolov5', 'custom', path='best-3.pt'
)

# Global variables to store images and labels for carousel functionality
processed_images = []
label_contents = []
processed_image_paths = []

# Temporary folder for saving processed files
TEMP_DIR = "temp_processed"
os.makedirs(TEMP_DIR, exist_ok=True)

# Function to process all uploaded images
def process_images(files):
    global processed_images, label_contents, processed_image_paths
    processed_images = []
    label_contents = []
    processed_image_paths = []

    # Clear the temp directory
    for f in os.listdir(TEMP_DIR):
        os.remove(os.path.join(TEMP_DIR, f))

    for i, file_path in enumerate(files):
        # Open the image using the file path
        img = Image.open(file_path)

        # Run inference
        results = model(img)

        # Convert results to Image format for display
        results.render()
        if hasattr(results, 'ims'):
            output_image = Image.fromarray(results.ims[0])
        else:
            output_image = Image.fromarray(results.imgs[0])

        # Save the processed image and its labels
        processed_images.append(output_image)

        # Generate YOLO-format labels as a string
        label_content = ""
        for *box, conf, cls in results.xywh[0]:
            class_id = int(cls)
            x_center, y_center, width, height = box
            label_content += f"{class_id} {x_center} {y_center} {width} {height}\n"
        label_contents.append(label_content)

        # Save the image to the temp folder
        image_path = os.path.join(TEMP_DIR, f"processed_image_{i}.png")
        output_image.save(image_path)
        processed_image_paths.append(image_path)

        # Save the label content to a text file
        label_filename = f"annotation_{i}.txt"
        label_path = os.path.join(TEMP_DIR, label_filename)
        with open(label_path, "w") as label_file:
            label_file.write(label_content)

    # Return the first image and its labels
    if processed_images:
        return processed_images[0], label_contents[0], 0  # Start with index 0
    else:
        return None, "No images found.", 0

# Function to create and return the path to the ZIP file for download
def create_zip():
    zip_filename = "processed_images_annotations.zip"
    zip_path = os.path.join(TEMP_DIR, zip_filename)

    # Remove existing ZIP file if it exists
    if os.path.exists(zip_path):
        os.remove(zip_path)

    with zipfile.ZipFile(zip_path, 'w') as z:
        # Add images and labels to the ZIP file
        for image_path in processed_image_paths:
            z.write(image_path, os.path.basename(image_path))
            # Get index from image filename
            image_filename = os.path.basename(image_path)
            base_name, ext = os.path.splitext(image_filename)
            index = base_name.split('_')[-1]
            # Construct label filename
            label_filename = f"annotation_{index}.txt"
            label_path = os.path.join(TEMP_DIR, label_filename)
            z.write(label_path, label_filename)

    return zip_path  # Return the file path as a string

# Function to navigate through images
def next_image(index):
    global processed_images, label_contents
    if processed_images:
        index = (index + 1) % len(processed_images)
        return processed_images[index], label_contents[index], index
    else:
        return None, "No images processed.", index

def prev_image(index):
    global processed_images, label_contents
    if processed_images:
        index = (index - 1) % len(processed_images)
        return processed_images[index], label_contents[index], index
    else:
        return None, "No images processed.", index

# Gradio interface
with gr.Blocks() as interface:
    # Welcome message and general instructions
    gr.Markdown("## Welcome to the Construction Image Processing App!")
    gr.Markdown("""
    This app allows you to upload multiple construction-related images, process them using a custom YOLO model, and download the processed images along with their YOLO-format annotations.
    
    ### How to Use:
    1. **Upload**: Upload multiple images for processing.
    2. **View**: Navigate through the processed images using the 'Previous' and 'Next' buttons.
    3. **Download**: Download all processed images and annotations as a ZIP file.
    
    Follow the instructions below to get started!
    """)

    # Step 1: Upload Instructions
    gr.Markdown("### Step 1: Upload Your Images")
    gr.Markdown("Upload multiple construction-related image files that you want to process using the model. The supported file types are JPEG and PNG.")

    # Multiple file input and display area
    file_input = gr.Files(label="Upload multiple image files", type="filepath")
    image_display = gr.Image(label="Processed Image")
    label_display = gr.Textbox(label="YOLO Annotation for the Processed Image")

    # Step 2: Navigation Instructions
    gr.Markdown("### Step 2: View Your Processed Images")
    gr.Markdown("After processing, use the 'Previous Image' and 'Next Image' buttons to navigate through the processed images and view their annotations.")

    # Buttons for carousel navigation
    prev_button = gr.Button("Previous Image")
    next_button = gr.Button("Next Image")

    # Hidden state to store current index
    current_index = gr.State(0)

    # Step 3: Download Instructions
    gr.Markdown("### Step 3: Download All Processed Images and Annotations")
    gr.Markdown("Click the 'Prepare and Download All' button to download a ZIP file containing all processed images and YOLO annotations.")

    # Button to download all processed images and annotations as a ZIP file
    download_button = gr.Button("Prepare and Download All")
    download_file = gr.File()

    # Define functionality when files are uploaded
    file_input.change(
        process_images,
        inputs=file_input,
        outputs=[image_display, label_display, current_index]
    )

    # Define functionality for next and previous buttons
    next_button.click(
        next_image,
        inputs=current_index,
        outputs=[image_display, label_display, current_index]
    )
    prev_button.click(
        prev_image,
        inputs=current_index,
        outputs=[image_display, label_display, current_index]
    )

    # Define functionality for the download button to zip the files and allow download
    def prepare_download():
        zip_path = create_zip()
        return zip_path

    download_button.click(
        prepare_download,
        outputs=download_file
    )

# Launch the interface
interface.launch(share=True)