Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- .DS_Store +0 -0
- .gitattributes +4 -0
- Dockerfile +18 -0
- README.md +5 -9
- backend.py +55 -0
- banner_generator.py +208 -0
- frontend.py +129 -0
- images/.DS_Store +0 -0
- images/logos/bigbasket_logo.png +0 -0
- images/logos/gemini_logo.png +0 -0
- images/logos/google_logo.png +0 -0
- images/output/.DS_Store +0 -0
- images/sample/.DS_Store +0 -0
- images/sample/input_sample/biscuit_back.jpg +0 -0
- images/sample/input_sample/biscuit_front.jpg +0 -0
- images/sample/output_sample/.DS_Store +0 -0
- images/sample/output_sample/dahi_durga puja_14344.png +0 -0
- images/sample/output_sample/dahi_durga puja_58861.png +3 -0
- images/sample/output_sample/doi dahi_durga puja_92098.png +3 -0
- images/sample/output_sample/doi dahi_durga puja_93931.png +3 -0
- images/sample/output_sample/pepsi and coca cola_durga puja_red, white, green, orange and blue_20 percent discount_7819.png +3 -0
- images/temp/.DS_Store +0 -0
- notebooks/.DS_Store +0 -0
- notebooks/__init__.py +1 -0
- notebooks/vg_2_0a_banner_generator.ipynb +0 -0
- requirements.txt +7 -0
.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
.gitattributes
CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
images/sample/output_sample/dahi_durga[[:space:]]puja_58861.png filter=lfs diff=lfs merge=lfs -text
|
37 |
+
images/sample/output_sample/doi[[:space:]]dahi_durga[[:space:]]puja_92098.png filter=lfs diff=lfs merge=lfs -text
|
38 |
+
images/sample/output_sample/doi[[:space:]]dahi_durga[[:space:]]puja_93931.png filter=lfs diff=lfs merge=lfs -text
|
39 |
+
images/sample/output_sample/pepsi[[:space:]]and[[:space:]]coca[[:space:]]cola_durga[[:space:]]puja_red,[[:space:]]white,[[:space:]]green,[[:space:]]orange[[:space:]]and[[:space:]]blue_20[[:space:]]percent[[:space:]]discount_7819.png filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use an official Python runtime as a base image
|
2 |
+
FROM python:3.11.9
|
3 |
+
|
4 |
+
# Set the working directory in the container
|
5 |
+
WORKDIR /app
|
6 |
+
|
7 |
+
# Copy requirements.txt and install dependencies
|
8 |
+
COPY requirements.txt /app/
|
9 |
+
RUN pip install -r requirements.txt
|
10 |
+
|
11 |
+
# Copy the rest of the application
|
12 |
+
COPY . /app/
|
13 |
+
|
14 |
+
# Expose the ports where the apps will run
|
15 |
+
EXPOSE 8000 7860
|
16 |
+
|
17 |
+
# Start both backend and frontend
|
18 |
+
CMD bash -c "uvicorn backend:app --host 0.0.0.0 --port 8000 && python frontend.py"
|
README.md
CHANGED
@@ -1,12 +1,8 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
|
4 |
-
colorFrom: purple
|
5 |
-
colorTo: pink
|
6 |
sdk: gradio
|
7 |
-
sdk_version: 4.44.
|
8 |
-
app_file: app.py
|
9 |
-
pinned: false
|
10 |
---
|
11 |
-
|
12 |
-
|
|
|
1 |
---
|
2 |
+
title: Bigbasket_Promo_Generator
|
3 |
+
app_file: frontend.py
|
|
|
|
|
4 |
sdk: gradio
|
5 |
+
sdk_version: 4.44.0
|
|
|
|
|
6 |
---
|
7 |
+
# bigbasket_promo_generator
|
8 |
+
AI Powered Banner and Promo Generator for Bigbasket
|
backend.py
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI, UploadFile, Form
|
2 |
+
from typing import List, Optional
|
3 |
+
from banner_generator import BannerGenerator, info # Import BannerGenerator and info
|
4 |
+
import shutil
|
5 |
+
import os
|
6 |
+
from fastapi.responses import FileResponse
|
7 |
+
|
8 |
+
app = FastAPI()
|
9 |
+
|
10 |
+
# Ensure directories for saving images exist
|
11 |
+
os.makedirs('images/temp', exist_ok=True)
|
12 |
+
os.makedirs('images/output', exist_ok=True)
|
13 |
+
|
14 |
+
# Endpoint for generating a banner
|
15 |
+
@app.post("/generate_banner")
|
16 |
+
async def generate_banner(
|
17 |
+
topic: str = Form(...),
|
18 |
+
images: List[UploadFile] = Form(...),
|
19 |
+
aspect_ratio: Optional[str] = Form(None) # Added aspect_ratio as input parameter
|
20 |
+
):
|
21 |
+
# Save uploaded images to disk
|
22 |
+
image_paths = []
|
23 |
+
for image in images:
|
24 |
+
temp_path = f"images/temp/{os.path.basename(image.filename)}"
|
25 |
+
try:
|
26 |
+
with open(temp_path, "wb") as buffer:
|
27 |
+
shutil.copyfileobj(image.file, buffer)
|
28 |
+
image_paths.append(temp_path)
|
29 |
+
except FileNotFoundError as e:
|
30 |
+
return {"error": f"Could not save image: {e}"}
|
31 |
+
|
32 |
+
# Create a BannerGenerator instance
|
33 |
+
banner_generator = BannerGenerator(
|
34 |
+
CONFIGS=info,
|
35 |
+
topic=topic,
|
36 |
+
images=image_paths,
|
37 |
+
aspect_ratio=aspect_ratio # Pass the aspect_ratio parameter
|
38 |
+
)
|
39 |
+
|
40 |
+
# Execute the banner generation process
|
41 |
+
try:
|
42 |
+
final_image_path = banner_generator.execute()
|
43 |
+
except Exception as e:
|
44 |
+
return {"error": f"Banner generation failed: {e}"}
|
45 |
+
|
46 |
+
# Return the relative path to the generated banner image
|
47 |
+
return {"image_path": f"/images/{os.path.basename(final_image_path)}"}
|
48 |
+
|
49 |
+
# Endpoint to serve images
|
50 |
+
@app.get("/images/{image_name}")
|
51 |
+
async def get_image(image_name: str):
|
52 |
+
image_path = os.path.join("images/output", image_name)
|
53 |
+
if not os.path.exists(image_path):
|
54 |
+
return {"error": "Image not found"}
|
55 |
+
return FileResponse(image_path)
|
banner_generator.py
ADDED
@@ -0,0 +1,208 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import configparser
|
3 |
+
import PIL
|
4 |
+
from PIL import Image
|
5 |
+
from typing import Any, List, Optional, Literal
|
6 |
+
from pydantic import BaseModel, Field
|
7 |
+
import google.generativeai as genai
|
8 |
+
import vertexai
|
9 |
+
from vertexai.preview.vision_models import ImageGenerationModel, GeneratedImage
|
10 |
+
from vertexai.preview.vision_models import Image as VertexImage
|
11 |
+
|
12 |
+
# Load configuration
|
13 |
+
config = configparser.ConfigParser()
|
14 |
+
config.read('config.ini')
|
15 |
+
|
16 |
+
api_key = config['credentials']['gemini_api_key']
|
17 |
+
proj_id = config['credentials']['gcp_project_id']
|
18 |
+
info = {"PROJECT_ID": proj_id, "LOCATION": "us-central1", "API_KEY": api_key}
|
19 |
+
|
20 |
+
# Create directories for temporary and output images if they do not exist
|
21 |
+
os.makedirs('images/temp', exist_ok=True)
|
22 |
+
os.makedirs('images/output', exist_ok=True)
|
23 |
+
|
24 |
+
class BannerGenerator(BaseModel):
|
25 |
+
"""Class responsible for generating banners using generative models."""
|
26 |
+
|
27 |
+
CONFIGS: dict
|
28 |
+
topic: str
|
29 |
+
images: List[str] | None = Field(default=None)
|
30 |
+
aspect_ratio: Optional[Literal["1:1", "9:16", "16:9", "4:3", "3:4"]] = None # Added aspect_ratio attribute
|
31 |
+
text_model: str = "gemini-1.5-flash"
|
32 |
+
image_model: str = "imagen-3.0-generate-001"
|
33 |
+
edit_model: str = "imagegeneration@006"
|
34 |
+
pm: Any = None
|
35 |
+
im: Any = None
|
36 |
+
em: Any = None
|
37 |
+
text_v0: str = None
|
38 |
+
text_v1: str = None
|
39 |
+
text_v2: str = None
|
40 |
+
text_v3: str = None
|
41 |
+
img_response_v1: Any = None
|
42 |
+
img_response_v2: Any = None
|
43 |
+
img_response_v3: Any = None
|
44 |
+
launch_state: bool = False
|
45 |
+
|
46 |
+
def __launch(self):
|
47 |
+
"""Launches the generative models and sets up environment."""
|
48 |
+
if not self.launch_state:
|
49 |
+
vertexai.init(project=self.CONFIGS['PROJECT_ID'], location=self.CONFIGS['LOCATION'])
|
50 |
+
genai.configure(api_key=self.CONFIGS['API_KEY'])
|
51 |
+
self.pm = genai.GenerativeModel(self.text_model)
|
52 |
+
self.im = ImageGenerationModel.from_pretrained(self.image_model)
|
53 |
+
self.em = ImageGenerationModel.from_pretrained(self.edit_model)
|
54 |
+
self.launch_state = True
|
55 |
+
print("Model Launch successful!")
|
56 |
+
|
57 |
+
def load_images(self) -> List[PIL.Image.Image]:
|
58 |
+
"""Loads images from file paths provided in the `images` attribute."""
|
59 |
+
self.__launch()
|
60 |
+
loaded_images = []
|
61 |
+
|
62 |
+
for image_path in self.images:
|
63 |
+
img = PIL.Image.open(image_path)
|
64 |
+
if img.mode == 'RGBA':
|
65 |
+
img = img.convert('RGB') # Convert to RGB if needed
|
66 |
+
loaded_images.append(img)
|
67 |
+
|
68 |
+
return loaded_images
|
69 |
+
|
70 |
+
def extract_image_information(self) -> str:
|
71 |
+
"""Extracts information from images using the generative text model."""
|
72 |
+
images = self.load_images()
|
73 |
+
extraction_prompt = '''Examine the set of images to extract information about the product (name, logo) in less than 80 words.'''
|
74 |
+
model_input = [extraction_prompt] + images
|
75 |
+
response = self.pm.generate_content(model_input)
|
76 |
+
print("Attached images examined!")
|
77 |
+
return response.text
|
78 |
+
|
79 |
+
def extract_information(self) -> None:
|
80 |
+
"""Extracts information from the given topic and images using a detailed analysis."""
|
81 |
+
self.__launch()
|
82 |
+
|
83 |
+
out_text = f"""Deep analyze text from retail advertising, marketing psychology, and thoroughly researched marketing studies perspective: {self.topic}
|
84 |
+
Extract the following information:
|
85 |
+
0. Product: Product name, brand and supplier, logo, tagline, size, packaging if available
|
86 |
+
1. Objective: 1 word for primary goal of the banner. Example - Awareness, Engagement, Conversion, Branding
|
87 |
+
2. Festival: Event or occasion it may be tied to. Example - Christmas, Diwali, Black Friday, Summer Sale, New Year, Generic
|
88 |
+
3. Headline: Suggest a main text that captures attention. Example - Discover [product] for [festival], Shop now and save!, Limited time offer, Innovate your life with [product]
|
89 |
+
4. Subheadline: Optional additional supporting information to clarify the offer. Example - Get 50% off until [date], Exclusive deal for festive season, Hurry offer ends soon
|
90 |
+
5. CTA: Add a call to action. Example - Buy now, Shop the collection, Discover More, Sign up today
|
91 |
+
6. Color Scheme: Use color palette based on audience, occasion, or product tone. Example - Red & Gold (Festive, Urgency), Blue & White (Trust, Calm), Green & Brown (Eco-friendly, Natural), Black & White (Elegant, Minimal)
|
92 |
+
7. Promotional offer: Suggest 1 best promotional offer. Example - MAX βΉ99 OFF, UP TO 60% OFF, UNDER βΉ999, MIN βΉ10 OFF, MIN 20% OFF, STARTS @βΉ99, FLAT βΉ100 OFF, FLAT 20% OFF, βΉ499 STORE, BUY 2 GET 1 FREE
|
93 |
+
8. Background color gradient: Dynamic color generation to match overall look and feel
|
94 |
+
9. Background theme: Festival oriented or generic if no festival
|
95 |
+
"""
|
96 |
+
self.text_v0 = self.pm.generate_content(out_text).text
|
97 |
+
|
98 |
+
# Information consolidation
|
99 |
+
out_text = f"Respond concisely and summarize in Python dictionary format only this: {self.text_v0}"
|
100 |
+
if self.images:
|
101 |
+
image_info = self.extract_image_information()
|
102 |
+
out_text += ' Product insights: ' + image_info
|
103 |
+
print(f"Product insights: {image_info}")
|
104 |
+
|
105 |
+
self.text_v1 = self.pm.generate_content(out_text).text[9:-5]
|
106 |
+
|
107 |
+
# Scrapper to ensure data integrity and consistency
|
108 |
+
out_text = f"Respond concisely by scrapping all unavailable information in Python dictionary format only this: {self.text_v1}"
|
109 |
+
self.text_v2 = self.pm.generate_content(out_text).text
|
110 |
+
|
111 |
+
print("Information collection complete!")
|
112 |
+
|
113 |
+
def create_text_prompt(self) -> None:
|
114 |
+
"""Creates a text prompt based on the extracted information."""
|
115 |
+
out_text = f"""Task: Fill in the values in this json: {self.text_v2}
|
116 |
+
Guidelines:
|
117 |
+
1. It will be used to generate an ads banner.
|
118 |
+
2. Ensure it has all details pair-wise meticulously captured.
|
119 |
+
3. All unknown/missing/unprovided variables are replaced with the attributes of the most probable shopper for that product.
|
120 |
+
4. Recheck and identify all ambiguity or any text that leads to uncertainty.
|
121 |
+
5. Replace all uncertainty with targeted values that make the most sense for the given product.
|
122 |
+
6. Quantify everything possible, like high, medium, and lows to percentage values based on marketing and psychometric research studies.
|
123 |
+
7. All KPIs and qualitative measures are to be used subcontextually only. Remove any details about statistical testing or names of any performance KPIs.
|
124 |
+
8. Avoid sentences and use only necessary keywords.
|
125 |
+
9. Remove all redundant key-value pairs.
|
126 |
+
"""
|
127 |
+
self.text_v3 = self.pm.generate_content(out_text).text
|
128 |
+
print("Information processed!")
|
129 |
+
|
130 |
+
def generate_image(self) -> str:
|
131 |
+
"""Generates an image based on the given prompt and saves it in images/temp/."""
|
132 |
+
prompt = f"""Realistic, subcontextually implied qualitative attributes inspired, excellent image quality ad capturing every detail in json:{self.text_v3}"""
|
133 |
+
|
134 |
+
# Adding the aspect ratio parameter to the image generation
|
135 |
+
if self.aspect_ratio:
|
136 |
+
self.img_response_v1 = self.im.generate_images(prompt=prompt, aspect_ratio=self.aspect_ratio)
|
137 |
+
else:
|
138 |
+
self.img_response_v1 = self.im.generate_images(prompt=prompt)
|
139 |
+
|
140 |
+
# Save the generated image to images/temp/
|
141 |
+
temp_img_path = 'images/temp/temp.jpg'
|
142 |
+
if os.path.exists(temp_img_path):
|
143 |
+
os.remove(temp_img_path)
|
144 |
+
self.img_response_v1.images[0].save(temp_img_path)
|
145 |
+
|
146 |
+
print("Image v1 generated!")
|
147 |
+
return temp_img_path
|
148 |
+
|
149 |
+
def identify_lags(self) -> str:
|
150 |
+
"""Identifies quality issues in the generated image and provides suggestions for improvement."""
|
151 |
+
prompt = f"""Be direct. Quality check the banner out of 10 on:
|
152 |
+
1. Promotional offer present as per instructions below
|
153 |
+
2. Ensure ALL texts pass grammatical checks
|
154 |
+
3. Color pallette as per instructions below
|
155 |
+
4. Occassion or festival theme is present as per instructions below
|
156 |
+
|
157 |
+
ONLY USE INFORMATION FROM {self.text_v3}. Don't DO NOT make up colors, promo or occasion. Make sure the promo and color pallete is followed as per above instructions.
|
158 |
+
|
159 |
+
Precisely point out errors and corresponding actions to fix the image where score is below 8.
|
160 |
+
Do not output anything about elements that need no change.
|
161 |
+
"""
|
162 |
+
temp_img_path = 'images/temp/temp.jpg'
|
163 |
+
response = self.pm.generate_content([prompt, PIL.Image.open(temp_img_path)])
|
164 |
+
print(f'Lags identified: {response.text}')
|
165 |
+
return response.text
|
166 |
+
|
167 |
+
def fix_image(self, retest: bool = False) -> str:
|
168 |
+
"""Attempts to fix the identified lags in the generated image and saves it."""
|
169 |
+
prompt = f'Realistic, subcontextually implied qualitative attributes inspired, excellent image quality ad by: {self.identify_lags()}'
|
170 |
+
temp_img_path = 'images/temp/temp.jpg'
|
171 |
+
|
172 |
+
base_image = VertexImage.load_from_file(location=temp_img_path)
|
173 |
+
self.img_response_v2 = self.em.edit_image(
|
174 |
+
base_image=base_image,
|
175 |
+
prompt=prompt,
|
176 |
+
edit_mode="inpainting-insert",
|
177 |
+
mask_mode="background"
|
178 |
+
)
|
179 |
+
self.img_response_v2.images[0].save(temp_img_path)
|
180 |
+
print("Image v2 generated!")
|
181 |
+
|
182 |
+
if retest:
|
183 |
+
prompt = f'Realistic, subcontextually implied qualitative attributes inspired, excellent image quality ad edit by: {self.identify_lags()}'
|
184 |
+
self.img_response_v3 = self.em.edit_image(
|
185 |
+
base_image=VertexImage.load_from_file(location=temp_img_path),
|
186 |
+
prompt=prompt,
|
187 |
+
edit_mode="inpainting-insert",
|
188 |
+
mask_mode="background"
|
189 |
+
)
|
190 |
+
self.img_response_v3.images[0].save(temp_img_path)
|
191 |
+
print("Image v3 generated!")
|
192 |
+
|
193 |
+
# Save final image to output directory with a name corresponding to the topic
|
194 |
+
output_filename = ''.join(e for e in self.topic if e.isalnum() or e == ' ')
|
195 |
+
output_filename = output_filename[:50].strip().replace(' ', '_') + ".jpg"
|
196 |
+
output_img_path = os.path.join('images/output', output_filename)
|
197 |
+
self.img_response_v2.images[0].save(output_img_path)
|
198 |
+
print(f"Final image saved as: {output_img_path}")
|
199 |
+
|
200 |
+
return output_img_path
|
201 |
+
|
202 |
+
def execute(self, QC=False) -> str:
|
203 |
+
"""Executes the entire workflow to generate and refine the banner."""
|
204 |
+
self.extract_information()
|
205 |
+
self.create_text_prompt()
|
206 |
+
self.generate_image()
|
207 |
+
final_image_path = self.fix_image(retest=QC)
|
208 |
+
return final_image_path
|
frontend.py
ADDED
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import requests
|
3 |
+
import os
|
4 |
+
|
5 |
+
# BASE_URL = "http://localhost:8000"
|
6 |
+
BASE_URL = os.getenv("BASE_URL", "http://localhost:8000") # Default to localhost for local testing
|
7 |
+
|
8 |
+
# Function to generate the banner
|
9 |
+
def generate_banner(topic, images, aspect_ratio):
|
10 |
+
# Preparing files for the request
|
11 |
+
files = [('images', (img.name, open(img.name, 'rb'))) for img in images]
|
12 |
+
data = {
|
13 |
+
'topic': topic,
|
14 |
+
'aspect_ratio': aspect_ratio
|
15 |
+
}
|
16 |
+
response = requests.post(f"{BASE_URL}/generate_banner", data=data, files=files)
|
17 |
+
|
18 |
+
# Close the files to prevent issues
|
19 |
+
for _, (_, file) in files:
|
20 |
+
file.close()
|
21 |
+
|
22 |
+
if response.status_code == 200:
|
23 |
+
result = response.json()
|
24 |
+
image_path = result.get("image_path")
|
25 |
+
if image_path:
|
26 |
+
# Construct the full URL to access the generated image
|
27 |
+
full_image_url = f"{BASE_URL}{image_path}"
|
28 |
+
return full_image_url
|
29 |
+
else:
|
30 |
+
return "Error: Generated image not found."
|
31 |
+
else:
|
32 |
+
return "Error generating banner."
|
33 |
+
|
34 |
+
# Function to preview uploaded images
|
35 |
+
def preview_images(images):
|
36 |
+
return images
|
37 |
+
|
38 |
+
# Gradio Interface
|
39 |
+
with gr.Blocks(theme=gr.themes.Soft()) as demo:
|
40 |
+
# Main Container for UI elements
|
41 |
+
with gr.Row():
|
42 |
+
# Left Column: Introduction, Banner Topic, Aspect Ratio, Upload Images, and Generate Button
|
43 |
+
with gr.Column(scale=1, min_width=300, elem_id="branding_section"):
|
44 |
+
gr.Markdown(
|
45 |
+
"""
|
46 |
+
<div style="text-align: left;">
|
47 |
+
<h1 style="font-size: 2.5rem; color: #ff6347; font-weight: bold;">Bigbasket Banner Generator</h1>
|
48 |
+
<p style="font-size: 1.25rem; color: #333;">Create beautiful, impactful banners with ease! Simply upload images, enter the topic, and let our AI generate stunning banners for your projects.</p>
|
49 |
+
<p style="font-size: 1.1rem; color: #555;">Powered by <b>Google Gemini</b> and <b>Google Imagen</b>.</p>
|
50 |
+
</div>
|
51 |
+
""", elem_id="intro_text"
|
52 |
+
)
|
53 |
+
# Moved Banner Topic Input Below "Powered by" Text
|
54 |
+
topic_input = gr.Textbox(label="π Banner Details (Product, Theme, Color, etc.)", placeholder="Enter the details for your banner", lines=2, elem_id="topic_input")
|
55 |
+
aspect_ratio_dropdown = gr.Dropdown(
|
56 |
+
label="π Select Aspect Ratio",
|
57 |
+
choices=["1:1", "9:16", "16:9", "4:3", "3:4"],
|
58 |
+
elem_id="aspect_ratio_input"
|
59 |
+
)
|
60 |
+
image_input = gr.Files(label="πΈ Upload Images", file_types=["image"], type="filepath", elem_id="image_input")
|
61 |
+
generate_button = gr.Button("β¨ Generate Banner", size="large", elem_id="generate_button")
|
62 |
+
|
63 |
+
# Right Column: Image Preview and Generated Banner
|
64 |
+
with gr.Column(scale=1, min_width=400, elem_id="interaction_section"):
|
65 |
+
image_preview = gr.Gallery(label="π Image Preview", elem_id="image_preview", show_label=False, height=300, preview=True)
|
66 |
+
generated_image = gr.Image(label="π¨ Generated Banner", type="filepath", interactive=False, elem_id="generated_image")
|
67 |
+
|
68 |
+
# Show uploaded images in the preview
|
69 |
+
image_input.change(
|
70 |
+
fn=preview_images,
|
71 |
+
inputs=image_input,
|
72 |
+
outputs=image_preview
|
73 |
+
)
|
74 |
+
|
75 |
+
# Button to Trigger Banner Generation and Display the Generated Image
|
76 |
+
generate_button.click(
|
77 |
+
fn=generate_banner,
|
78 |
+
inputs=[topic_input, image_input, aspect_ratio_dropdown],
|
79 |
+
outputs=generated_image
|
80 |
+
)
|
81 |
+
|
82 |
+
# Footer
|
83 |
+
gr.Markdown(
|
84 |
+
"""
|
85 |
+
<div style="text-align: center; margin-top: 20px;">
|
86 |
+
<p style="font-size: 1.25rem; color: #888;">Made with β€οΈ for creative designers</p>
|
87 |
+
<p style="font-size: 1rem; color: #888;">Powered by Google Gemini and Google Imagen</p>
|
88 |
+
</div>
|
89 |
+
""", elem_id="footer_text"
|
90 |
+
)
|
91 |
+
|
92 |
+
# Custom CSS for improving the UI layout
|
93 |
+
demo.css = """
|
94 |
+
#branding_section {
|
95 |
+
background-color: #f9f9f9;
|
96 |
+
padding: 20px;
|
97 |
+
border-radius: 15px;
|
98 |
+
}
|
99 |
+
#interaction_section {
|
100 |
+
padding: 20px;
|
101 |
+
background-color: #ffffff;
|
102 |
+
border-radius: 15px;
|
103 |
+
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
|
104 |
+
}
|
105 |
+
#generate_button {
|
106 |
+
width: 100%;
|
107 |
+
margin-bottom: 15px;
|
108 |
+
padding: 15px;
|
109 |
+
font-size: 1.2rem;
|
110 |
+
font-weight: bold;
|
111 |
+
background-color: #ff6347;
|
112 |
+
color: white;
|
113 |
+
border: none;
|
114 |
+
border-radius: 10px;
|
115 |
+
cursor: pointer;
|
116 |
+
}
|
117 |
+
#generate_button:hover {
|
118 |
+
background-color: #e5533d;
|
119 |
+
}
|
120 |
+
#generated_image, #image_preview {
|
121 |
+
width: 100%;
|
122 |
+
border: none;
|
123 |
+
border-radius: 0px;
|
124 |
+
object-fit: cover;
|
125 |
+
}
|
126 |
+
"""
|
127 |
+
|
128 |
+
# Launch the demo
|
129 |
+
demo.launch(share=True)
|
images/.DS_Store
ADDED
Binary file (8.2 kB). View file
|
|
images/logos/bigbasket_logo.png
ADDED
images/logos/gemini_logo.png
ADDED
images/logos/google_logo.png
ADDED
images/output/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
images/sample/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
images/sample/input_sample/biscuit_back.jpg
ADDED
images/sample/input_sample/biscuit_front.jpg
ADDED
images/sample/output_sample/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
images/sample/output_sample/dahi_durga puja_14344.png
ADDED
images/sample/output_sample/dahi_durga puja_58861.png
ADDED
Git LFS Details
|
images/sample/output_sample/doi dahi_durga puja_92098.png
ADDED
Git LFS Details
|
images/sample/output_sample/doi dahi_durga puja_93931.png
ADDED
Git LFS Details
|
images/sample/output_sample/pepsi and coca cola_durga puja_red, white, green, orange and blue_20 percent discount_7819.png
ADDED
Git LFS Details
|
images/temp/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
notebooks/.DS_Store
ADDED
Binary file (6.15 kB). View file
|
|
notebooks/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
|
notebooks/vg_2_0a_banner_generator.ipynb
ADDED
The diff for this file is too large to render.
See raw diff
|
|
requirements.txt
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
configparser==7.1.0
|
2 |
+
google-generativeai==0.8.1
|
3 |
+
vertexai==1.66.0
|
4 |
+
fastapi==0.115.0
|
5 |
+
gradio==4.44.0
|
6 |
+
uvicorn==0.31.0
|
7 |
+
google-cloud-aiplatform==1.66.0
|