anilkumar5590 commited on
Commit
16c1e88
·
verified ·
1 Parent(s): ed11bd5

Update backendapi.py

Browse files
Files changed (1) hide show
  1. backendapi.py +284 -56
backendapi.py CHANGED
@@ -1,8 +1,215 @@
1
 
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  import os
4
  from flask import Flask, request, jsonify
5
- from flask_cors import CORS # Import CORS for cross-origin access
6
  import tensorflow as tf
7
  from tensorflow.keras.preprocessing import image
8
  import numpy as np
@@ -10,10 +217,11 @@ import io
10
  from PIL import Image
11
  import time
12
  import traceback
13
- import google.generativeai as genai # Google Gemini AI
14
  import re
15
  from huggingface_hub import hf_hub_download
16
  from dotenv import load_dotenv
 
17
  # Create Flask app
18
  app = Flask(__name__)
19
 
@@ -21,9 +229,10 @@ app = Flask(__name__)
21
  CORS(app)
22
 
23
  load_dotenv()
 
24
  # Configure Google Gemini AI
25
- genai.configure(api_key=os.environ.get("gemini_api", "")) # Replace with your actual API key
26
- model_gemini = genai.GenerativeModel("gemini-1.5-flash") # Use a fast Gemini AI model
27
 
28
  # In-memory store to simulate prediction processing
29
  prediction_results = {}
@@ -31,10 +240,10 @@ prediction_results = {}
31
  # Define preprocessing function for the uploaded image
32
  def preprocess_image(img):
33
  try:
34
- img = img.resize((224, 224)) # Resize image to match model input size
35
  img_array = np.array(img)
36
- img_array = np.expand_dims(img_array, axis=0) # Add batch dimension
37
- img_array = tf.keras.applications.efficientnet.preprocess_input(img_array) # Preprocess for EfficientNet
38
  return img_array
39
  except Exception as e:
40
  print(f"Error during image preprocessing: {e}")
@@ -42,9 +251,8 @@ def preprocess_image(img):
42
 
43
  # Clean Gemini AI explanation
44
  def clean_explanation(text):
45
- """Remove unnecessary formatting such as * and excess whitespace."""
46
- text = re.sub(r'\*+', '', text) # Remove asterisks
47
- text = re.sub(r'\s+', ' ', text).strip() # Normalize spaces
48
  return text
49
 
50
  # Generate explanation using Gemini AI
@@ -53,22 +261,13 @@ def generate_explanation(predicted_class):
53
  prompt = f"Get instant feedback with the predicted animal name {predicted_class} along with relevant details like its habitat, diet. Provide a brief yet informative explanation, including unique characteristics, scientific name, and any interesting facts. Keep the response engaging and easy to understand for general users. Avoid technical jargon, but ensure accuracy. Limit the response to 5-6 sentences."
54
  response = model_gemini.generate_content(prompt)
55
  raw_text = response.text.strip() if response and response.text else f"This is a {predicted_class}."
56
- return clean_explanation(raw_text) # Clean the AI-generated text
57
  except Exception as e:
58
  print(f"Error generating explanation: {e}")
59
  return f"This is a {predicted_class}."
60
 
61
  # Get conservation status
62
  def get_conservation_status(class_name):
63
- """
64
- Extracts and returns the conservation status from the given class name.
65
-
66
- Args:
67
- class_name (str): The predicted class name, e.g., 'Axolotl-CR', 'African Elephant-EN'.
68
-
69
- Returns:
70
- str: The full conservation status description.
71
- """
72
  status_map = {
73
  "EX": "Extinct (EX) - No known individuals remaining.",
74
  "EW": "Extinct in the Wild (EW) - Survives only in captivity.",
@@ -80,26 +279,22 @@ def get_conservation_status(class_name):
80
  "DD": "Data Deficient (DD) - Not enough information to assess the risk.",
81
  "NE": "Not Evaluated (NE) - Has not yet been assessed."
82
  }
83
-
84
- # Extract the conservation status from the class name
85
  parts = class_name.split('-')
86
  if len(parts) > 1:
87
- status_abbr = parts[-1] # The last part should be the conservation status
88
  return status_map.get(status_abbr, "Unknown conservation status")
89
-
90
  return "Unknown conservation status"
91
 
92
  # Load model from Hugging Face Hub
93
  def load_model_from_huggingface():
94
- cache_dir = "/tmp/huggingface" # Define a writable cache directory
95
- os.makedirs(cache_dir, exist_ok=True) # Ensure it exists
96
-
97
  print("Downloading model from Hugging Face Hub...")
98
  try:
99
  model_path = hf_hub_download(
100
  repo_id="anilkumar5590/image-classification-viit",
101
- filename="model.keras", # Adjust the filename based on your model
102
- cache_dir=cache_dir # Use the custom directory
103
  )
104
  print(f"Model downloaded successfully at: {model_path}")
105
  model = tf.keras.models.load_model(model_path)
@@ -112,17 +307,11 @@ def load_model_from_huggingface():
112
  # Load model at startup
113
  model = load_model_from_huggingface()
114
 
115
-
116
-
117
-
118
  # Home Route
119
  @app.route('/')
120
  def home():
121
  return "Welcome to the Wild Life Image Classification Project!"
122
 
123
-
124
- prediction_results = {}
125
-
126
  # Define route for predictions (POST)
127
  @app.route("/predict", methods=["POST"])
128
  def predict():
@@ -150,38 +339,76 @@ def predict():
150
  predicted_class_index = np.argmax(predictions, axis=1)[0]
151
  confidence_level = round(np.max(predictions) * 100, 2)
152
 
153
- # Define labels (replace with your model's labels)
154
- # labels = {
155
- # 0: 'Aardvark-LC', 1: 'African Elephant-EN', 2: 'Alligator-LC', 3: 'Alpaca-LC', 4: 'Anaconda-LC',
156
- # # Add the rest of your labels here...
157
- # }
158
- labels = {0: 'Aardvark-LC', 1: 'African Elephant-EN', 2: 'Alligator-LC', 3: 'Alpaca-LC', 4: 'Anaconda-LC', 5: 'Arctic Fox-VU', 6: 'Armadillo-LC', 7: 'Axolotl-CR', 8: 'Baboon-LC', 9: 'Badger-LC', 10: 'Bald Eagle-LC', 11: 'Barracuda-LC', 12: 'Bat-LC', 13: 'Bison-NT', 14: 'Black Bear-LC', 15: 'Blue Jay-LC', 16: 'Boa Constrictor-LC', 17: 'Bonobo-EN', 18: 'Buffalo-LC', 19: 'Butterfly-LC', 20: 'Caiman-LC', 21: 'Camel-LC', 22: 'Capybara-LC', 23: 'Caracal-LC', 24: 'Cheetah-VU', 25: 'Chimpanzee-EN', 26: 'Cobra-LC', 27: 'Cockatoo-LC', 28: 'Coral-CR', 29: 'Coyote-LC', 30: 'Crocodile-LC', 31: 'Deer-LC', 32: 'Dingo-LC', 33: 'Dodo-EX', 34: 'Dolphin-LC', 35: 'Domestic Cat-LC', 36: 'Donkey-LC', 37: 'Dragonfly-LC', 38: 'Duck-LC', 39: 'Dugong-VU', 40: 'Eagle-LC', 41: 'Earthworm-LC', 42: 'Echidna-LC', 43: 'Eel-LC', 44: 'Elephant-EN', 45: 'Elk-LC', 46: 'Emu-LC', 47: 'Falcon-LC', 48: 'Ferret-EN', 49: 'Finch-LC', 50: 'Firefly-LC', 51: 'Fish-LC', 52: 'Flamingo-LC', 53: 'Fossa-VU', 54: 'Fox-LC', 55: 'Frog-LC', 56: 'Galápagos Tortoise-VU', 57: 'Gazelle-VU', 58: 'Gecko-LC', 59: 'Gibbon-EN', 60: 'Giraffe-VU', 61: 'Goat-LC', 62: 'Goose-LC', 63: 'Gorilla-CR', 64: 'Grasshopper-LC', 65: 'Great White Shark-VU', 66: 'Green Anaconda-LC', 67: 'Grizzly Bear-LC', 68: 'Hammerhead Shark-CR', 69: 'Hamster-LC', 70: 'Hare-LC', 71: 'Hawk-LC', 72: 'Hedgehog-LC', 73: 'Hermit Crab-LC', 74: 'Hippopotamus-VU', 75: 'Honeybee-LC', 76: 'Hornbill-NT', 77: 'Horse-LC', 78: 'Hummingbird-LC', 79: 'Ibex-LC', 80: 'Ibis-LC', 81: 'Indian Cobra-LC', 82: 'Indian Elephant-EN', 83: 'Indian Star Tortoise-VU', 84: 'Indian Wolf-EN', 85: 'Jackal-LC', 86: 'Jaguar-NT', 87: 'Japanese Beetle-LC', 88: 'Jellyfish-LC', 89: 'Kangaroo-LC', 90: 'King Cobra-VU', 91: 'Kingfisher-LC', 92: 'Kiwi-EN', 93: 'Koala-VU', 94: 'Komodo Dragon-EN', 95: 'Ladybug-LC', 96: 'Lemming-LC', 97: 'Lemur-CR', 98: 'Leopard-VU', 99: 'Lion-VU', 100: 'Lizard-LC', 101: 'Llama-LC', 102: 'Lobster-LC', 103: 'Lynx-LC', 104: 'Macaw-EN', 105: 'Magpie-LC', 106: 'Manatee-VU', 107: 'Mandrill-VU', 108: 'Mantis Shrimp-LC', 109: 'Meerkat-LC', 110: 'Mole-LC', 111: 'Moose-LC', 112: 'Moray Eel-LC', 113: 'Mountain Lion-LC', 114: 'Musk Ox-LC', 115: 'Nandu Rhea-LC', 116: 'Narwhal-NT', 117: 'Newt-LC', 118: 'Nightingale-LC', 119: 'Octopus-LC', 120: 'Okapi-EN', 121: 'Opossum-LC', 122: 'Orangutan-CR', 123: 'Ostrich-LC', 124: 'Otter-VU', 125: 'Owl-LC', 126: 'Ox-LC', 127: 'Panda-VU', 128: 'Panther-NT', 129: 'Parrot-LC', 130: 'Peacock-LC', 131: 'Pelican-LC', 132: 'Penguin-NT', 133: 'Pigeon-LC', 134: 'Piranha-LC', 135: 'Platypus-LC', 136: 'Polar Bear-VU', 137: 'Porcupine-LC', 138: 'Possum-LC', 139: 'Praying Mantis-LC', 140: 'Puffin-LC', 141: 'Python-LC', 142: 'Quail-LC', 143: 'Quetzal-NT', 144: 'Quokka-LC', 145: 'Quoll-NT', 146: 'Rabbit-LC', 147: 'Raccoon-LC', 148: 'Ram-LC', 149: 'Rat-LC', 150: 'Raven-LC', 151: 'Red Panda-EN', 152: 'Reindeer-VU', 153: 'Rhinoceros-CR', 154: 'Roadrunner-LC', 155: 'Salamander-LC', 156: 'Scorpion-LC', 157: 'Sea Lion-LC', 158: 'Seahorse-LC', 159: 'Shark-VU', 160: 'Sheep-LC', 161: 'Skunk-LC', 162: 'Sloth-VU', 163: 'Snail-LC', 164: 'Snake-LC', 165: 'Snow Leopard-VU', 166: 'Sparrow-LC', 167: 'Spider-LC', 168: 'Squirrel-LC', 169: 'Starfish-LC', 170: 'Stork-LC', 171: 'Swan-LC', 172: 'Tamarin-EN', 173: 'Tapir-VU', 174: 'Tasmanian Devil-EN', 175: 'Termite-LC', 176: 'Thorny Devil-LC', 177: 'Tiger-EN', 178: 'Toad-LC', 179: 'Toucan-LC', 180: 'Tuna-LC', 181: 'Turkey-LC', 182: 'Turtle-VU', 183: 'Uakari-VU', 184: 'Umbrellabird-VU', 185: 'Urchin-LC', 186: 'Uromastyx-LC', 187: 'Vampire Bat-LC', 188: 'Vaquita-CR', 189: 'Vervet Monkey-LC', 190: 'Vulture-LC', 191: 'Wallaby-LC', 192: 'Walrus-VU', 193: 'Warthog-LC', 194: 'Weasel-LC', 195: 'Whale-EN', 196: 'White Tiger-EN', 197: 'Wild Cat-VU', 198: 'Wolf-VU', 199: 'Wolverine-LC', 200: 'Wombat-LC', 201: 'Woodpecker-LC', 202: 'X-ray Tetra-LC', 203: 'Xenopus-LC', 204: 'Yak-LC', 205: 'Yellowjacket-LC', 206: 'Zebra Finch-LC', 207: 'Zebra-NT', 208: 'Zebu-LC', 209: 'Zorilla-LC'}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
  predicted_class = labels.get(predicted_class_index, "Unknown")
161
  conservation_status = get_conservation_status(predicted_class)
162
- predicted_class = predicted_class.split('-')[0] # Remove the conservation status from the class name
163
- print(f"Prediction: {predicted_class}, Confidence: {confidence_level}%")
164
 
165
  # Generate explanation using Gemini AI
166
- explanation = generate_explanation(predicted_class)
167
-
168
- prediction_id = str(time.time()) # Unique ID for the request
169
- if confidence_level<=30:
170
- prediction_results[prediction_id] = {
171
- "predicted_class": "---",
172
- "conservation_status": "---",
173
- "confidence_level": "---",
174
- "explanation": "Sorry! This image doesn’t seem to match any animals I was trained on. I’m doing my best with the knowledge I have. Please try a different image – ideally of a single, clear animal."
175
- }
176
- else:
177
  # Store the result in the in-memory dictionary
 
 
 
 
 
 
 
178
  prediction_results[prediction_id] = {
179
- "predicted_class": predicted_class,
180
  "conservation_status": conservation_status,
181
  "confidence_level": confidence_level,
182
  "explanation": explanation
183
  }
184
- print(f"Prediction ID: {prediction_id}, Result: {prediction_results[prediction_id]}")
185
  return jsonify({"prediction_id": prediction_id}), 200
186
 
187
  except Exception as e:
@@ -195,6 +422,7 @@ def get_prediction(prediction_id):
195
  print(f"Fetching prediction result for ID: {prediction_id}")
196
  result = prediction_results.get(prediction_id)
197
  if result:
 
198
  return jsonify(result)
199
  else:
200
  print(f"No result found for ID: {prediction_id}")
 
1
 
2
 
3
+ # import os
4
+ # from flask import Flask, request, jsonify
5
+ # from flask_cors import CORS # Import CORS for cross-origin access
6
+ # import tensorflow as tf
7
+ # from tensorflow.keras.preprocessing import image
8
+ # import numpy as np
9
+ # import io
10
+ # from PIL import Image
11
+ # import time
12
+ # import traceback
13
+ # import google.generativeai as genai # Google Gemini AI
14
+ # import re
15
+ # from huggingface_hub import hf_hub_download
16
+ # from dotenv import load_dotenv
17
+ # # Create Flask app
18
+ # app = Flask(__name__)
19
+
20
+ # # Enable CORS for all routes
21
+ # CORS(app)
22
+
23
+ # load_dotenv()
24
+ # # Configure Google Gemini AI
25
+ # genai.configure(api_key=os.environ.get("gemini_api", "")) # Replace with your actual API key
26
+ # model_gemini = genai.GenerativeModel("gemini-1.5-flash") # Use a fast Gemini AI model
27
+
28
+ # # In-memory store to simulate prediction processing
29
+ # prediction_results = {}
30
+
31
+ # # Define preprocessing function for the uploaded image
32
+ # def preprocess_image(img):
33
+ # try:
34
+ # img = img.resize((224, 224)) # Resize image to match model input size
35
+ # img_array = np.array(img)
36
+ # img_array = np.expand_dims(img_array, axis=0) # Add batch dimension
37
+ # img_array = tf.keras.applications.efficientnet.preprocess_input(img_array) # Preprocess for EfficientNet
38
+ # return img_array
39
+ # except Exception as e:
40
+ # print(f"Error during image preprocessing: {e}")
41
+ # raise
42
+
43
+ # # Clean Gemini AI explanation
44
+ # def clean_explanation(text):
45
+ # """Remove unnecessary formatting such as * and excess whitespace."""
46
+ # text = re.sub(r'\*+', '', text) # Remove asterisks
47
+ # text = re.sub(r'\s+', ' ', text).strip() # Normalize spaces
48
+ # return text
49
+
50
+ # # Generate explanation using Gemini AI
51
+ # def generate_explanation(predicted_class):
52
+ # try:
53
+ # prompt = f"Get instant feedback with the predicted animal name {predicted_class} along with relevant details like its habitat, diet. Provide a brief yet informative explanation, including unique characteristics, scientific name, and any interesting facts. Keep the response engaging and easy to understand for general users. Avoid technical jargon, but ensure accuracy. Limit the response to 5-6 sentences."
54
+ # response = model_gemini.generate_content(prompt)
55
+ # raw_text = response.text.strip() if response and response.text else f"This is a {predicted_class}."
56
+ # return clean_explanation(raw_text) # Clean the AI-generated text
57
+ # except Exception as e:
58
+ # print(f"Error generating explanation: {e}")
59
+ # return f"This is a {predicted_class}."
60
+
61
+ # # Get conservation status
62
+ # def get_conservation_status(class_name):
63
+ # """
64
+ # Extracts and returns the conservation status from the given class name.
65
+
66
+ # Args:
67
+ # class_name (str): The predicted class name, e.g., 'Axolotl-CR', 'African Elephant-EN'.
68
+
69
+ # Returns:
70
+ # str: The full conservation status description.
71
+ # """
72
+ # status_map = {
73
+ # "EX": "Extinct (EX) - No known individuals remaining.",
74
+ # "EW": "Extinct in the Wild (EW) - Survives only in captivity.",
75
+ # "CR": "Critically Endangered (CR) - Faces an extremely high risk of extinction.",
76
+ # "EN": "Endangered (EN) - High risk of extinction in the wild.",
77
+ # "VU": "Vulnerable (VU) - At risk of becoming endangered.",
78
+ # "NT": "Near Threatened (NT) - Likely to become endangered in the future.",
79
+ # "LC": "Least Concern (LC) - Lowest risk of extinction.",
80
+ # "DD": "Data Deficient (DD) - Not enough information to assess the risk.",
81
+ # "NE": "Not Evaluated (NE) - Has not yet been assessed."
82
+ # }
83
+
84
+ # # Extract the conservation status from the class name
85
+ # parts = class_name.split('-')
86
+ # if len(parts) > 1:
87
+ # status_abbr = parts[-1] # The last part should be the conservation status
88
+ # return status_map.get(status_abbr, "Unknown conservation status")
89
+
90
+ # return "Unknown conservation status"
91
+
92
+ # # Load model from Hugging Face Hub
93
+ # def load_model_from_huggingface():
94
+ # cache_dir = "/tmp/huggingface" # Define a writable cache directory
95
+ # os.makedirs(cache_dir, exist_ok=True) # Ensure it exists
96
+
97
+ # print("Downloading model from Hugging Face Hub...")
98
+ # try:
99
+ # model_path = hf_hub_download(
100
+ # repo_id="anilkumar5590/image-classification-viit",
101
+ # filename="model.keras", # Adjust the filename based on your model
102
+ # cache_dir=cache_dir # Use the custom directory
103
+ # )
104
+ # print(f"Model downloaded successfully at: {model_path}")
105
+ # model = tf.keras.models.load_model(model_path)
106
+ # print("Model loaded successfully!")
107
+ # return model
108
+ # except Exception as e:
109
+ # print(f"Error loading model: {e}")
110
+ # raise
111
+
112
+ # # Load model at startup
113
+ # model = load_model_from_huggingface()
114
+
115
+
116
+
117
+
118
+ # # Home Route
119
+ # @app.route('/')
120
+ # def home():
121
+ # return "Welcome to the Wild Life Image Classification Project!"
122
+
123
+
124
+ # prediction_results = {}
125
+
126
+ # # Define route for predictions (POST)
127
+ # @app.route("/predict", methods=["POST"])
128
+ # def predict():
129
+ # print("Request Files:", request.files)
130
+ # file = request.files.get('file')
131
+
132
+ # if not file:
133
+ # print("No file part in the request")
134
+ # return jsonify({"error": "No file part"}), 400
135
+
136
+ # try:
137
+ # # Open and preprocess the image
138
+ # print("Opening image...")
139
+ # img = Image.open(io.BytesIO(file.read()))
140
+ # print(f"Received image: {img.size}")
141
+ # img_array = preprocess_image(img)
142
+ # print("Image preprocessed successfully")
143
+
144
+ # # Make prediction
145
+ # print("Making prediction...")
146
+ # predictions = model.predict(img_array)
147
+ # print("Prediction completed")
148
+
149
+ # # Process prediction results
150
+ # predicted_class_index = np.argmax(predictions, axis=1)[0]
151
+ # confidence_level = round(np.max(predictions) * 100, 2)
152
+
153
+ # # Define labels (replace with your model's labels)
154
+ # # labels = {
155
+ # # 0: 'Aardvark-LC', 1: 'African Elephant-EN', 2: 'Alligator-LC', 3: 'Alpaca-LC', 4: 'Anaconda-LC',
156
+ # # # Add the rest of your labels here...
157
+ # # }
158
+ # labels = {0: 'Aardvark-LC', 1: 'African Elephant-EN', 2: 'Alligator-LC', 3: 'Alpaca-LC', 4: 'Anaconda-LC', 5: 'Arctic Fox-VU', 6: 'Armadillo-LC', 7: 'Axolotl-CR', 8: 'Baboon-LC', 9: 'Badger-LC', 10: 'Bald Eagle-LC', 11: 'Barracuda-LC', 12: 'Bat-LC', 13: 'Bison-NT', 14: 'Black Bear-LC', 15: 'Blue Jay-LC', 16: 'Boa Constrictor-LC', 17: 'Bonobo-EN', 18: 'Buffalo-LC', 19: 'Butterfly-LC', 20: 'Caiman-LC', 21: 'Camel-LC', 22: 'Capybara-LC', 23: 'Caracal-LC', 24: 'Cheetah-VU', 25: 'Chimpanzee-EN', 26: 'Cobra-LC', 27: 'Cockatoo-LC', 28: 'Coral-CR', 29: 'Coyote-LC', 30: 'Crocodile-LC', 31: 'Deer-LC', 32: 'Dingo-LC', 33: 'Dodo-EX', 34: 'Dolphin-LC', 35: 'Domestic Cat-LC', 36: 'Donkey-LC', 37: 'Dragonfly-LC', 38: 'Duck-LC', 39: 'Dugong-VU', 40: 'Eagle-LC', 41: 'Earthworm-LC', 42: 'Echidna-LC', 43: 'Eel-LC', 44: 'Elephant-EN', 45: 'Elk-LC', 46: 'Emu-LC', 47: 'Falcon-LC', 48: 'Ferret-EN', 49: 'Finch-LC', 50: 'Firefly-LC', 51: 'Fish-LC', 52: 'Flamingo-LC', 53: 'Fossa-VU', 54: 'Fox-LC', 55: 'Frog-LC', 56: 'Galápagos Tortoise-VU', 57: 'Gazelle-VU', 58: 'Gecko-LC', 59: 'Gibbon-EN', 60: 'Giraffe-VU', 61: 'Goat-LC', 62: 'Goose-LC', 63: 'Gorilla-CR', 64: 'Grasshopper-LC', 65: 'Great White Shark-VU', 66: 'Green Anaconda-LC', 67: 'Grizzly Bear-LC', 68: 'Hammerhead Shark-CR', 69: 'Hamster-LC', 70: 'Hare-LC', 71: 'Hawk-LC', 72: 'Hedgehog-LC', 73: 'Hermit Crab-LC', 74: 'Hippopotamus-VU', 75: 'Honeybee-LC', 76: 'Hornbill-NT', 77: 'Horse-LC', 78: 'Hummingbird-LC', 79: 'Ibex-LC', 80: 'Ibis-LC', 81: 'Indian Cobra-LC', 82: 'Indian Elephant-EN', 83: 'Indian Star Tortoise-VU', 84: 'Indian Wolf-EN', 85: 'Jackal-LC', 86: 'Jaguar-NT', 87: 'Japanese Beetle-LC', 88: 'Jellyfish-LC', 89: 'Kangaroo-LC', 90: 'King Cobra-VU', 91: 'Kingfisher-LC', 92: 'Kiwi-EN', 93: 'Koala-VU', 94: 'Komodo Dragon-EN', 95: 'Ladybug-LC', 96: 'Lemming-LC', 97: 'Lemur-CR', 98: 'Leopard-VU', 99: 'Lion-VU', 100: 'Lizard-LC', 101: 'Llama-LC', 102: 'Lobster-LC', 103: 'Lynx-LC', 104: 'Macaw-EN', 105: 'Magpie-LC', 106: 'Manatee-VU', 107: 'Mandrill-VU', 108: 'Mantis Shrimp-LC', 109: 'Meerkat-LC', 110: 'Mole-LC', 111: 'Moose-LC', 112: 'Moray Eel-LC', 113: 'Mountain Lion-LC', 114: 'Musk Ox-LC', 115: 'Nandu Rhea-LC', 116: 'Narwhal-NT', 117: 'Newt-LC', 118: 'Nightingale-LC', 119: 'Octopus-LC', 120: 'Okapi-EN', 121: 'Opossum-LC', 122: 'Orangutan-CR', 123: 'Ostrich-LC', 124: 'Otter-VU', 125: 'Owl-LC', 126: 'Ox-LC', 127: 'Panda-VU', 128: 'Panther-NT', 129: 'Parrot-LC', 130: 'Peacock-LC', 131: 'Pelican-LC', 132: 'Penguin-NT', 133: 'Pigeon-LC', 134: 'Piranha-LC', 135: 'Platypus-LC', 136: 'Polar Bear-VU', 137: 'Porcupine-LC', 138: 'Possum-LC', 139: 'Praying Mantis-LC', 140: 'Puffin-LC', 141: 'Python-LC', 142: 'Quail-LC', 143: 'Quetzal-NT', 144: 'Quokka-LC', 145: 'Quoll-NT', 146: 'Rabbit-LC', 147: 'Raccoon-LC', 148: 'Ram-LC', 149: 'Rat-LC', 150: 'Raven-LC', 151: 'Red Panda-EN', 152: 'Reindeer-VU', 153: 'Rhinoceros-CR', 154: 'Roadrunner-LC', 155: 'Salamander-LC', 156: 'Scorpion-LC', 157: 'Sea Lion-LC', 158: 'Seahorse-LC', 159: 'Shark-VU', 160: 'Sheep-LC', 161: 'Skunk-LC', 162: 'Sloth-VU', 163: 'Snail-LC', 164: 'Snake-LC', 165: 'Snow Leopard-VU', 166: 'Sparrow-LC', 167: 'Spider-LC', 168: 'Squirrel-LC', 169: 'Starfish-LC', 170: 'Stork-LC', 171: 'Swan-LC', 172: 'Tamarin-EN', 173: 'Tapir-VU', 174: 'Tasmanian Devil-EN', 175: 'Termite-LC', 176: 'Thorny Devil-LC', 177: 'Tiger-EN', 178: 'Toad-LC', 179: 'Toucan-LC', 180: 'Tuna-LC', 181: 'Turkey-LC', 182: 'Turtle-VU', 183: 'Uakari-VU', 184: 'Umbrellabird-VU', 185: 'Urchin-LC', 186: 'Uromastyx-LC', 187: 'Vampire Bat-LC', 188: 'Vaquita-CR', 189: 'Vervet Monkey-LC', 190: 'Vulture-LC', 191: 'Wallaby-LC', 192: 'Walrus-VU', 193: 'Warthog-LC', 194: 'Weasel-LC', 195: 'Whale-EN', 196: 'White Tiger-EN', 197: 'Wild Cat-VU', 198: 'Wolf-VU', 199: 'Wolverine-LC', 200: 'Wombat-LC', 201: 'Woodpecker-LC', 202: 'X-ray Tetra-LC', 203: 'Xenopus-LC', 204: 'Yak-LC', 205: 'Yellowjacket-LC', 206: 'Zebra Finch-LC', 207: 'Zebra-NT', 208: 'Zebu-LC', 209: 'Zorilla-LC'}
159
+
160
+ # predicted_class = labels.get(predicted_class_index, "Unknown")
161
+ # conservation_status = get_conservation_status(predicted_class)
162
+ # predicted_class = predicted_class.split('-')[0] # Remove the conservation status from the class name
163
+ # print(f"Prediction: {predicted_class}, Confidence: {confidence_level}%")
164
+
165
+ # # Generate explanation using Gemini AI
166
+ # explanation = generate_explanation(predicted_class)
167
+
168
+ # prediction_id = str(time.time()) # Unique ID for the request
169
+ # if confidence_level<=30:
170
+ # prediction_results[prediction_id] = {
171
+ # "predicted_class": "---",
172
+ # "conservation_status": "---",
173
+ # "confidence_level": "---",
174
+ # "explanation": "Sorry! This image doesn’t seem to match any animals I was trained on. I’m doing my best with the knowledge I have. Please try a different image – ideally of a single, clear animal."
175
+ # }
176
+ # else:
177
+ # # Store the result in the in-memory dictionary
178
+ # prediction_results[prediction_id] = {
179
+ # "predicted_class": predicted_class,
180
+ # "conservation_status": conservation_status,
181
+ # "confidence_level": confidence_level,
182
+ # "explanation": explanation
183
+ # }
184
+ # print(f"Prediction ID: {prediction_id}, Result: {prediction_results[prediction_id]}")
185
+ # return jsonify({"prediction_id": prediction_id}), 200
186
+
187
+ # except Exception as e:
188
+ # print(f"Error during prediction: {e}")
189
+ # print(traceback.format_exc())
190
+ # return jsonify({"error": f"Error during prediction: {e}"}), 500
191
+
192
+ # # Define route for retrieving predictions (GET)
193
+ # @app.route("/get_prediction/<prediction_id>", methods=["GET"])
194
+ # def get_prediction(prediction_id):
195
+ # print(f"Fetching prediction result for ID: {prediction_id}")
196
+ # result = prediction_results.get(prediction_id)
197
+ # if result:
198
+ # return jsonify(result)
199
+ # else:
200
+ # print(f"No result found for ID: {prediction_id}")
201
+ # return jsonify({"error": "Prediction not found or still processing"}), 404
202
+
203
+ # # Run the Flask app
204
+ # if __name__ == "__main__":
205
+ # app.run(host='0.0.0.0', port=7860, debug=True)
206
+
207
+
208
+
209
+
210
  import os
211
  from flask import Flask, request, jsonify
212
+ from flask_cors import CORS
213
  import tensorflow as tf
214
  from tensorflow.keras.preprocessing import image
215
  import numpy as np
 
217
  from PIL import Image
218
  import time
219
  import traceback
220
+ import google.generativeai as genai
221
  import re
222
  from huggingface_hub import hf_hub_download
223
  from dotenv import load_dotenv
224
+
225
  # Create Flask app
226
  app = Flask(__name__)
227
 
 
229
  CORS(app)
230
 
231
  load_dotenv()
232
+
233
  # Configure Google Gemini AI
234
+ genai.configure(api_key=os.environ.get("gemini_api", ""))
235
+ model_gemini = genai.GenerativeModel("gemini-1.5-flash")
236
 
237
  # In-memory store to simulate prediction processing
238
  prediction_results = {}
 
240
  # Define preprocessing function for the uploaded image
241
  def preprocess_image(img):
242
  try:
243
+ img = img.resize((224, 224))
244
  img_array = np.array(img)
245
+ img_array = np.expand_dims(img_array, axis=0)
246
+ img_array = tf.keras.applications.efficientnet.preprocess_input(img_array)
247
  return img_array
248
  except Exception as e:
249
  print(f"Error during image preprocessing: {e}")
 
251
 
252
  # Clean Gemini AI explanation
253
  def clean_explanation(text):
254
+ text = re.sub(r'\*+', '', text)
255
+ text = re.sub(r'\s+', ' ', text).strip()
 
256
  return text
257
 
258
  # Generate explanation using Gemini AI
 
261
  prompt = f"Get instant feedback with the predicted animal name {predicted_class} along with relevant details like its habitat, diet. Provide a brief yet informative explanation, including unique characteristics, scientific name, and any interesting facts. Keep the response engaging and easy to understand for general users. Avoid technical jargon, but ensure accuracy. Limit the response to 5-6 sentences."
262
  response = model_gemini.generate_content(prompt)
263
  raw_text = response.text.strip() if response and response.text else f"This is a {predicted_class}."
264
+ return clean_explanation(raw_text)
265
  except Exception as e:
266
  print(f"Error generating explanation: {e}")
267
  return f"This is a {predicted_class}."
268
 
269
  # Get conservation status
270
  def get_conservation_status(class_name):
 
 
 
 
 
 
 
 
 
271
  status_map = {
272
  "EX": "Extinct (EX) - No known individuals remaining.",
273
  "EW": "Extinct in the Wild (EW) - Survives only in captivity.",
 
279
  "DD": "Data Deficient (DD) - Not enough information to assess the risk.",
280
  "NE": "Not Evaluated (NE) - Has not yet been assessed."
281
  }
 
 
282
  parts = class_name.split('-')
283
  if len(parts) > 1:
284
+ status_abbr = parts[-1]
285
  return status_map.get(status_abbr, "Unknown conservation status")
 
286
  return "Unknown conservation status"
287
 
288
  # Load model from Hugging Face Hub
289
  def load_model_from_huggingface():
290
+ cache_dir = "/tmp/huggingface"
291
+ os.makedirs(cache_dir, exist_ok=True)
 
292
  print("Downloading model from Hugging Face Hub...")
293
  try:
294
  model_path = hf_hub_download(
295
  repo_id="anilkumar5590/image-classification-viit",
296
+ filename="model.keras",
297
+ cache_dir=cache_dir
298
  )
299
  print(f"Model downloaded successfully at: {model_path}")
300
  model = tf.keras.models.load_model(model_path)
 
307
  # Load model at startup
308
  model = load_model_from_huggingface()
309
 
 
 
 
310
  # Home Route
311
  @app.route('/')
312
  def home():
313
  return "Welcome to the Wild Life Image Classification Project!"
314
 
 
 
 
315
  # Define route for predictions (POST)
316
  @app.route("/predict", methods=["POST"])
317
  def predict():
 
339
  predicted_class_index = np.argmax(predictions, axis=1)[0]
340
  confidence_level = round(np.max(predictions) * 100, 2)
341
 
342
+ # Define labels
343
+ labels = {
344
+ 0: 'Aardvark-LC', 1: 'African Elephant-EN', 2: 'Alligator-LC', 3: 'Alpaca-LC', 4: 'Anaconda-LC',
345
+ 5: 'Arctic Fox-VU', 6: 'Armadillo-LC', 7: 'Axolotl-CR', 8: 'Baboon-LC', 9: 'Badger-LC',
346
+ 10: 'Bald Eagle-LC', 11: 'Barracuda-LC', 12: 'Bat-LC', 13: 'Bison-NT', 14: 'Black Bear-LC',
347
+ 15: 'Blue Jay-LC', 16: 'Boa Constrictor-LC', 17: 'Bonobo-EN', 18: 'Buffalo-LC', 19: 'Butterfly-LC',
348
+ 20: 'Caiman-LC', 21: 'Camel-LC', 22: 'Capybara-LC', 23: 'Caracal-LC', 24: 'Cheetah-VU',
349
+ 25: 'Chimpanzee-EN', 26: 'Cobra-LC', 27: 'Cockatoo-LC', 28: 'Coral-CR', 29: 'Coyote-LC',
350
+ 30: 'Crocodile-LC', 31: 'Deer-LC', 32: 'Dingo-LC', 33: 'Dodo-EX', 34: 'Dolphin-LC',
351
+ 35: 'Domestic Cat-LC', 36: 'Donkey-LC', 37: 'Dragonfly-LC', 38: 'Duck-LC', 39: 'Dugong-VU',
352
+ 40: 'Eagle-LC', 41: 'Earthworm-LC', 42: 'Echidna-LC', 43: 'Eel-LC', 44: 'Elephant-EN',
353
+ 45: 'Elk-LC', 46: 'Emu-LC', 47: 'Falcon-LC', 48: 'Ferret-EN', 49: 'Finch-LC',
354
+ 50: 'Firefly-LC', 51: 'Fish-LC', 52: 'Flamingo-LC', 53: 'Fossa-VU', 54: 'Fox-LC',
355
+ 55: 'Frog-LC', 56: 'Galápagos Tortoise-VU', 57: 'Gazelle-VU', 58: 'Gecko-LC', 59: 'Gibbon-EN',
356
+ 60: 'Giraffe-VU', 61: 'Goat-LC', 62: 'Goose-LC', 63: 'Gorilla-CR', 64: 'Grasshopper-LC',
357
+ 65: 'Great White Shark-VU', 66: 'Green Anaconda-LC', 67: 'Grizzly Bear-LC', 68: 'Hammerhead Shark-CR',
358
+ 69: 'Hamster-LC', 70: 'Hare-LC', 71: 'Hawk-LC', 72: 'Hedgehog-LC', 73: 'Hermit Crab-LC',
359
+ 74: 'Hippopotamus-VU', 75: 'Honeybee-LC', 76: 'Hornbill-NT', 77: 'Horse-LC', 78: 'Hummingbird-LC',
360
+ 79: 'Ibex-LC', 80: 'Ibis-LC', 81: 'Indian Cobra-LC', 82: 'Indian Elephant-EN', 83: 'Indian Star Tortoise-VU',
361
+ 84: 'Indian Wolf-EN', 85: 'Jackal-LC', 86: 'Jaguar-NT', 87: 'Japanese Beetle-LC', 88: 'Jellyfish-LC',
362
+ 89: 'Kangaroo-LC', 90: 'King Cobra-VU', 91: 'Kingfisher-LC', 92: 'Kiwi-EN', 93: 'Koala-VU',
363
+ 94: 'Komodo Dragon-EN', 95: 'Ladybug-LC', 96: 'Lemming-LC', 97: 'Lemur-CR', 98: 'Leopard-VU',
364
+ 99: 'Lion-VU', 100: 'Lizard-LC', 101: 'Llama-LC', 102: 'Lobster-LC', 103: 'Lynx-LC',
365
+ 104: 'Macaw-EN', 105: 'Magpie-LC', 106: 'Manatee-VU', 107: 'Mandrill-VU', 108: 'Mantis Shrimp-LC',
366
+ 109: 'Meerkat-LC', 110: 'Mole-LC', 111: 'Moose-LC', 112: 'Moray Eel-LC', 113: 'Mountain Lion-LC',
367
+ 114: 'Musk Ox-LC', 115: 'Nandu Rhea-LC', 116: 'Narwhal-NT', 117: 'Newt-LC', 118: 'Nightingale-LC',
368
+ 119: 'Octopus-LC', 120: 'Okapi-EN', 121: 'Opossum-LC', 122: 'Orangutan-CR', 123: 'Ostrich-LC',
369
+ 124: 'Otter-VU', 125: 'Owl-LC', 126: 'Ox-LC', 127: 'Panda-VU', 128: 'Panther-NT',
370
+ 129: 'Parrot-LC', 130: 'Peacock-LC', 131: 'Pelican-LC', 132: 'Penguin-NT', 133: 'Pigeon-LC',
371
+ 134: 'Piranha-LC', 135: 'Platypus-LC', 136: 'Polar Bear-VU', 137: 'Porcupine-LC', 138: 'Possum-LC',
372
+ 139: 'Praying Mantis-LC', 140: 'Puffin-LC', 141: 'Python-LC', 142: 'Quail-LC', 143: 'Quetzal-NT',
373
+ 144: 'Quokka-LC', 145: 'Quoll-NT', 146: 'Rabbit-LC', 147: 'Raccoon-LC', 148: 'Ram-LC',
374
+ 149: 'Rat-LC', 150: 'Raven-LC', 151: 'Red Panda-EN', 152: 'Reindeer-VU', 153: 'Rhinoceros-CR',
375
+ 154: 'Roadrunner-LC', 155: 'Salamander-LC', 156: 'Scorpion-LC', 157: 'Sea Lion-LC', 158: 'Seahorse-LC',
376
+ 159: 'Shark-VU', 160: 'Sheep-LC', 161: 'Skunk-LC', 162: 'Sloth-VU', 163: 'Snail-LC',
377
+ 164: 'Snake-LC', 165: 'Snow Leopard-VU', 166: 'Sparrow-LC', 167: 'Spider-LC', 168: 'Squirrel-LC',
378
+ 169: 'Starfish-LC', 170: 'Stork-LC', 171: 'Swan-LC', 172: 'Tamarin-EN', 173: 'Tapir-VU',
379
+ 174: 'Tasmanian Devil-EN', 175: 'Termite-LC', 176: 'Thorny Devil-LC', 177: 'Tiger-EN',
380
+ 178: 'Toad-LC', 179: 'Toucan-LC', 180: 'Tuna-LC', 181: 'Turkey-LC', 182: 'Turtle-VU',
381
+ 183: 'Uakari-VU', 184: 'Umbrellabird-VU', 185: 'Urchin-LC', 186: 'Uromastyx-LC', 187: 'Vampire Bat-LC',
382
+ 188: 'Vaquita-CR', 189: 'Vervet Monkey-LC', 190: 'Vulture-LC', 191: 'Wallaby-LC', 192: 'Walrus-VU',
383
+ 193: 'Warthog-LC', 194: 'Weasel-LC', 195: 'Whale-EN', 196: 'White Tiger-EN', 197: 'Wild Cat-VU',
384
+ 198: 'Wolf-VU', 199: 'Wolverine-LC', 200: 'Wombat-LC', 201: 'Woodpecker-LC', 202: 'X-ray Tetra-LC',
385
+ 203: 'Xenopus-LC', 204: 'Yak-LC', 205: 'Yellowjacket-LC', 206: 'Zebra Finch-LC', 207: 'Zebra-NT',
386
+ 208: 'Zebu-LC', 209: 'Zorilla-LC'
387
+ }
388
 
389
  predicted_class = labels.get(predicted_class_index, "Unknown")
390
  conservation_status = get_conservation_status(predicted_class)
391
+ predicted_class_clean = predicted_class.split('-')[0]
392
+ print(f"Prediction: {predicted_class_clean}, Confidence: {confidence_level}%")
393
 
394
  # Generate explanation using Gemini AI
395
+ explanation = generate_explanation(predicted_class_clean if confidence_level >= 30 else "unknown animal")
396
+
 
 
 
 
 
 
 
 
 
397
  # Store the result in the in-memory dictionary
398
+ prediction_id = str(time.time())
399
+ print(f"Storing result for Prediction ID: {prediction_id}")
400
+ if confidence_level < 30:
401
+ prediction_results[prediction_id] = {
402
+ "explanation": "Sorry! This image doesn’t seem to match any animals I was trained on. I’m doing my best with the knowledge I have. Please try a different image – ideally of a single, clear animal."
403
+ }
404
+ else:
405
  prediction_results[prediction_id] = {
406
+ "predicted_class": predicted_class_clean,
407
  "conservation_status": conservation_status,
408
  "confidence_level": confidence_level,
409
  "explanation": explanation
410
  }
411
+ print(f"Stored Result: {prediction_results[prediction_id]}")
412
  return jsonify({"prediction_id": prediction_id}), 200
413
 
414
  except Exception as e:
 
422
  print(f"Fetching prediction result for ID: {prediction_id}")
423
  result = prediction_results.get(prediction_id)
424
  if result:
425
+ print(f"Found result: {result}")
426
  return jsonify(result)
427
  else:
428
  print(f"No result found for ID: {prediction_id}")