1MR commited on
Commit
59e413f
·
verified ·
1 Parent(s): 3687d2f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -0
app.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, Form, UploadFile, HTTPException
2
+ from fastapi.responses import FileResponse, JSONResponse
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ import boto3
5
+ import os
6
+ from botocore.exceptions import ClientError
7
+ import logging
8
+ import wikipedia
9
+ from gtts import gTTS
10
+ from PIL import Image, ImageEnhance
11
+ import uuid
12
+ import shutil
13
+
14
+ # Configure logging
15
+ logging.basicConfig(level=logging.INFO)
16
+ logger = logging.getLogger(__name__)
17
+
18
+ app = FastAPI()
19
+
20
+ app.add_middleware(
21
+ CORSMiddleware,
22
+ allow_origins=["*"],
23
+ allow_credentials=True,
24
+ allow_methods=["*"],
25
+ allow_headers=["*"],
26
+ )
27
+
28
+ aws_access_key = os.getenv("AWS_ACCESS_KEY_ID", "AKIA6G75DYEK3NWC2AXH")
29
+ aws_secret_key = os.getenv("AWS_SECRET_ACCESS_KEY", "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")
30
+ region_name = "us-east-1"
31
+
32
+ try:
33
+ rekognition = boto3.client(
34
+ "rekognition",
35
+ aws_access_key_id=aws_access_key,
36
+ aws_secret_access_key=aws_secret_key,
37
+ region_name=region_name
38
+ )
39
+ logger.info("Rekognition client initialized successfully.")
40
+ except Exception as e:
41
+ logger.error(f"Error initializing Rekognition client: {e}")
42
+ rekognition = None
43
+
44
+ KNOWN_LANDMARKS = {
45
+ "Pyramid": "Giza Pyramids",
46
+ "Eiffel Tower": "Eiffel Tower",
47
+ "Statue of Liberty": "Statue of Liberty",
48
+ "Great Wall": "Great Wall of China",
49
+ "Colosseum": "Colosseum",
50
+ "Taj Mahal": "Taj Mahal",
51
+ "Machu Picchu": "Machu Picchu",
52
+ "Christ the Redeemer": "Christ the Redeemer",
53
+ "Big Ben": "Big Ben",
54
+ "Leaning Tower of Pisa": "Leaning Tower of Pisa",
55
+ "Sydney Opera House": "Sydney Opera House",
56
+ "Mount Rushmore": "Mount Rushmore",
57
+ "Burj Khalifa": "Burj Khalifa"
58
+ }
59
+
60
+ def enhance_image(image_path):
61
+ with Image.open(image_path) as img:
62
+ logger.info("Enhancing image")
63
+ img = ImageEnhance.Contrast(img).enhance(1.5)
64
+ img = ImageEnhance.Sharpness(img).enhance(2.0)
65
+ img.thumbnail((640, 360), Image.Resampling.LANCZOS)
66
+ img.save(image_path)
67
+
68
+ def detect_landmark(image_path):
69
+ with open(image_path, "rb") as image_file:
70
+ response = rekognition.detect_labels(Image={"Bytes": image_file.read()}, MaxLabels=10)
71
+
72
+ best_match = None
73
+ for label in response.get("Labels", []):
74
+ if label["Name"] in KNOWN_LANDMARKS:
75
+ return KNOWN_LANDMARKS[label["Name"]]
76
+ if best_match is None or label["Confidence"] > best_match[1]:
77
+ best_match = (label["Name"], label["Confidence"])
78
+
79
+ return best_match[0] if best_match else None
80
+
81
+ def get_wikipedia_info(object_name, lang="en"):
82
+ try:
83
+ wikipedia.set_lang(lang)
84
+ results = wikipedia.search(object_name)
85
+ if not results:
86
+ return "No results found on Wikipedia."
87
+ page = wikipedia.page(results[0])
88
+ return page.summary[:600]
89
+ except Exception as e:
90
+ logger.error(f"Wikipedia error: {e}")
91
+ return f"Error fetching Wikipedia info: {e}"
92
+
93
+ def text_to_speech(text, lang="en"):
94
+ try:
95
+ tts = gTTS(text=text, lang=lang)
96
+ audio_path = f"temp_audio_{uuid.uuid4()}.mp3"
97
+ tts.save(audio_path)
98
+ return audio_path
99
+ except Exception as e:
100
+ logger.error(f"TTS error: {e}")
101
+ return None
102
+
103
+ @app.post("/recognize")
104
+ async def recognize_landmark(image: UploadFile = File(...), language: str = Form(...)):
105
+ if rekognition is None:
106
+ raise HTTPException(status_code=500, detail="Rekognition client not initialized")
107
+
108
+ image_path = f"temp_image_{uuid.uuid4()}.jpg"
109
+ try:
110
+ with open(image_path, "wb") as buffer:
111
+ shutil.copyfileobj(image.file, buffer)
112
+
113
+ enhance_image(image_path)
114
+ landmark_name = detect_landmark(image_path)
115
+ if not landmark_name:
116
+ os.remove(image_path)
117
+ raise HTTPException(status_code=400, detail="No landmark recognized")
118
+
119
+ wiki_info = get_wikipedia_info(landmark_name, language)
120
+ if "error" in wiki_info.lower():
121
+ os.remove(image_path)
122
+ raise HTTPException(status_code=500, detail=wiki_info)
123
+
124
+ audio_path = text_to_speech(wiki_info, language)
125
+ if not audio_path:
126
+ os.remove(image_path)
127
+ raise HTTPException(status_code=500, detail="Failed to generate audio")
128
+
129
+ return {
130
+ "landmark": landmark_name,
131
+ "information": wiki_info,
132
+ "image_url": f"/image/{os.path.basename(image_path)}",
133
+ "audio_url": f"/audio/{os.path.basename(audio_path)}"
134
+ }
135
+ except ClientError as e:
136
+ raise HTTPException(status_code=500, detail=f"AWS error: {str(e)}")
137
+ except Exception as e:
138
+ raise HTTPException(status_code=500, detail=f"Server error: {str(e)}")
139
+
140
+ @app.get("/image/{filename}")
141
+ async def serve_image(filename: str):
142
+ image_path = os.path.join(os.getcwd(), filename)
143
+ if not os.path.exists(image_path):
144
+ raise HTTPException(status_code=404, detail="Image not found")
145
+ response = FileResponse(image_path, media_type="image/jpeg")
146
+ try:
147
+ os.remove(image_path)
148
+ except Exception as e:
149
+ logger.warning(f"Could not delete image: {e}")
150
+ return response
151
+
152
+ @app.get("/audio/{filename}")
153
+ async def serve_audio(filename: str):
154
+ audio_path = os.path.join(os.getcwd(), filename)
155
+ if not os.path.exists(audio_path):
156
+ raise HTTPException(status_code=404, detail="Audio not found")
157
+ response = FileResponse(audio_path, media_type="audio/mpeg")
158
+ try:
159
+ os.remove(audio_path)
160
+ except Exception as e:
161
+ logger.warning(f"Could not delete audio: {e}")
162
+ return response