Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,90 +1,95 @@
|
|
1 |
-
from flask import Flask, render_template, request, jsonify
|
2 |
-
import google.generativeai as genai
|
3 |
import os
|
4 |
-
import
|
5 |
import base64
|
6 |
-
import
|
7 |
-
from
|
|
|
|
|
|
|
8 |
|
9 |
-
# Configure
|
10 |
-
|
11 |
|
12 |
-
#
|
13 |
-
|
14 |
|
|
|
15 |
app = Flask(__name__)
|
16 |
-
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
-
|
30 |
-
if not image_data or not object_type:
|
31 |
-
return jsonify({"success": False, "message": "Missing required parameters"})
|
32 |
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
-
|
42 |
-
with tempfile.TemporaryDirectory() as temp_dir:
|
43 |
-
input_path = os.path.join(temp_dir, "input.png")
|
44 |
-
with open(input_path, "wb") as f:
|
45 |
-
f.write(image_bytes)
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
response = model.generate_content(
|
52 |
-
[prompt, genai.upload_file(input_path)],
|
53 |
-
generation_config={
|
54 |
-
"temperature": 0.9,
|
55 |
-
"top_p": 0.95,
|
56 |
-
"top_k": 32,
|
57 |
-
"max_output_tokens": 4096,
|
58 |
-
},
|
59 |
-
safety_settings={
|
60 |
-
"HARM_CATEGORY_CIVIC_INTEGRITY": "BLOCK_NONE",
|
61 |
-
"HARM_CATEGORY_HARASSMENT": "BLOCK_NONE",
|
62 |
-
"HARM_CATEGORY_HATE_SPEECH": "BLOCK_NONE",
|
63 |
-
"HARM_CATEGORY_SEXUALLY_EXPLICIT": "BLOCK_NONE",
|
64 |
-
"HARM_CATEGORY_DANGEROUS_CONTENT": "BLOCK_NONE"
|
65 |
-
}
|
66 |
-
)
|
67 |
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
with open(output_path, "wb") as f:
|
75 |
-
f.write(part.inline_data.data)
|
76 |
-
return jsonify({
|
77 |
-
"success": True,
|
78 |
-
"resultPath": output_path
|
79 |
-
})
|
80 |
-
elif hasattr(part, 'text'):
|
81 |
-
logging.info(f"Text response: {part.text}")
|
82 |
|
83 |
-
|
|
|
84 |
|
|
|
|
|
|
|
|
|
85 |
except Exception as e:
|
86 |
-
|
87 |
-
return jsonify({"success": False, "message": f"Processing error: {str(e)}"})
|
88 |
|
89 |
-
if __name__ ==
|
90 |
-
|
|
|
|
|
|
|
|
1 |
import os
|
2 |
+
import io
|
3 |
import base64
|
4 |
+
import tempfile
|
5 |
+
from flask import Flask, render_template, request, jsonify
|
6 |
+
from google import genai
|
7 |
+
from google.genai import types
|
8 |
+
from PIL import Image
|
9 |
|
10 |
+
# Configure Gemini API key using an environment variable
|
11 |
+
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
|
12 |
|
13 |
+
# Initialize Gemini client
|
14 |
+
client = genai.Client()
|
15 |
|
16 |
+
# Initialize Flask app
|
17 |
app = Flask(__name__)
|
|
|
18 |
|
19 |
+
def save_image(image_data):
|
20 |
+
"""Save the image from a base64 string to a temporary file and return its path."""
|
21 |
+
# image_data is expected to be in the format "data:image/png;base64,...."
|
22 |
+
header, encoded = image_data.split(',', 1)
|
23 |
+
image_bytes = base64.b64decode(encoded)
|
24 |
+
image = Image.open(io.BytesIO(image_bytes))
|
25 |
+
temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
|
26 |
+
image.save(temp_file, "PNG")
|
27 |
+
return temp_file.name
|
28 |
|
29 |
+
def remove_object_from_image(image_path, object_type):
|
30 |
+
"""Use Gemini API to remove a specified object from the image."""
|
31 |
+
# Upload the image file to Gemini
|
32 |
+
uploaded_file = client.files.upload(file=image_path)
|
33 |
+
|
34 |
+
# Prepare the input parts:
|
35 |
+
# 1. The image file
|
36 |
+
parts = [types.Part.from_uri(file_uri=uploaded_file.uri, mime_type="image/png")]
|
37 |
+
# 2. The Gemini magic text instructing removal
|
38 |
+
if object_type:
|
39 |
+
parts.append(types.Part.from_text(text=f"Remove {object_type} from the image"))
|
40 |
+
|
41 |
+
contents = [types.Content(role="user", parts=parts)]
|
42 |
+
generate_content_config = types.GenerateContentConfig(
|
43 |
+
temperature=1,
|
44 |
+
top_p=0.95,
|
45 |
+
top_k=40,
|
46 |
+
max_output_tokens=8192,
|
47 |
+
response_modalities=["image", "text"],
|
48 |
+
safety_settings=[types.SafetySetting(category="HARM_CATEGORY_CIVIC_INTEGRITY", threshold="OFF")],
|
49 |
+
response_mime_type="text/plain",
|
50 |
+
)
|
51 |
|
52 |
+
result_image = None
|
|
|
|
|
53 |
|
54 |
+
# Process the generation stream from Gemini
|
55 |
+
for chunk in client.models.generate_content_stream(
|
56 |
+
model="gemini-2.0-flash-exp-image-generation",
|
57 |
+
contents=contents,
|
58 |
+
config=generate_content_config,
|
59 |
+
):
|
60 |
+
if chunk.candidates and chunk.candidates[0].content and chunk.candidates[0].content.parts:
|
61 |
+
part = chunk.candidates[0].content.parts[0]
|
62 |
+
if part.inline_data:
|
63 |
+
# Save the generated binary image data
|
64 |
+
file_name = "generated_output.png"
|
65 |
+
with open(file_name, "wb") as f:
|
66 |
+
f.write(part.inline_data.data)
|
67 |
+
result_image = file_name
|
68 |
|
69 |
+
return result_image
|
|
|
|
|
|
|
|
|
70 |
|
71 |
+
@app.route('/')
|
72 |
+
def index():
|
73 |
+
"""Render the main page."""
|
74 |
+
return render_template('index.html')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
|
76 |
+
@app.route('/process', methods=['POST'])
|
77 |
+
def process_image():
|
78 |
+
"""Handle image processing via POST request."""
|
79 |
+
data = request.get_json()
|
80 |
+
image_data = data['image']
|
81 |
+
object_type = data['objectType']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
82 |
|
83 |
+
# Save the uploaded image locally
|
84 |
+
image_path = save_image(image_data)
|
85 |
|
86 |
+
try:
|
87 |
+
# Use Gemini to remove the object from the image
|
88 |
+
result_image = remove_object_from_image(image_path, object_type)
|
89 |
+
return jsonify({'success': True, 'resultPath': result_image})
|
90 |
except Exception as e:
|
91 |
+
return jsonify({'success': False, 'message': str(e)})
|
|
|
92 |
|
93 |
+
if __name__ == '__main__':
|
94 |
+
# For local testing; in production, your hosting provider will manage the server.
|
95 |
+
app.run(debug=True)
|