mr-dee commited on
Commit
996813c
·
verified ·
1 Parent(s): 6ce98b0

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +196 -0
app.py ADDED
@@ -0,0 +1,196 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ import os
3
+ import gradio as gr
4
+ from google import genai
5
+ from google.genai import types
6
+ from google.genai.types import HarmBlockThreshold
7
+ from PIL import Image
8
+ from io import BytesIO
9
+ import tempfile
10
+ from dotenv import load_dotenv
11
+
12
+ # Load environment variables from .env file
13
+ load_dotenv()
14
+
15
+ def swap_clothing(person_image, clothing_image):
16
+ """
17
+ Generate an image where the person from the first image is wearing clothing from the second image.
18
+
19
+ Args:
20
+ person_image: The image containing the person
21
+ clothing_image: The image containing the clothing to swap
22
+
23
+ Returns:
24
+ The generated image with the clothing swapped and any relevant messages
25
+ """
26
+ # Check if both images are provided
27
+ if person_image is None or clothing_image is None:
28
+ return None, "Please upload both images."
29
+
30
+ # Get API key from environment variables
31
+ api_key = os.environ.get("GEMINI_API_KEY")
32
+ if not api_key:
33
+ return None, "GEMINI_API_KEY not found in environment variables."
34
+
35
+ client = genai.Client(api_key=api_key)
36
+
37
+ # Save both uploaded images to temporary files
38
+ temp_files = []
39
+ try:
40
+ for img, prefix in [(person_image, "person"), (clothing_image, "clothing")]:
41
+ with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as temp_file:
42
+ img.save(temp_file.name)
43
+ temp_files.append(temp_file.name)
44
+
45
+ # Upload both files to Gemini
46
+ files = [
47
+ client.files.upload(file=temp_files[0]), # person image
48
+ client.files.upload(file=temp_files[1]), # clothing image
49
+ ]
50
+
51
+ # Create the prompt
52
+ prompt = '''
53
+ Edit the person's clothing by swapping it with the clothing in the clothing image.
54
+ Retain the same facial features, pose and background from the person image.
55
+ The output image should be an image of the person wearing the clothing from the clothing image.
56
+ The image pose and background should be the same as the person image but with the new clothing:
57
+ '''
58
+
59
+ contents = [
60
+ types.Content(
61
+ role="user",
62
+ parts=[
63
+ types.Part.from_text(text="This is the person image. Do not change the face or features of the person. Pay attention and retain the background, pose, facial features."),
64
+ types.Part.from_uri(
65
+ file_uri=files[0].uri,
66
+ mime_type=files[0].mime_type,
67
+ ),
68
+ types.Part.from_text(text="This is the clothing image."),
69
+ types.Part.from_uri(
70
+ file_uri=files[1].uri,
71
+ mime_type=files[1].mime_type,
72
+ ),
73
+ types.Part.from_text(text=prompt),
74
+ types.Part.from_uri(
75
+ file_uri=files[0].uri,
76
+ mime_type=files[0].mime_type,
77
+ ),
78
+ ],
79
+ ),
80
+ ]
81
+
82
+ generate_content_config = types.GenerateContentConfig(
83
+ temperature=0.12,
84
+ top_p=0.95,
85
+ top_k=40,
86
+ max_output_tokens=8192,
87
+ response_modalities=[
88
+ "image",
89
+ "text",
90
+ ],
91
+ safety_settings=[
92
+ types.SafetySetting(
93
+ category="HARM_CATEGORY_HARASSMENT",
94
+ threshold=HarmBlockThreshold.BLOCK_NONE,
95
+ ),
96
+ types.SafetySetting(
97
+ category="HARM_CATEGORY_HATE_SPEECH",
98
+ threshold=HarmBlockThreshold.BLOCK_NONE,
99
+ ),
100
+ types.SafetySetting(
101
+ category="HARM_CATEGORY_SEXUALLY_EXPLICIT",
102
+ threshold=HarmBlockThreshold.BLOCK_NONE,
103
+ ),
104
+ types.SafetySetting(
105
+ category="HARM_CATEGORY_DANGEROUS_CONTENT",
106
+ threshold=HarmBlockThreshold.BLOCK_NONE,
107
+ ),
108
+ ],
109
+ response_mime_type="text/plain",
110
+ )
111
+
112
+ try:
113
+ response = client.models.generate_content(
114
+ model="models/gemini-2.0-flash-exp",
115
+ contents=contents,
116
+ config=generate_content_config,
117
+ )
118
+
119
+ output_image = None
120
+ output_text = ""
121
+
122
+ # Process the response
123
+ if response and hasattr(response, 'candidates') and response.candidates:
124
+ candidate = response.candidates[0]
125
+ if hasattr(candidate, 'content') and candidate.content:
126
+ for part in candidate.content.parts:
127
+ if part.text is not None:
128
+ output_text += part.text + "\n"
129
+ elif part.inline_data is not None:
130
+ try:
131
+ if isinstance(part.inline_data.data, bytes):
132
+ image_data = part.inline_data.data
133
+ else:
134
+ image_data = base64.b64decode(part.inline_data.data)
135
+
136
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as temp_file:
137
+ temp_file.write(image_data)
138
+ temp_file_path = temp_file.name
139
+
140
+ output_image = Image.open(temp_file_path)
141
+ os.unlink(temp_file_path)
142
+
143
+ except Exception as img_error:
144
+ output_text += f"Error processing image: {str(img_error)}\n"
145
+ else:
146
+ output_text = "The model did not generate a valid response. Please try again with different images."
147
+
148
+ except Exception as api_error:
149
+ output_text = f"API Error: {str(api_error)}\n\nDetails: {type(api_error).__name__}"
150
+ return None, output_text
151
+
152
+ finally:
153
+ # Clean up temporary files
154
+ for temp_file in temp_files:
155
+ if os.path.exists(temp_file):
156
+ os.unlink(temp_file)
157
+
158
+ return output_image, output_text
159
+
160
+ except Exception as e:
161
+ # Clean up temporary files in case of error
162
+ for temp_file in temp_files:
163
+ if os.path.exists(temp_file):
164
+ os.unlink(temp_file)
165
+
166
+ error_details = f"Error: {str(e)}\n\nType: {type(e).__name__}"
167
+ print(f"Exception occurred: {error_details}")
168
+ return None, error_details
169
+
170
+ # Create the Gradio interface
171
+ def create_interface():
172
+ with gr.Blocks(title="Virtual Clothing Try-On") as app:
173
+ gr.Markdown("# Virtual Clothing Try-On")
174
+ gr.Markdown("Upload a photo of yourself and a photo of clothing you'd like to try on!")
175
+
176
+ with gr.Row():
177
+ with gr.Column():
178
+ person_image = gr.Image(label="Your Photo", type="pil", image_mode="RGB")
179
+ clothing_image = gr.Image(label="Clothing Photo", type="pil", image_mode="RGB")
180
+ submit_btn = gr.Button("Generate")
181
+
182
+ with gr.Column():
183
+ output_image = gr.Image(label="Result", type="pil")
184
+ output_text = gr.Textbox(label="Response", lines=3)
185
+
186
+ submit_btn.click(
187
+ fn=swap_clothing,
188
+ inputs=[person_image, clothing_image],
189
+ outputs=[output_image, output_text]
190
+ )
191
+
192
+ return app
193
+
194
+ if __name__ == "__main__":
195
+ app = create_interface()
196
+ app.launch()