Update app.py
Browse files
app.py
CHANGED
|
@@ -29,6 +29,14 @@ MODEL_NAME = os.getenv(
|
|
| 29 |
"hf-hub:imageomics/bioclip"
|
| 30 |
)
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
# Load BioCLIP Model from Hugging Face
|
| 33 |
logger.info("Loading model from Hugging Face...")
|
| 34 |
model, _, preprocess = create_model_and_transforms(MODEL_NAME)
|
|
@@ -38,13 +46,14 @@ model = model.to(device)
|
|
| 38 |
logger.info(f"Model loaded on device successfully: {device}")
|
| 39 |
|
| 40 |
# Gradio App Function
|
| 41 |
-
def app_function(uploaded_image: Optional[np.ndarray]) -> Tuple[str, Optional[str], Optional[str], str]:
|
| 42 |
"""Main function for the Gradio app.
|
| 43 |
|
| 44 |
Processes the uploaded image, performs semantic search, and returns a summary, species information, and HTML output.
|
| 45 |
|
| 46 |
Args:
|
| 47 |
uploaded_image (Optional[np.ndarray]): Uploaded image as a NumPy array.
|
|
|
|
| 48 |
|
| 49 |
Returns:
|
| 50 |
Tuple[str, Optional[str], Optional[str], str]: Summary, proposed scientific name, proposed common name, and HTML output.
|
|
@@ -53,6 +62,10 @@ def app_function(uploaded_image: Optional[np.ndarray]) -> Tuple[str, Optional[st
|
|
| 53 |
logger.error("app_function: No image uploaded.")
|
| 54 |
return "No image uploaded", None, None, ""
|
| 55 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
try:
|
| 57 |
image = Image.fromarray(uploaded_image)
|
| 58 |
except Exception as e:
|
|
@@ -67,7 +80,7 @@ def app_function(uploaded_image: Optional[np.ndarray]) -> Tuple[str, Optional[st
|
|
| 67 |
logger.exception("app_function: Error encoding image. Uploaded image shape: %s. Exception: %s", getattr(uploaded_image, 'shape', 'N/A'), e)
|
| 68 |
return f"Error encoding image: {e}", None, None, ""
|
| 69 |
|
| 70 |
-
payload = {"query_embedding": query_embedding, "country_code": "
|
| 71 |
headers = {"x-api-key": API_GATEWAY_API_KEY}
|
| 72 |
logger.info("app_function: Calling API Gateway with payload (embedding sample: %s...)", query_embedding[:5])
|
| 73 |
|
|
@@ -205,17 +218,22 @@ with gr.Blocks(title="Wildlife Semantic Search with BioCLIP") as demo:
|
|
| 205 |
with gr.Column(scale=30):
|
| 206 |
gr.Markdown(
|
| 207 |
"""
|
| 208 |
-
### Welcome to Ecologist –
|
| 209 |
|
| 210 |
-
**Ecologist** identifies wildlife species found in
|
| 211 |
|
| 212 |
-
Powered by multimodal image retrieval and visual encoding with [BioCLIP](https://huggingface.co/imageomics/bioclip), the system extracts features from the image and matches them against a specialized database of
|
| 213 |
|
| 214 |
-
Both scientific and common names are provided within seconds, along with visually similar images that offer context about
|
| 215 |
|
| 216 |
-
Ecologist is a step towards celebrating and preserving the
|
| 217 |
"""
|
| 218 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 219 |
|
| 220 |
# Row 2: Image Upload with a fixed display container.
|
| 221 |
with gr.Row(variant="panel"):
|
|
@@ -276,7 +294,7 @@ with gr.Blocks(title="Wildlife Semantic Search with BioCLIP") as demo:
|
|
| 276 |
gr.Markdown(
|
| 277 |
"""
|
| 278 |
**Disclaimer:**
|
| 279 |
-
|
| 280 |
|
| 281 |
**References:**
|
| 282 |
This project is inspired by the work on [Biome](https://huggingface.co/spaces/govtech/Biome) from GovTech Singapore.
|
|
@@ -287,15 +305,15 @@ with gr.Blocks(title="Wildlife Semantic Search with BioCLIP") as demo:
|
|
| 287 |
)
|
| 288 |
|
| 289 |
# Wrapping the function to only forward the necessary outputs.
|
| 290 |
-
def wrapper(uploaded_image):
|
| 291 |
-
summary, proposed_scientific, proposed_common, boxes_html = app_function(uploaded_image)
|
| 292 |
|
| 293 |
# Print the summary for debugging
|
| 294 |
# print(summary)
|
| 295 |
|
| 296 |
return proposed_scientific, proposed_common, boxes_html
|
| 297 |
|
| 298 |
-
submit_button.click(fn=wrapper, inputs=image_input, outputs=[proposed_scientific_output, proposed_common_output, html_output])
|
| 299 |
|
| 300 |
if __name__ == "__main__":
|
| 301 |
demo.launch()
|
|
|
|
| 29 |
"hf-hub:imageomics/bioclip"
|
| 30 |
)
|
| 31 |
|
| 32 |
+
# Load country code mappings from the JSON file
|
| 33 |
+
# Assumes the JSON file is located in the same directory as app.py.
|
| 34 |
+
logger.info("Loading country code mappings...")
|
| 35 |
+
country_codes_path = os.path.join(os.path.dirname(__file__), "country_codes.json")
|
| 36 |
+
with open(country_codes_path, "r") as f:
|
| 37 |
+
country_code_mappings = json.load(f)
|
| 38 |
+
logger.info("Country code mappings loaded successfully.")
|
| 39 |
+
|
| 40 |
# Load BioCLIP Model from Hugging Face
|
| 41 |
logger.info("Loading model from Hugging Face...")
|
| 42 |
model, _, preprocess = create_model_and_transforms(MODEL_NAME)
|
|
|
|
| 46 |
logger.info(f"Model loaded on device successfully: {device}")
|
| 47 |
|
| 48 |
# Gradio App Function
|
| 49 |
+
def app_function(uploaded_image: Optional[np.ndarray], country: Optional[str]) -> Tuple[str, Optional[str], Optional[str], str]:
|
| 50 |
"""Main function for the Gradio app.
|
| 51 |
|
| 52 |
Processes the uploaded image, performs semantic search, and returns a summary, species information, and HTML output.
|
| 53 |
|
| 54 |
Args:
|
| 55 |
uploaded_image (Optional[np.ndarray]): Uploaded image as a NumPy array.
|
| 56 |
+
country (Optional[str]): Country for filtering the search results.
|
| 57 |
|
| 58 |
Returns:
|
| 59 |
Tuple[str, Optional[str], Optional[str], str]: Summary, proposed scientific name, proposed common name, and HTML output.
|
|
|
|
| 62 |
logger.error("app_function: No image uploaded.")
|
| 63 |
return "No image uploaded", None, None, ""
|
| 64 |
|
| 65 |
+
if country is None:
|
| 66 |
+
logger.error("app_function: No country selected.")
|
| 67 |
+
return "No country selected", None, None, ""
|
| 68 |
+
|
| 69 |
try:
|
| 70 |
image = Image.fromarray(uploaded_image)
|
| 71 |
except Exception as e:
|
|
|
|
| 80 |
logger.exception("app_function: Error encoding image. Uploaded image shape: %s. Exception: %s", getattr(uploaded_image, 'shape', 'N/A'), e)
|
| 81 |
return f"Error encoding image: {e}", None, None, ""
|
| 82 |
|
| 83 |
+
payload = {"query_embedding": query_embedding, "country_code": country_code_mappings.get(country, "")}
|
| 84 |
headers = {"x-api-key": API_GATEWAY_API_KEY}
|
| 85 |
logger.info("app_function: Calling API Gateway with payload (embedding sample: %s...)", query_embedding[:5])
|
| 86 |
|
|
|
|
| 218 |
with gr.Column(scale=30):
|
| 219 |
gr.Markdown(
|
| 220 |
"""
|
| 221 |
+
### Welcome to Ecologist – an AI-powered biodiversity explorer!
|
| 222 |
|
| 223 |
+
**Ecologist** identifies wildlife species found in your selected country from an uploaded photo.
|
| 224 |
|
| 225 |
+
Powered by multimodal image retrieval and visual encoding with [BioCLIP](https://huggingface.co/imageomics/bioclip), the system extracts features from the image and matches them against a specialized database of the country's diverse flora and fauna.
|
| 226 |
|
| 227 |
+
Both scientific and common names are provided within seconds, along with visually similar images that offer context about the country's rich natural heritage.
|
| 228 |
|
| 229 |
+
Ecologist is a step towards celebrating and preserving the world’s unique wildlife through AI.
|
| 230 |
"""
|
| 231 |
)
|
| 232 |
+
country_dropdown = gr.Dropdown(
|
| 233 |
+
label="Select Country",
|
| 234 |
+
choices=["Singapore"],
|
| 235 |
+
value="Singapore"
|
| 236 |
+
)
|
| 237 |
|
| 238 |
# Row 2: Image Upload with a fixed display container.
|
| 239 |
with gr.Row(variant="panel"):
|
|
|
|
| 294 |
gr.Markdown(
|
| 295 |
"""
|
| 296 |
**Disclaimer:**
|
| 297 |
+
Intended for non-commercial use, no user data is stored or used for training purposes, and all retrieval data is sourced from [iNaturalist](https://inaturalist.org/). Results may vary depending on the input image.
|
| 298 |
|
| 299 |
**References:**
|
| 300 |
This project is inspired by the work on [Biome](https://huggingface.co/spaces/govtech/Biome) from GovTech Singapore.
|
|
|
|
| 305 |
)
|
| 306 |
|
| 307 |
# Wrapping the function to only forward the necessary outputs.
|
| 308 |
+
def wrapper(uploaded_image, country):
|
| 309 |
+
summary, proposed_scientific, proposed_common, boxes_html = app_function(uploaded_image, country)
|
| 310 |
|
| 311 |
# Print the summary for debugging
|
| 312 |
# print(summary)
|
| 313 |
|
| 314 |
return proposed_scientific, proposed_common, boxes_html
|
| 315 |
|
| 316 |
+
submit_button.click(fn=wrapper, inputs=[image_input, country_dropdown], outputs=[proposed_scientific_output, proposed_common_output, html_output])
|
| 317 |
|
| 318 |
if __name__ == "__main__":
|
| 319 |
demo.launch()
|