File size: 9,123 Bytes
a275fd7
 
 
 
 
 
994e76c
ec2f2e2
a275fd7
ec2f2e2
994e76c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a275fd7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ec2f2e2
994e76c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a275fd7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42b94c5
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
import gradio as gr
import os
from rembg import remove
from PIL import Image
import io
import zipfile
from typing import List, Tuple, Union, IO, Optional
import spaces

@spaces.GPU
def remove_background_single(image_file: Union[str, IO[bytes]]) -> Optional[Image.Image]:
    """Removes the background from a single image.

    This function takes an image file (either as a path or a file-like object),
    processes it to remove the background, and returns the result as a 
    Pillow (PIL) Image object with a transparent background.

    Args:
        image_file: The input image. Can be a path to a
            file on disk or a file-like object (e.g., from a file upload).

    Returns:
        A Pillow Image object with the background removed, or None if 
        the input was None.
    """
    if image_file is None:
        return None
    
    # Read the image data
    if hasattr(image_file, 'read'):
        input_data = image_file.read()
    else:
        with open(image_file, 'rb') as f:
            input_data = f.read()
    
    # Remove background
    output_data = remove(input_data)
    
    # Convert to PIL Image
    output_image = Image.open(io.BytesIO(output_data))
    return output_image

@spaces.GPU
def remove_background_multiple(image_files: List[Union[str, IO[bytes]]]) -> Tuple[Optional[str], List[Image.Image]]:
    """Removes backgrounds from multiple images and provides a zip archive.

    This function processes a list of image files. For each image, it removes
    the background, then bundles all the processed images (in PNG format)
    into a single zip file for download. It also returns a small number of
    processed images as previews for display in the UI.

    Args:
        image_files: A list of input images. Each element can be a 
            path to a file or a file-like object.

    Returns:
        A tuple containing:
            - A string with the file path to the generated zip archive. This 
              is `None` if the input list was empty.
            - A list of up to 5 processed Pillow Image objects to be used 
              as a preview.
    """
    if not image_files:
        return None, []
    
    processed_images = []
    preview_images = []
    
    # Create a zip file in memory
    zip_buffer = io.BytesIO()
    
    with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
        for i, image_file in enumerate(image_files):
            try:
                # Get original filename or create one
                if hasattr(image_file, 'name') and image_file.name:
                    original_name = os.path.basename(image_file.name)
                    name_without_ext = os.path.splitext(original_name)[0]
                else:
                    name_without_ext = f"image_{i+1}"
                
                # Remove background
                processed_image = remove_background_single(image_file)
                
                if processed_image:
                    # Save to zip file
                    img_buffer = io.BytesIO()
                    processed_image.save(img_buffer, format='PNG')
                    img_buffer.seek(0)
                    
                    zip_file.writestr(f"{name_without_ext}_no_bg.png", img_buffer.getvalue())
                    
                    # Add to preview (limit to first 5 images for display)
                    if len(preview_images) < 5:
                        preview_images.append(processed_image)
                    
            except Exception as e:
                print(f"Error processing image {i+1}: {str(e)}")
                continue
    
    zip_buffer.seek(0)
    
    # Save zip file temporarily
    zip_path = "processed_images.zip"
    with open(zip_path, 'wb') as f:
        f.write(zip_buffer.getvalue())
    
    return zip_path, preview_images

def process_images(single_image, multiple_images, processing_mode):
    """Main processing function based on selected mode"""
    if processing_mode == "Single Image":
        if single_image is None:
            return None, None, None, "Please upload an image first."
        
        try:
            result = remove_background_single(single_image)
            return result, None, None, "Background removed successfully!"
        except Exception as e:
            return None, None, None, f"Error processing image: {str(e)}"
    
    else:  # Multiple Images
        if not multiple_images:
            return None, None, None, "Please upload at least one image."
        
        try:
            zip_file, preview_images = remove_background_multiple(multiple_images)
            if zip_file and preview_images:
                return None, preview_images, zip_file, f"Processed {len(multiple_images)} images successfully! Download the zip file to get all results."
            else:
                return None, None, None, "No images were processed successfully."
        except Exception as e:
            return None, None, None, f"Error processing images: {str(e)}"

# Create Gradio interface
with gr.Blocks(title="Background Removal Tool", theme=gr.themes.Default()) as app:
    gr.Markdown(
        """
        # 🖼️ Background Removal Tool
        
        Upload your images and get them back with transparent backgrounds!
        
        **Choose your mode:**
        - **Single Image**: Upload one image and preview the result
        - **Multiple Images**: Upload multiple images and download them as a zip file
        """
    )
    
    with gr.Row():
        processing_mode = gr.Radio(
            choices=["Single Image", "Multiple Images"],
            value="Single Image",
            label="Processing Mode"
        )
    
    with gr.Row():
        with gr.Column():
            # Single image input (visible by default)
            single_image_input = gr.File(
                label="Upload Single Image",
                file_types=["image"],
                visible=True
            )
            
            # Multiple images input (hidden by default)
            multiple_images_input = gr.File(
                label="Upload Multiple Images",
                file_count="multiple",
                file_types=["image"],
                visible=False
            )
            
            process_btn = gr.Button("Remove Background", variant="primary", size="lg")
        
        with gr.Column():
            # Output for single image
            single_output = gr.Image(
                label="Result",
                visible=True
            )
            
            # Output for multiple images
            multiple_output_gallery = gr.Gallery(
                label="Preview (first 5 images)",
                visible=False,
                columns=3,
                rows=2,
                height="auto"
            )
            
            download_file = gr.File(
                label="Download All Processed Images",
                visible=False
            )
    
    status_message = gr.Textbox(label="Status", interactive=False)
    
    # Function to toggle visibility based on mode
    def toggle_inputs(mode):
        if mode == "Single Image":
            return (
                gr.update(visible=True),   # single_image_input
                gr.update(visible=False),  # multiple_images_input
                gr.update(visible=True),   # single_output
                gr.update(visible=False),  # multiple_output_gallery
                gr.update(visible=False)   # download_file
            )
        else:
            return (
                gr.update(visible=False),  # single_image_input
                gr.update(visible=True),   # multiple_images_input
                gr.update(visible=False),  # single_output
                gr.update(visible=True),   # multiple_output_gallery
                gr.update(visible=True)    # download_file
            )
    
    # Toggle inputs when mode changes
    processing_mode.change(
        fn=toggle_inputs,
        inputs=[processing_mode],
        outputs=[single_image_input, multiple_images_input, single_output, multiple_output_gallery, download_file]
    )
    
    # Process images when button is clicked
    process_btn.click(
        fn=process_images,
        inputs=[single_image_input, multiple_images_input, processing_mode],
        outputs=[single_output, multiple_output_gallery, download_file, status_message]
    )
    
    # Remove the separate gallery update function since we're handling it directly now

    gr.Markdown(
        """
        ### 📝 Instructions:
        1. Choose your processing mode (Single or Multiple images)
        2. Upload your image(s) - supports PNG, JPG, JPEG formats
        3. Click "Remove Background" to process
        4. For single images: preview the result directly
        5. For multiple images: download the zip file containing all processed images
        
        ### ⚡ Features:
        - Automatic background removal using AI
        - Support for batch processing
        - Transparent PNG output
        - Easy download of results
        """
    )

if __name__ == "__main__":
    app.launch()