pramodmisra commited on
Commit
b6866fc
·
verified ·
1 Parent(s): de946bd

Create app/gemini_scanner.py

Browse files
Files changed (1) hide show
  1. app/gemini_scanner.py +262 -0
app/gemini_scanner.py ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Gemini Vision API Integration for Image Scanning
3
+ Provides OCR and product identification for accessibility
4
+ """
5
+
6
+ import base64
7
+ from typing import Dict, Optional
8
+ from pydantic import BaseModel
9
+
10
+ GEMINI_API_KEY = "AIzaSyCKg9oniH4PH6gLcG7WZzrjNAESqmZCk2o"
11
+ GEMINI_API_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp:generateContent?key={GEMINI_API_KEY}"
12
+
13
+ class ScanResult(BaseModel):
14
+ success: bool
15
+ product_type: str # "medication", "grocery", "receipt", "unknown"
16
+ product_name: Optional[str] = None
17
+ brand: Optional[str] = None
18
+ details: Dict = {}
19
+ spoken_description: str
20
+ warnings: list = []
21
+
22
+ async def scan_product_image(image_data: str, scan_type: str = "auto") -> ScanResult:
23
+ """
24
+ Scan a product image using Gemini Vision API
25
+
26
+ Args:
27
+ image_data: Base64 encoded image
28
+ scan_type: "medication", "grocery", "receipt", or "auto"
29
+
30
+ Returns:
31
+ ScanResult with all extracted information
32
+ """
33
+
34
+ # Different prompts based on scan type
35
+ prompts = {
36
+ "medication": """
37
+ Analyze this medication/pharmaceutical product image carefully for a visually impaired user.
38
+
39
+ Provide COMPLETE information in this EXACT format:
40
+
41
+ PRODUCT TYPE: [Medication/Prescription/OTC]
42
+ PRODUCT NAME: [Full medication name]
43
+ BRAND: [Brand name if visible]
44
+ GENERIC NAME: [Generic name if visible]
45
+ STRENGTH: [Dosage strength, e.g., 500mg, 10mg]
46
+ FORM: [Tablet/Capsule/Liquid/Cream/etc]
47
+ QUANTITY: [Number of pills/volume]
48
+ EXPIRATION DATE: [Date if visible - CHECK CAREFULLY]
49
+ NDC/BARCODE: [If visible]
50
+ PRESCRIPTION INFO: [Patient name, Rx number if visible]
51
+ DIRECTIONS: [Usage instructions]
52
+ WARNINGS: [Any warning labels - list ALL you see]
53
+ INTERACTIONS: [Drug interaction warnings if visible]
54
+
55
+ SPOKEN DESCRIPTION: [Create a 2-3 sentence natural description that would be read aloud to someone who cannot see the image. Include the most critical safety information.]
56
+
57
+ SAFETY ALERTS: [If expired or any critical warnings, mention them prominently]
58
+
59
+ Be thorough and accurate. If you cannot read something clearly, say "Not clearly visible" rather than guessing.
60
+ """,
61
+
62
+ "grocery": """
63
+ Analyze this grocery/food product image for a visually impaired user.
64
+
65
+ Provide COMPLETE information in this EXACT format:
66
+
67
+ PRODUCT TYPE: [Food category]
68
+ PRODUCT NAME: [Full product name]
69
+ BRAND: [Brand name]
70
+ SIZE/WEIGHT: [Package size]
71
+ PRICE: [If visible on label or tag]
72
+ EXPIRATION/BEST BY: [Date if visible]
73
+ NUTRITIONAL HIGHLIGHTS: [Key nutrition facts if visible - calories, protein, etc]
74
+ INGREDIENTS: [Main ingredients if visible]
75
+ SPECIAL LABELS: [Organic, Gluten-Free, Non-GMO, etc]
76
+ BARCODE/UPC: [If visible]
77
+
78
+ SPOKEN DESCRIPTION: [Create a natural 2-3 sentence description for someone who cannot see. Include product name, size, and any important details like expiration or special features.]
79
+
80
+ If anything is unclear, say "Not clearly visible" rather than guessing.
81
+ """,
82
+
83
+ "receipt": """
84
+ Analyze this receipt image for a visually impaired user who wants to track their purchases.
85
+
86
+ Provide information in this EXACT format:
87
+
88
+ STORE: [Store name]
89
+ DATE: [Purchase date]
90
+ TIME: [Purchase time if visible]
91
+ TOTAL: [Total amount]
92
+
93
+ ITEMS PURCHASED: [List each item with price in this format]
94
+ - Item name | Price
95
+ - Item name | Price
96
+
97
+ PAYMENT METHOD: [If visible]
98
+
99
+ SPOKEN DESCRIPTION: [Create a natural summary: "Receipt from [Store] on [Date]. Total: [Amount]. You purchased [X] items including..." List 3-5 main items.]
100
+
101
+ List items clearly so they can be added to inventory.
102
+ """,
103
+
104
+ "auto": """
105
+ Analyze this image and determine what type of product it shows (medication, grocery item, receipt, or other).
106
+
107
+ Then provide detailed information following these guidelines:
108
+
109
+ 1. First, identify: Is this a MEDICATION, GROCERY ITEM, RECEIPT, or OTHER?
110
+
111
+ 2. For MEDICATIONS: Include name, dosage, warnings, expiration date, usage instructions
112
+ 3. For GROCERY: Include product name, brand, size, price, nutritional info, expiration
113
+ 4. For RECEIPTS: Include store, date, items purchased, total
114
+ 5. For OTHER: Describe what you see
115
+
116
+ PRODUCT TYPE: [medication/grocery/receipt/other]
117
+
118
+ [Then provide all relevant details in clear format]
119
+
120
+ SPOKEN DESCRIPTION: [Create a natural 2-3 sentence description that would be helpful for someone who cannot see the image. Focus on the most important information they would want to know.]
121
+
122
+ Always prioritize clarity and accuracy for accessibility purposes.
123
+ """
124
+ }
125
+
126
+ prompt = prompts.get(scan_type, prompts["auto"])
127
+
128
+ try:
129
+ import httpx
130
+
131
+ # Prepare the request
132
+ payload = {
133
+ "contents": [{
134
+ "parts": [
135
+ {"text": prompt},
136
+ {
137
+ "inline_data": {
138
+ "mime_type": "image/jpeg",
139
+ "data": image_data
140
+ }
141
+ }
142
+ ]
143
+ }],
144
+ "generationConfig": {
145
+ "temperature": 0.2, # Low temperature for accuracy
146
+ "maxOutputTokens": 2000
147
+ }
148
+ }
149
+
150
+ async with httpx.AsyncClient(timeout=30.0) as client:
151
+ response = await client.post(GEMINI_API_URL, json=payload)
152
+ response.raise_for_status()
153
+
154
+ data = response.json()
155
+ analysis_text = data["candidates"][0]["content"]["parts"][0]["text"]
156
+
157
+ # Parse the response
158
+ result = parse_gemini_response(analysis_text, scan_type)
159
+ return result
160
+
161
+ except Exception as e:
162
+ return ScanResult(
163
+ success=False,
164
+ product_type="error",
165
+ spoken_description=f"Sorry, I encountered an error scanning the image: {str(e)}",
166
+ warnings=["Scan failed - please try again or manually enter information"]
167
+ )
168
+
169
+ def parse_gemini_response(text: str, scan_type: str) -> ScanResult:
170
+ """Parse Gemini's response into structured data"""
171
+
172
+ lines = text.split('\n')
173
+ details = {}
174
+ product_name = None
175
+ brand = None
176
+ spoken_desc = ""
177
+ warnings = []
178
+ detected_type = scan_type if scan_type != "auto" else "unknown"
179
+
180
+ for line in lines:
181
+ line = line.strip()
182
+
183
+ # Extract key-value pairs
184
+ if ':' in line:
185
+ key, value = line.split(':', 1)
186
+ key = key.strip().upper()
187
+ value = value.strip()
188
+
189
+ if 'PRODUCT TYPE' in key:
190
+ detected_type = value.lower()
191
+ if 'medication' in detected_type or 'prescription' in detected_type:
192
+ detected_type = "medication"
193
+ elif 'grocery' in detected_type or 'food' in detected_type:
194
+ detected_type = "grocery"
195
+ elif 'receipt' in detected_type:
196
+ detected_type = "receipt"
197
+
198
+ elif 'PRODUCT NAME' in key or 'MEDICATION NAME' in key:
199
+ product_name = value
200
+ details['name'] = value
201
+
202
+ elif 'BRAND' in key:
203
+ brand = value
204
+ details['brand'] = value
205
+
206
+ elif 'SPOKEN DESCRIPTION' in key:
207
+ spoken_desc = value
208
+
209
+ elif 'WARNING' in key or 'SAFETY ALERT' in key:
210
+ if value and value != "None" and value != "Not visible":
211
+ warnings.append(value)
212
+
213
+ elif 'EXPIRATION' in key or 'EXPIRES' in key or 'BEST BY' in key:
214
+ details['expiration'] = value
215
+ # Check if expired
216
+ if 'expired' in value.lower():
217
+ warnings.append(f"⚠️ EXPIRED: {value}")
218
+
219
+ elif value and value not in ["None", "Not visible", "Not clearly visible"]:
220
+ # Store other details
221
+ clean_key = key.lower().replace(' ', '_')
222
+ details[clean_key] = value
223
+
224
+ # If no spoken description was found, create one from details
225
+ if not spoken_desc and product_name:
226
+ if detected_type == "medication":
227
+ spoken_desc = f"This is {product_name}"
228
+ if 'strength' in details:
229
+ spoken_desc += f", {details['strength']}"
230
+ if warnings:
231
+ spoken_desc += ". " + warnings[0]
232
+ elif detected_type == "grocery":
233
+ spoken_desc = f"This is {product_name}"
234
+ if brand:
235
+ spoken_desc += f" by {brand}"
236
+ if 'size/weight' in details:
237
+ spoken_desc += f", {details['size/weight']}"
238
+ else:
239
+ spoken_desc = f"Product identified: {product_name or 'Unknown'}"
240
+
241
+ return ScanResult(
242
+ success=True,
243
+ product_type=detected_type,
244
+ product_name=product_name,
245
+ brand=brand,
246
+ details=details,
247
+ spoken_description=spoken_desc or "Image scanned successfully. Please check details.",
248
+ warnings=warnings
249
+ )
250
+ ```
251
+
252
+ 5. **Click "Commit new file to main"**
253
+
254
+ ---
255
+
256
+ ### **Step 2: Update requirements.txt**
257
+
258
+ 1. **Click on `requirements.txt`**
259
+ 2. **Click "Edit"**
260
+ 3. **Add this line:**
261
+ ```
262
+ httpx==0.25.0