root-sajjan commited on
Commit
bca9cda
·
verified ·
1 Parent(s): c109c9f
cropped_images/crop_0.jpg ADDED
cropped_images/crop_1.jpg ADDED
cropped_images/crop_2.jpg ADDED
llm/fridge.JPG ADDED
llm/image_description.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoModelForCausalLM, AutoTokenizer
2
+ import torch
3
+ from PIL import Image
4
+
5
+ model = AutoModelForCausalLM.from_pretrained(
6
+ "openbmb/MiniCPM-Llama3-V-2_5",
7
+ trust_remote_code=True
8
+ )
9
+
10
+ print(model)
11
+
12
+ tokenizer = AutoTokenizer.from_pretrained(
13
+ "openbmb/MiniCPM-Llama3-V-2_5",
14
+ trust_remote_code=True
15
+ )
16
+
17
+ image = Image.open("fridge.JPG")
18
+ prompt = "What is the main object shown in the image? Describe in less than 5 words, as a name for it."
19
+
20
+ # First round chat
21
+ # question = "Tell me the model of this aircraft."
22
+ msgs = [{'role': 'user', 'content': [image, prompt]}]
23
+
24
+ answer = model.chat(
25
+ image=None,
26
+ msgs=msgs,
27
+ tokenizer=tokenizer
28
+ )
29
+ print(answer)
30
+
31
+
32
+ # chat = model.chat(
33
+ # image=image,
34
+ # question=prompt,
35
+ # tokenizer=tokenizer,
36
+ # generate_args={"temperature": 0.8}
37
+ # )
38
+
39
+ # print(chat)
llm/inference.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from huggingface_hub import InferenceClient
2
+ import nltk
3
+ import re
4
+ import requests
5
+ import os
6
+
7
+ api_key = os.getenv("HF_KEY")
8
+
9
+ nltk.download('punkt_tab')
10
+ nltk.download('averaged_perceptron_tagger')
11
+
12
+
13
+ client = InferenceClient(api_key=api_key)
14
+
15
+
16
+ def extract_product_info(text):
17
+ # Initialize result dictionary
18
+ result = {"brand": None, "model": None, "description": None, "price": None}
19
+
20
+ # Improved regex to prioritize currency-related patterns
21
+ price_match = re.search(
22
+ r'(\$\s?\d{1,3}(?:,\d{3})*(?:\.\d{2})?|(?:\d{1,3}(?:,\d{3})*(?:\.\d{2})?\s?(?:USD|usd|dollars|DOLLARS)))',
23
+ text
24
+ )
25
+ if price_match:
26
+ price = price_match.group().strip()
27
+ # Clean up the price format
28
+ if "$" in price or "USD" in price or "usd" in price:
29
+ result["price"] = re.sub(r'[^\d.]', '', price) # Keep only digits and decimals
30
+ else:
31
+ result["price"] = price
32
+ # Remove the price part from the text to prevent it from being included in the brand/model extraction
33
+ text = text.replace(price_match.group(), "").strip()
34
+
35
+ # Tokenize the remaining text and tag parts of speech
36
+ tokens = nltk.word_tokenize(text)
37
+ pos_tags = nltk.pos_tag(tokens)
38
+
39
+ # Extract brand and model (Proper Nouns + Alphanumeric patterns)
40
+ brand_parts = []
41
+ model_parts = []
42
+ description_parts = []
43
+
44
+ for word, tag in pos_tags:
45
+ if tag == 'NNP' or re.match(r'[A-Za-z0-9-]+', word):
46
+ if len(brand_parts) == 0: # Assume the first proper noun is the brand
47
+ brand_parts.append(word)
48
+ else: # Model number tends to follow the brand
49
+ model_parts.append(word)
50
+ else:
51
+ description_parts.append(word)
52
+
53
+ # Assign brand and model to result dictionary
54
+ if brand_parts:
55
+ result["brand"] = " ".join(brand_parts)
56
+ if model_parts:
57
+ result["model"] = " ".join(model_parts)
58
+
59
+ # Combine the remaining parts as description
60
+ result["description"] = " ".join(description_parts)
61
+
62
+ return result
63
+
64
+
65
+
66
+ def extract_info(text):
67
+ API_URL = "https://api-inference.huggingface.co/models/google/flan-t5-large"
68
+ headers = {"Authorization": f"Bearer {api_key}"}
69
+ payload = {"inputs": f"From the given text, extract brand name, model number, description about it, and its average price in today's market. Give me back a python dictionary with keys as brand_name, model_number, desc, price. The text is {text}.",}
70
+ response = requests.post(API_URL, headers=headers, json=payload)
71
+ print('GOOGLEE LLM OUTPUTTTTTTT\n\n',response )
72
+ output = response.json()
73
+ print(output)
74
+
75
+
76
+
77
+ def get_name(url, object):
78
+ messages = [
79
+ {
80
+ "role": "user",
81
+ "content": [
82
+ {
83
+ "type": "text",
84
+ "text": f"Is this a {object}?. Can you guess what it is and give me the closest brand it resembles to? or a model number? And give me its average price in today's market in USD. In output, give me its normal name, model name, model number and price. separated by commas. No description is needed."
85
+ },
86
+ {
87
+ "type": "image_url",
88
+ "image_url": {
89
+ "url": url
90
+ }
91
+ }
92
+ ]
93
+ }
94
+ ]
95
+
96
+ completion = client.chat.completions.create(
97
+ model="meta-llama/Llama-3.2-11B-Vision-Instruct",
98
+ messages=messages,
99
+ max_tokens=500
100
+ )
101
+
102
+
103
+ print(f'\n\nNow output of LLM:\n')
104
+ llm_result = completion.choices[0].message['content']
105
+ print(llm_result)
106
+ print(f'\n\nThat is the output')
107
+
108
+ result = extract_product_info(llm_result)
109
+ print(f'\n\nResult brand and price:{result}')
110
+
111
+ # result2 = extract_info(llm_result)
112
+ # print(f'\n\nFrom Google llm:{result2}')
113
+
114
+ return result
115
+
116
+ # url = "https://i.ibb.co/mNYvqDL/crop_39.jpg"
117
+ # object="fridge"
118
+
119
+ # get_name(url, object)
llm/upload_image.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+
3
+ def upload_image_to_imgbb(image_path, api_key="0e7fb6d183b8db925812dee230f71079"):
4
+ """
5
+ Uploads an image to ImgBB and returns the URL.
6
+
7
+ :param image_path: Path to the local image
8
+ :param api_key: ImgBB API key
9
+ :return: URL of the uploaded image
10
+ """
11
+ try:
12
+ # API endpoint for ImgBB
13
+ url = "https://api.imgbb.com/1/upload"
14
+
15
+ # Open the image in binary mode
16
+ with open(image_path, "rb") as image_file:
17
+ # Send POST request to upload the image
18
+ response = requests.post(
19
+ url,
20
+ data={"key": api_key},
21
+ files={"image": image_file}
22
+ )
23
+
24
+ # Check if the request was successful
25
+ if response.status_code == 200:
26
+ data = response.json()
27
+ print(f'Uploaded to {data["data"]["url"]}')
28
+ return data["data"]["url"]
29
+ else:
30
+ raise Exception(f"Error uploading image: {response.status_code}, {response.text}")
31
+ except Exception as e:
32
+ return str(e)
33
+
34
+ # # Replace with your local image path and ImgBB API key
35
+ # image_path = "fridge.JPG" # Replace this with your local image path
36
+ # api_key = "0e7fb6d183b8db925812dee230f71079" # Get your API key from https://api.imgbb.com/
37
+
38
+ # uploaded_url = upload_image_to_imgbb(image_path, api_key)
39
+ # print(f"Uploaded image URL: {uploaded_url}")
main.py ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile, Response, HTTPException
2
+ from fastapi.responses import JSONResponse, FileResponse
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from PIL import Image
5
+ import io
6
+ import requests
7
+ import sqlite3
8
+ from pydantic import BaseModel, EmailStr
9
+ from typing import List, Optional
10
+
11
+
12
+ from pathlib import Path
13
+ from model import YOLOModel
14
+ import shutil
15
+
16
+ from openpyxl import Workbook
17
+ from openpyxl.drawing.image import Image as ExcelImage
18
+ from openpyxl.styles import Alignment
19
+ import os
20
+
21
+ yolo = YOLOModel()
22
+
23
+ UPLOAD_FOLDER = Path("./uploads")
24
+ UPLOAD_FOLDER.mkdir(exist_ok=True)
25
+
26
+ app = FastAPI()
27
+
28
+ cropped_images_dir = "cropped_images"
29
+
30
+ # Initialize SQLite database
31
+ def init_db():
32
+ conn = sqlite3.connect('users.db')
33
+ c = conn.cursor()
34
+ c.execute('''
35
+ CREATE TABLE IF NOT EXISTS users (
36
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
37
+ firstName TEXT NOT NULL,
38
+ lastName TEXT NOT NULL,
39
+ country TEXT,
40
+ number TEXT, -- Phone number stored as TEXT to allow various formats
41
+ email TEXT UNIQUE NOT NULL, -- Email should be unique and non-null
42
+ password TEXT NOT NULL -- Password will be stored as a string (hashed ideally)
43
+ )
44
+ ''')
45
+ conn.commit()
46
+ conn.close()
47
+
48
+ init_db()
49
+
50
+ class UserSignup(BaseModel):
51
+ firstName: str
52
+ lastName: str
53
+ country: str
54
+ number: str
55
+ email: EmailStr
56
+ password: str
57
+
58
+ class UserLogin(BaseModel):
59
+ email: str
60
+ password: str
61
+
62
+ @app.post("/signup")
63
+ async def signup(user_data: UserSignup):
64
+ try:
65
+ conn = sqlite3.connect('users.db')
66
+ c = conn.cursor()
67
+
68
+ # Check if user already exists
69
+ c.execute("SELECT * FROM users WHERE email = ?", (user_data.email,))
70
+ if c.fetchone():
71
+ raise HTTPException(status_code=400, detail="Email already registered")
72
+
73
+ # Insert new user
74
+ c.execute("""
75
+ INSERT INTO users (firstName, lastName, country, number, email, password)
76
+ VALUES (?, ?, ?, ?, ?, ?)
77
+ """, (user_data.firstName, user_data.lastName, user_data.country, user_data.number, user_data.email, user_data.password))
78
+
79
+ conn.commit()
80
+ conn.close()
81
+
82
+ return {"message": "User registered successfully", "email": user_data.email}
83
+ except Exception as e:
84
+ raise HTTPException(status_code=500, detail=str(e))
85
+
86
+ @app.post("/login")
87
+ async def login(user_data: UserLogin):
88
+ try:
89
+ conn = sqlite3.connect('users.db')
90
+ c = conn.cursor()
91
+
92
+ # Find user
93
+ c.execute("SELECT * FROM users WHERE email = ? AND password = ?",
94
+ (user_data.email, user_data.password))
95
+ user = c.fetchone()
96
+
97
+ conn.close()
98
+
99
+ if not user:
100
+ raise HTTPException(status_code=401, detail="Invalid credentials")
101
+
102
+ return {
103
+ "message": "Login successful",
104
+ "user": {
105
+ "firstName": user[1],
106
+ "lastName": user[2],
107
+ "email": user[3]
108
+ }
109
+ }
110
+ except Exception as e:
111
+ raise HTTPException(status_code=500, detail=str(e))
112
+
113
+
114
+
115
+ @app.post("/upload")
116
+ async def upload_image(image: UploadFile = File(...)):
117
+ # print(f'\n\t\tUPLOADED!!!!')
118
+ try:
119
+ file_path = UPLOAD_FOLDER / image.filename
120
+ with file_path.open("wb") as buffer:
121
+ shutil.copyfileobj(image.file, buffer)
122
+ # print(f'Starting to pass into model, {file_path}')
123
+ # Perform YOLO inference
124
+ predictions = yolo.predict(str(file_path))
125
+ print(f'\n\n\n{predictions}\n\n\ \n\t\t\t\tare predictions')
126
+ # Clean up uploaded file
127
+ file_path.unlink() # Remove file after processing
128
+ return JSONResponse(content={"items": predictions})
129
+
130
+
131
+ except Exception as e:
132
+ return JSONResponse(content={"error": str(e)}, status_code=500)
133
+
134
+
135
+ @app.get("/download_cropped_image/{image_idx}")
136
+ def download_cropped_image(image_idx: int):
137
+ cropped_image_path = cropped_images_dir / f"crop_{image_idx}.jpg"
138
+ if cropped_image_path.exists():
139
+ return FileResponse(cropped_image_path, media_type="image/jpeg")
140
+ return JSONResponse(content={"error": "Cropped image not found"}, status_code=404)
141
+
142
+
143
+ def cleanup_images(directory: str):
144
+ """Remove all images in the directory."""
145
+ for file in Path(directory).glob("*"):
146
+ file.unlink()
147
+ '''
148
+
149
+ @app.post("/generate-excel/")
150
+ async def generate_excel(predictions: list):
151
+ # Create an Excel workbook
152
+ workbook = Workbook()
153
+ sheet = workbook.active
154
+ sheet.title = "Predictions"
155
+
156
+ # Add headers
157
+ headers = ["Category", "Confidence", "Predicted Brand", "Price", "Details", "Detected Text", "Image"]
158
+ sheet.append(headers)
159
+
160
+ for idx, prediction in enumerate(predictions):
161
+ # Extract details from the prediction
162
+ category = prediction["category"]
163
+ confidence = prediction["confidence"]
164
+ predicted_brand = prediction["predicted_brand"]
165
+ price = prediction["price"]
166
+ details = prediction["details"]
167
+ detected_text = prediction["detected_text"]
168
+ cropped_image_path = prediction["image_path"]
169
+
170
+ # Append data row
171
+ sheet.append([category, confidence, predicted_brand, price, details, detected_text])
172
+
173
+ # Add the image to the Excel file (if it exists)
174
+ if os.path.exists(cropped_image_path):
175
+ img = ExcelImage(cropped_image_path)
176
+ img.width, img.height = 50, 50 # Resize image to fit into the cell
177
+ sheet.add_image(img, f"G{idx + 2}") # Place in the "Image" column
178
+
179
+ excel_file_path = "predictions_with_images.xlsx"
180
+ workbook.save(excel_file_path)
181
+
182
+ # Cleanup after saving
183
+ cleanup_images(cropped_images_dir)
184
+
185
+ # Serve the Excel file as a response
186
+ return FileResponse(
187
+ excel_file_path,
188
+ media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
189
+ filename="predictions_with_images.xlsx"
190
+ )
191
+
192
+ '''
193
+
194
+ # Define the Prediction model
195
+ class Prediction(BaseModel):
196
+ category: Optional[str]
197
+ confidence: Optional[float]
198
+ predicted_brand: Optional[str]
199
+ price: Optional[str]
200
+ details: Optional[str]
201
+ detected_text: Optional[str]
202
+ image_url: Optional[str]
203
+ image_path: Optional[str]
204
+
205
+
206
+ @app.post("/generate-excel/")
207
+ async def generate_excel(predictions: List[Prediction]):
208
+ print('Generate excel called')
209
+
210
+ # Create an Excel workbook
211
+ workbook = Workbook()
212
+ sheet = workbook.active
213
+ sheet.title = "Predictions"
214
+
215
+ # Add headers
216
+ headers = ["Category", "Confidence", "Predicted Brand", "Price", "Image URL", "Details", "Detected Text", ]
217
+ sheet.append(headers)
218
+
219
+ # Set header style and alignment
220
+ for cell in sheet[1]:
221
+ cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
222
+ sheet.row_dimensions[1].height = 30 # Adjust header row height
223
+
224
+ # Set column widths based on data type
225
+ column_widths = {
226
+ "A": 20, # Category
227
+ "B": 15, # Confidence
228
+ "C": 40, # Predicted Brand
229
+ "D": 15, # Price
230
+ "E": 50, # Image URL
231
+ "F": 30, # Details
232
+ "G": 30 # Detected Text
233
+ }
234
+ for col, width in column_widths.items():
235
+ sheet.column_dimensions[col].width = width
236
+
237
+ # Add prediction rows
238
+ for idx, prediction in enumerate(predictions):
239
+ row_index = idx + 2 # Start from the second row
240
+
241
+ # Add data to the row
242
+ sheet.append([
243
+ prediction.category,
244
+ prediction.confidence,
245
+ prediction.predicted_brand,
246
+ prediction.price,
247
+ prediction.image_url,
248
+ prediction.details,
249
+ prediction.detected_text,
250
+
251
+ ])
252
+
253
+ # Adjust row height for multiline text
254
+ sheet.row_dimensions[row_index].height = 180 # Default height for rows
255
+
256
+ # Wrap text in all cells of the row
257
+ for col_idx in range(1, 8): # Columns A to G
258
+ cell = sheet.cell(row=row_index, column=col_idx)
259
+ cell.alignment = Alignment(wrap_text=True, vertical="top")
260
+
261
+ # Add image if the path exists
262
+ if os.path.exists(prediction.image_path):
263
+ img = ExcelImage(prediction.image_path)
264
+ img.width, img.height = 160, 160 # Resize image to fit into the cell
265
+ img_cell = f"G{row_index}" # Image column
266
+ sheet.add_image(img, img_cell)
267
+
268
+ # Save the Excel file
269
+ excel_file_path = "predictions_with_images.xlsx"
270
+ workbook.save(excel_file_path)
271
+
272
+ # Serve the Excel file as a response
273
+ return FileResponse(
274
+ excel_file_path,
275
+ media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
276
+ filename="predictions_with_images.xlsx"
277
+ )
278
+ '''
279
+
280
+ @app.post("/generate-excel/")
281
+ async def generate_excel(predictions: list):
282
+ print('Generate excel called')
283
+ # Create an Excel workbook
284
+ workbook = Workbook()
285
+ sheet = workbook.active
286
+ sheet.title = "Predictions"
287
+
288
+ # Add headers
289
+ headers = ["Category", "Confidence", "Predicted Brand", "Price", "Details", "Detected Text", "Image URL"]
290
+ sheet.append(headers)
291
+
292
+ # Format the header row
293
+ for cell in sheet[1]:
294
+ cell.alignment = Alignment(horizontal="center", vertical="center")
295
+
296
+ for idx, prediction in enumerate(predictions):
297
+ # Extract details from the prediction
298
+ category = prediction["category"]
299
+ confidence = prediction["confidence"]
300
+ predicted_brand = prediction["predicted_brand"]
301
+ price = prediction["price"]
302
+ details = prediction["details"]
303
+ detected_text = prediction["detected_text"]
304
+ image_url = prediction["image_url"] # URL to the image
305
+ cropped_image_path = prediction["image_path"] # Path to local image file for Excel embedding
306
+
307
+ # Append data row
308
+ sheet.append([category, confidence, predicted_brand, price, details, detected_text, image_url])
309
+
310
+ # If the image path exists, add the image to the Excel file
311
+ if os.path.exists(cropped_image_path):
312
+ img = ExcelImage(cropped_image_path)
313
+ img.width, img.height = 50, 50 # Resize image to fit into the cell
314
+ sheet.add_image(img, f"G{idx + 2}") # Place in the "Image" column
315
+
316
+ excel_file_path = "predictions_with_images.xlsx"
317
+ workbook.save(excel_file_path)
318
+
319
+ # Serve the Excel file as a response
320
+ return FileResponse(
321
+ excel_file_path,
322
+ media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
323
+ filename="predictions_with_images.xlsx"
324
+ )
325
+ '''
326
+
327
+ # code to accept the localhost to get images from
328
+ app.add_middleware(
329
+ CORSMiddleware,
330
+ allow_origins=["http://192.168.56.1:3000", "http://192.168.56.1:3001", "http://localhost:3000"],
331
+ allow_methods=["*"],
332
+ allow_headers=["*"],
333
+ )
main2.py ADDED
@@ -0,0 +1,188 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile, Response, HTTPException
2
+ from fastapi.responses import JSONResponse, FileResponse
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from PIL import Image
5
+ import io
6
+
7
+ import sqlite3
8
+ from pydantic import BaseModel, EmailStr
9
+
10
+ from pathlib import Path
11
+ from model import YOLOModel
12
+ import shutil
13
+
14
+ from openpyxl import Workbook
15
+ from openpyxl.drawing.image import Image as ExcelImage
16
+ import os
17
+
18
+ yolo = YOLOModel()
19
+
20
+ UPLOAD_FOLDER = Path("./uploads")
21
+ UPLOAD_FOLDER.mkdir(exist_ok=True)
22
+
23
+ app = FastAPI()
24
+
25
+ cropped_images_dir = "cropped_images"
26
+
27
+ # Initialize SQLite database
28
+ def init_db():
29
+ conn = sqlite3.connect('users.db')
30
+ c = conn.cursor()
31
+ c.execute('''
32
+ CREATE TABLE IF NOT EXISTS users (
33
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
34
+ firstName TEXT NOT NULL,
35
+ lastName TEXT NOT NULL,
36
+ country TEXT,
37
+ number TEXT, -- Phone number stored as TEXT to allow various formats
38
+ email TEXT UNIQUE NOT NULL, -- Email should be unique and non-null
39
+ password TEXT NOT NULL -- Password will be stored as a string (hashed ideally)
40
+ )
41
+ ''')
42
+ conn.commit()
43
+ conn.close()
44
+
45
+ init_db()
46
+
47
+ class UserSignup(BaseModel):
48
+ firstName: str
49
+ lastName: str
50
+ country: str
51
+ number: str
52
+ email: EmailStr
53
+ password: str
54
+
55
+ class UserLogin(BaseModel):
56
+ email: str
57
+ password: str
58
+
59
+ @app.post("/signup")
60
+ async def signup(user_data: UserSignup):
61
+ try:
62
+ conn = sqlite3.connect('users.db')
63
+ c = conn.cursor()
64
+
65
+ # Check if user already exists
66
+ c.execute("SELECT * FROM users WHERE email = ?", (user_data.email,))
67
+ if c.fetchone():
68
+ raise HTTPException(status_code=400, detail="Email already registered")
69
+
70
+ # Insert new user
71
+ c.execute("""
72
+ INSERT INTO users (firstName, lastName, country, number, email, password)
73
+ VALUES (?, ?, ?, ?, ?, ?)
74
+ """, (user_data.firstName, user_data.lastName, user_data.country, user_data.number, user_data.email, user_data.password))
75
+
76
+ conn.commit()
77
+ conn.close()
78
+
79
+ return {"message": "User registered successfully", "email": user_data.email}
80
+ except Exception as e:
81
+ raise HTTPException(status_code=500, detail=str(e))
82
+
83
+ @app.post("/login")
84
+ async def login(user_data: UserLogin):
85
+ try:
86
+ conn = sqlite3.connect('users.db')
87
+ c = conn.cursor()
88
+
89
+ # Find user
90
+ c.execute("SELECT * FROM users WHERE email = ? AND password = ?",
91
+ (user_data.email, user_data.password))
92
+ user = c.fetchone()
93
+
94
+ conn.close()
95
+
96
+ if not user:
97
+ raise HTTPException(status_code=401, detail="Invalid credentials")
98
+
99
+ return {
100
+ "message": "Login successful",
101
+ "user": {
102
+ "firstName": user[1],
103
+ "lastName": user[2],
104
+ "email": user[3]
105
+ }
106
+ }
107
+ except Exception as e:
108
+ raise HTTPException(status_code=500, detail=str(e))
109
+
110
+
111
+
112
+ @app.post("/upload")
113
+ async def upload_image(image: UploadFile = File(...)):
114
+ # print(f'\n\t\tUPLOADED!!!!')
115
+ try:
116
+ file_path = UPLOAD_FOLDER / image.filename
117
+ with file_path.open("wb") as buffer:
118
+ shutil.copyfileobj(image.file, buffer)
119
+ # print(f'Starting to pass into model, {file_path}')
120
+ # Perform YOLO inference
121
+ predictions = yolo.predict(str(file_path))
122
+ print(f'\n\n\n{predictions}\n\n\ \n\t\t\t\tare predictions')
123
+ # Clean up uploaded file
124
+ file_path.unlink() # Remove file after processing
125
+ return JSONResponse(content={"items": predictions})
126
+
127
+
128
+ except Exception as e:
129
+ return JSONResponse(content={"error": str(e)}, status_code=500)
130
+
131
+
132
+ def cleanup_images(directory: str):
133
+ """Remove all images in the directory."""
134
+ for file in Path(directory).glob("*"):
135
+ file.unlink()
136
+
137
+
138
+ @app.post("/generate-excel/")
139
+ async def generate_excel(predictions: list):
140
+ # Create an Excel workbook
141
+ workbook = Workbook()
142
+ sheet = workbook.active
143
+ sheet.title = "Predictions"
144
+
145
+ # Add headers
146
+ headers = ["Category", "Confidence", "Predicted Brand", "Price", "Details", "Detected Text", "Image"]
147
+ sheet.append(headers)
148
+
149
+ for idx, prediction in enumerate(predictions):
150
+ # Extract details from the prediction
151
+ category = prediction["category"]
152
+ confidence = prediction["confidence"]
153
+ predicted_brand = prediction["predicted_brand"]
154
+ price = prediction["price"]
155
+ details = prediction["details"]
156
+ detected_text = prediction["detected_text"]
157
+ cropped_image_path = prediction["image_path"]
158
+
159
+ # Append data row
160
+ sheet.append([category, confidence, predicted_brand, price, details, detected_text])
161
+
162
+ # Add the image to the Excel file (if it exists)
163
+ if os.path.exists(cropped_image_path):
164
+ img = ExcelImage(cropped_image_path)
165
+ img.width, img.height = 50, 50 # Resize image to fit into the cell
166
+ sheet.add_image(img, f"G{idx + 2}") # Place in the "Image" column
167
+
168
+ excel_file_path = "predictions_with_images.xlsx"
169
+ workbook.save(excel_file_path)
170
+
171
+ # Cleanup after saving
172
+ cleanup_images(cropped_images_dir)
173
+
174
+ # Serve the Excel file as a response
175
+ return FileResponse(
176
+ excel_file_path,
177
+ media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
178
+ filename="predictions_with_images.xlsx"
179
+ )
180
+
181
+
182
+ # code to accept the localhost to get images from
183
+ app.add_middleware(
184
+ CORSMiddleware,
185
+ allow_origins=["http://192.168.56.1:3000", "http://192.168.56.1:3001", "http://localhost:3000"],
186
+ allow_methods=["*"],
187
+ allow_headers=["*"],
188
+ )
model.py ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from pathlib import Path
3
+ from transformers import CLIPProcessor, CLIPModel
4
+ from PIL import Image, ImageDraw
5
+ import pytesseract
6
+ import requests
7
+ import os
8
+ from llm import inference, upload_image
9
+ from fastapi.responses import FileResponse, JSONResponse
10
+
11
+ import re
12
+
13
+ from io import BytesIO
14
+
15
+ cropped_images_dir = "cropped_images"
16
+ os.makedirs(cropped_images_dir, exist_ok=True)
17
+
18
+ # Load YOLO model
19
+ class YOLOModel:
20
+ def __init__(self, model_path="yolov5s.pt"):
21
+ """
22
+ Initialize the YOLO model. Downloads YOLOv5 pretrained model if not available.
23
+ """
24
+ torch.hub._validate_not_a_forked_repo=lambda a,b,c: True
25
+ self.model = torch.hub.load("ultralytics/yolov5", "custom", path=model_path, force_reload=True)
26
+
27
+
28
+ def predict_clip(self, image, brand_names):
29
+ """
30
+ Predict the most probable brand using CLIP.
31
+ """
32
+ inputs = self.clip_processor(
33
+ text=brand_names,
34
+ images=image,
35
+ return_tensors="pt",
36
+ padding=True
37
+ )
38
+ # print(f'Inputs to clip processor:{inputs}')
39
+ outputs = self.clip_model(**inputs)
40
+ logits_per_image = outputs.logits_per_image
41
+ probs = logits_per_image.softmax(dim=1) # Convert logits to probabilities
42
+ best_idx = probs.argmax().item()
43
+ return brand_names[best_idx], probs[0, best_idx].item()
44
+
45
+
46
+ def predict_text(self, image):
47
+ grayscale = image.convert('L')
48
+ text = pytesseract.image_to_string(grayscale)
49
+ return text.strip()
50
+
51
+
52
+ def predict(self, image_path):
53
+ """
54
+ Run YOLO inference on an image.
55
+
56
+ :param image_path: Path to the input image
57
+ :return: List of predictions with labels and bounding boxes
58
+ """
59
+ results = self.model(image_path)
60
+ image = Image.open(image_path).convert("RGB")
61
+ draw = ImageDraw.Draw(image)
62
+ predictions = results.pandas().xyxy[0] # Get predictions as pandas DataFrame
63
+ print(f'YOLO predictions:\n\n{predictions}')
64
+
65
+
66
+ output = []
67
+ file_responses = []
68
+
69
+
70
+ for idx, row in predictions.iterrows():
71
+ category = row['name']
72
+ confidence = row['confidence']
73
+ bbox = [row["xmin"], row["ymin"], row["xmax"], row["ymax"]]
74
+
75
+ # Crop the detected region
76
+ cropped_image = image.crop((bbox[0], bbox[1], bbox[2], bbox[3]))
77
+ cropped_image_path = os.path.join(cropped_images_dir, f"crop_{idx}.jpg")
78
+ cropped_image.save(cropped_image_path, "JPEG")
79
+
80
+ # uploading to cloud for getting URL to pass into LLM
81
+ print(f'Uploading now to image url')
82
+ image_url = upload_image.upload_image_to_imgbb(cropped_image_path)
83
+ print(f'Image URL received as{image_url}')
84
+ # inferencing llm for possible brands
85
+ result_llms = inference.get_name(image_url, category)
86
+
87
+ detected_text = self.predict_text(cropped_image)
88
+ print(f'Details:{detected_text}')
89
+ print(f'Predicted brand: {result_llms["model"]}')
90
+ # Draw bounding box and label on the image
91
+ draw.rectangle(bbox, outline="red", width=3)
92
+ draw.text(
93
+ (bbox[0], bbox[1] - 10),
94
+ f'{result_llms["brand"]})',
95
+ fill="red"
96
+ )
97
+
98
+ cropped_image_io = BytesIO()
99
+ cropped_image.save(cropped_image_io, format="JPEG")
100
+ cropped_image_io.seek(0)
101
+
102
+ # Append result
103
+ output.append({
104
+ "category": category,
105
+ "bbox": bbox,
106
+ "confidence": confidence,
107
+ "category_llm":result_llms["brand"],
108
+ "predicted_brand": result_llms["model"],
109
+ # "clip_confidence": clip_confidence,
110
+ "price":result_llms["price"],
111
+ "details":result_llms["description"],
112
+ "detected_text":detected_text,
113
+ "image_path":cropped_image_path,
114
+ "image_url":image_url,
115
+ })
116
+
117
+ # file_responses.append(f"/download_cropped_image/{idx}")
118
+
119
+ valid_indices = set(range(len(predictions)))
120
+
121
+ # Iterate over all files in the directory
122
+ for filename in os.listdir(cropped_images_dir):
123
+ # Check if the filename matches the pattern for cropped images
124
+ if filename.startswith("crop_") and filename.endswith(".jpg"):
125
+ # Extract the index from the filename
126
+ try:
127
+ file_idx = int(filename.split("_")[1].split(".")[0])
128
+ if file_idx not in valid_indices:
129
+ # Delete the file if its index is not valid
130
+ file_path = os.path.join(cropped_images_dir, filename)
131
+ os.remove(file_path)
132
+ print(f"Deleted excess file: {filename}")
133
+ except ValueError:
134
+ # Skip files that don't match the pattern
135
+ continue
136
+
137
+ return output
138
+ # return JSONResponse(
139
+ # content={
140
+ # "metadata": results,
141
+ # "cropped_image_urls": [
142
+ # f"/download_cropped_image/{idx}" for idx in range(len(file_responses))
143
+ # ],
144
+ # }
145
+ # )
146
+ # return {"metadata": results, "cropped_image_urls": file_responses}
147
+
148
+
149
+
predictions_with_images.xlsx ADDED
Binary file (21.9 kB). View file
 
users.db ADDED
Binary file (16.4 kB). View file