Spaces:
No application file
No application file
Commit ·
b887004
1
Parent(s): d20170b
upload
Browse files- app.py +138 -141
- app_file.py +2 -2
app.py
CHANGED
|
@@ -17,8 +17,8 @@ search_google = False
|
|
| 17 |
# GOOGLE_CSE_ID = "b536303d151b94476"
|
| 18 |
# GOOGLE_API_KEY = "AIzaSyBUvPKAZa2TddKYDJI9t0ac2A_JJqdgWHo"
|
| 19 |
# GOOGLE_CSE_ID = "f3446c60c52cd4dc2"
|
| 20 |
-
GOOGLE_API_KEY = "AIzaSyCoBYZK4khX_W5eW-AqEXKOclUIer6CiC8"
|
| 21 |
-
GOOGLE_CSE_ID = "c3ba01991c1a14c7d"
|
| 22 |
mode = 'local'
|
| 23 |
# mode = 'rbf'
|
| 24 |
|
|
@@ -70,21 +70,23 @@ shops = {
|
|
| 70 |
regex_price = r'(\d+\.?\d*) ?([€$])|([€$]) ?(\d+\.?\d*)'
|
| 71 |
|
| 72 |
|
| 73 |
-
def app(img, selected_shop):
|
| 74 |
-
|
| 75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
-
# Check if the uploaded file is a PDF
|
| 78 |
-
if selected_shop is None:
|
| 79 |
-
raise gr.Error("Please select a shop.")
|
| 80 |
|
| 81 |
-
try:
|
| 82 |
-
image_annotated = section(img)
|
| 83 |
-
pass
|
| 84 |
-
except Exception as e:
|
| 85 |
-
return gr.Error(f"An error occurred: {str(e)}")
|
| 86 |
-
|
| 87 |
-
return image_annotated, hotspots_sku_links[selected_shop]
|
| 88 |
def build_request(query, start=1, num=10, date_restrict=None, **params):
|
| 89 |
request = {
|
| 90 |
'key': GOOGLE_API_KEY,
|
|
@@ -112,6 +114,7 @@ def make_request(request):
|
|
| 112 |
else:
|
| 113 |
return None
|
| 114 |
|
|
|
|
| 115 |
with gr.Blocks() as demo:
|
| 116 |
|
| 117 |
with gr.Row():
|
|
@@ -127,6 +130,9 @@ with gr.Blocks() as demo:
|
|
| 127 |
section_btn = gr.Button("Identify Hotspots")
|
| 128 |
# selected_section = gr.Textbox(label="Selected Hotspot")
|
| 129 |
selected_section = gr.Markdown(label="Selected Hotspot")
|
|
|
|
|
|
|
|
|
|
| 130 |
def get_yolo_predictions(image, confidence_threshold):
|
| 131 |
# Use Roboflow API to get predictions
|
| 132 |
predictions = model.predict(image, confidence=confidence_threshold, overlap=10).json()
|
|
@@ -147,51 +153,23 @@ with gr.Blocks() as demo:
|
|
| 147 |
|
| 148 |
def section(img, selected_shop, confidence_threshold):
|
| 149 |
hostpots = []
|
| 150 |
-
texts = []
|
| 151 |
sku = []
|
| 152 |
-
|
|
|
|
|
|
|
|
|
|
| 153 |
|
| 154 |
#print("selected_shop:", selected_shop)
|
| 155 |
search_url = shops[selected_shop]['url']
|
| 156 |
ref_number_regex = shops[selected_shop]['regex']
|
| 157 |
# print("search_url:", search_url)
|
| 158 |
brands = shops[selected_shop]['brands'] if 'brands' in shops[selected_shop] else None
|
|
|
|
| 159 |
if brands:
|
| 160 |
brands = [brand.upper() for brand in brands]
|
| 161 |
|
| 162 |
if mode == 'rbf':
|
| 163 |
predictions = get_yolo_predictions(img)
|
| 164 |
-
# print("-------")
|
| 165 |
-
# for idx, pred in enumerate(predictions["predictions"]):
|
| 166 |
-
# x_center = int(pred["x"])
|
| 167 |
-
# y_center = int(pred["y"])
|
| 168 |
-
# x = int(x_center - (pred["width"] / 2))
|
| 169 |
-
# y = int(y_center - (pred["height"] / 2))
|
| 170 |
-
# w = int(pred["width"])
|
| 171 |
-
# h = int(pred["height"])
|
| 172 |
-
# # Cropping the image to the bounding box
|
| 173 |
-
# sub_image = img[y:y + h, x:x + w]
|
| 174 |
-
# cv2.imwrite(f"sub_image_{idx}.jpg", sub_image)
|
| 175 |
-
#
|
| 176 |
-
# # Extract text using OCR
|
| 177 |
-
# text = ocr(sub_image)
|
| 178 |
-
# texts.append(text)
|
| 179 |
-
#
|
| 180 |
-
# # print("bbox", idx)
|
| 181 |
-
# for object_number, text in enumerate(texts, start=1):
|
| 182 |
-
# print("object", object_number)
|
| 183 |
-
# # print("text", text)
|
| 184 |
-
# ref_numbers = re.findall(ref_number_regex, text)
|
| 185 |
-
# for ref in ref_numbers:
|
| 186 |
-
# print("SKU:", ref)
|
| 187 |
-
# # append 'M' before the ref number
|
| 188 |
-
# search_query = search_url + urllib.parse.quote(ref)
|
| 189 |
-
# if ref not in sku:
|
| 190 |
-
# sku.append(ref)
|
| 191 |
-
# # if search_query not in hotspots_sku_links:
|
| 192 |
-
# hotspots_sku_links.append(search_query)
|
| 193 |
-
# hostpots.append(((x, y, x + w, y + h), ref))
|
| 194 |
-
# return (img, hostpots)
|
| 195 |
else:
|
| 196 |
# local inference
|
| 197 |
results = get_yolo_predictions_local(img, confidence_threshold)
|
|
@@ -207,8 +185,6 @@ with gr.Blocks() as demo:
|
|
| 207 |
w = int(coord[2] - coord[0])
|
| 208 |
h = int(coord[3] - coord[1])
|
| 209 |
sub_image = img[y:y + h, x:x + w]
|
| 210 |
-
|
| 211 |
-
|
| 212 |
if shops[selected_shop]['url'] is None or shops[selected_shop]['url'] == "":
|
| 213 |
# just append the hotspot to hostpots
|
| 214 |
hostpots.append(((x, y, x + w, y + h), str(idx)))
|
|
@@ -216,110 +192,131 @@ with gr.Blocks() as demo:
|
|
| 216 |
|
| 217 |
# Extract text using OCR
|
| 218 |
text = ocr(sub_image)
|
| 219 |
-
texts.append(text)
|
| 220 |
|
| 221 |
-
|
| 222 |
-
#
|
| 223 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 224 |
ref_numbers = []
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
if
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
| 234 |
-
|
| 235 |
-
|
| 236 |
-
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
#print("PRICES: ", prices)
|
| 267 |
-
|
| 268 |
-
if brands:
|
| 269 |
-
# print("BRANDS: yes")
|
| 270 |
-
# Extracting the product name
|
| 271 |
-
lines = text.split('\n')
|
| 272 |
-
product_name = ""
|
| 273 |
-
found_brand = False
|
| 274 |
-
name_started = False
|
| 275 |
-
for line in lines:
|
| 276 |
-
if any(brand in line for brand in brands):
|
| 277 |
-
found_brand = True
|
| 278 |
-
#print("FOUND BRAND", line)
|
| 279 |
continue
|
| 280 |
-
if
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
break
|
| 286 |
-
product_name += line.strip() + " "
|
| 287 |
-
name_started = True
|
| 288 |
-
product_name = product_name.strip()
|
| 289 |
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
|
| 294 |
-
|
| 295 |
-
|
| 296 |
|
| 297 |
#print("PRODUCT NAME: ", product_name)
|
| 298 |
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
else:
|
| 310 |
search_query = search_url + urllib.parse.quote(ref)
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 317 |
print("hotspots_sku_links: ", hotspots_sku_links)
|
|
|
|
|
|
|
| 318 |
print("skus: ", sku)
|
| 319 |
-
|
|
|
|
|
|
|
|
|
|
| 320 |
|
|
|
|
| 321 |
|
| 322 |
-
section_btn.click(section, [img_input, selected_shop, confidence_threshold], img_output)
|
| 323 |
|
| 324 |
|
| 325 |
def select_section(evt: gr.SelectData):
|
|
|
|
| 17 |
# GOOGLE_CSE_ID = "b536303d151b94476"
|
| 18 |
# GOOGLE_API_KEY = "AIzaSyBUvPKAZa2TddKYDJI9t0ac2A_JJqdgWHo"
|
| 19 |
# GOOGLE_CSE_ID = "f3446c60c52cd4dc2"
|
| 20 |
+
# GOOGLE_API_KEY = "AIzaSyCoBYZK4khX_W5eW-AqEXKOclUIer6CiC8"
|
| 21 |
+
# GOOGLE_CSE_ID = "c3ba01991c1a14c7d"
|
| 22 |
mode = 'local'
|
| 23 |
# mode = 'rbf'
|
| 24 |
|
|
|
|
| 70 |
regex_price = r'(\d+\.?\d*) ?([€$])|([€$]) ?(\d+\.?\d*)'
|
| 71 |
|
| 72 |
|
| 73 |
+
# def app(img, selected_shop):
|
| 74 |
+
# if img is None:
|
| 75 |
+
# raise gr.Error("No file uploaded. Please upload an image.")
|
| 76 |
+
#
|
| 77 |
+
# # Check if the uploaded file is a PDF
|
| 78 |
+
# if selected_shop is None:
|
| 79 |
+
# raise gr.Error("Please select a shop.")
|
| 80 |
+
#
|
| 81 |
+
# try:
|
| 82 |
+
# image_annotated = section(img)
|
| 83 |
+
# pass
|
| 84 |
+
# except Exception as e:
|
| 85 |
+
# return gr.Error(f"An error occurred: {str(e)}")
|
| 86 |
+
#
|
| 87 |
+
# return image_annotated, hotspots_sku_links[selected_shop]
|
| 88 |
|
|
|
|
|
|
|
|
|
|
| 89 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
def build_request(query, start=1, num=10, date_restrict=None, **params):
|
| 91 |
request = {
|
| 92 |
'key': GOOGLE_API_KEY,
|
|
|
|
| 114 |
else:
|
| 115 |
return None
|
| 116 |
|
| 117 |
+
|
| 118 |
with gr.Blocks() as demo:
|
| 119 |
|
| 120 |
with gr.Row():
|
|
|
|
| 130 |
section_btn = gr.Button("Identify Hotspots")
|
| 131 |
# selected_section = gr.Textbox(label="Selected Hotspot")
|
| 132 |
selected_section = gr.Markdown(label="Selected Hotspot")
|
| 133 |
+
product_dataframe = gr.Dataframe(label="Products Found")
|
| 134 |
+
|
| 135 |
+
|
| 136 |
def get_yolo_predictions(image, confidence_threshold):
|
| 137 |
# Use Roboflow API to get predictions
|
| 138 |
predictions = model.predict(image, confidence=confidence_threshold, overlap=10).json()
|
|
|
|
| 153 |
|
| 154 |
def section(img, selected_shop, confidence_threshold):
|
| 155 |
hostpots = []
|
|
|
|
| 156 |
sku = []
|
| 157 |
+
product_table_data = []
|
| 158 |
+
|
| 159 |
+
global hotspots_sku_links
|
| 160 |
+
hotspots_sku_links = []
|
| 161 |
|
| 162 |
#print("selected_shop:", selected_shop)
|
| 163 |
search_url = shops[selected_shop]['url']
|
| 164 |
ref_number_regex = shops[selected_shop]['regex']
|
| 165 |
# print("search_url:", search_url)
|
| 166 |
brands = shops[selected_shop]['brands'] if 'brands' in shops[selected_shop] else None
|
| 167 |
+
|
| 168 |
if brands:
|
| 169 |
brands = [brand.upper() for brand in brands]
|
| 170 |
|
| 171 |
if mode == 'rbf':
|
| 172 |
predictions = get_yolo_predictions(img)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
else:
|
| 174 |
# local inference
|
| 175 |
results = get_yolo_predictions_local(img, confidence_threshold)
|
|
|
|
| 185 |
w = int(coord[2] - coord[0])
|
| 186 |
h = int(coord[3] - coord[1])
|
| 187 |
sub_image = img[y:y + h, x:x + w]
|
|
|
|
|
|
|
| 188 |
if shops[selected_shop]['url'] is None or shops[selected_shop]['url'] == "":
|
| 189 |
# just append the hotspot to hostpots
|
| 190 |
hostpots.append(((x, y, x + w, y + h), str(idx)))
|
|
|
|
| 192 |
|
| 193 |
# Extract text using OCR
|
| 194 |
text = ocr(sub_image)
|
|
|
|
| 195 |
|
| 196 |
+
if selected_shop == "Latulippe":
|
| 197 |
+
# if there is a 'i' between a "M" and a number, it is a sku. Replace the 'i' with a '1'
|
| 198 |
+
text = re.sub(r'Mi(\d+)', r'M1\1', text)
|
| 199 |
+
|
| 200 |
+
# for object_number, text in enumerate(texts, start=1):
|
| 201 |
+
#print("object", object_number)
|
| 202 |
+
print("text -----", text)
|
| 203 |
+
ref_numbers = []
|
| 204 |
+
if selected_shop == "Decathlon":
|
| 205 |
+
full_match = re.search(ref_number_regex, text)
|
| 206 |
+
if full_match:
|
| 207 |
+
print("FULL MATCH: ", full_match)
|
| 208 |
+
# Extracting all numbers from the captured sequence
|
| 209 |
+
numbers_string = full_match.group(1)
|
| 210 |
+
ref_numbers = re.findall(r'\d+', numbers_string)
|
| 211 |
+
print("REF NUMBERS: ", ref_numbers)
|
| 212 |
+
else:
|
| 213 |
+
ref_numbers = re.findall(ref_number_regex, text)
|
| 214 |
+
# print("REF NUMBERS: ", ref_numbers)
|
| 215 |
+
|
| 216 |
+
if selected_shop == "Canadian Tire":
|
| 217 |
+
temp_ref_numbers = ref_numbers
|
| 218 |
ref_numbers = []
|
| 219 |
+
split = False
|
| 220 |
+
for ref_sku in temp_ref_numbers:
|
| 221 |
+
if '/' in ref_sku:
|
| 222 |
+
split = True
|
| 223 |
+
sku_split = ref_sku.split('/')
|
| 224 |
+
sku_last = sku_split[-1]
|
| 225 |
+
length = len(sku_last)
|
| 226 |
+
base_number = sku_split[0][:-length]
|
| 227 |
+
ref_numbers.append(sku_split[0])
|
| 228 |
+
# base number + sku for each sku in sku_split except the first one
|
| 229 |
+
for i in range(1, len(sku_split)):
|
| 230 |
+
ref_numbers.append(base_number + sku_split[i])
|
| 231 |
+
|
| 232 |
+
if split == False:
|
| 233 |
+
ref_numbers = temp_ref_numbers
|
| 234 |
+
|
| 235 |
+
matches = re.findall(regex_price, text)
|
| 236 |
+
prices = []
|
| 237 |
+
for match in matches:
|
| 238 |
+
if match[0]: # If the first group is not empty, the format is "price currency"
|
| 239 |
+
prices.append(match[0] + match[1])
|
| 240 |
+
else: # Otherwise, the format is "currency price"
|
| 241 |
+
prices.append(match[2] + match[3])
|
| 242 |
+
# price = prices[0] if len(prices) > 0 else ""
|
| 243 |
+
#print("PRICES: ", prices)
|
| 244 |
+
|
| 245 |
+
if brands:
|
| 246 |
+
# print("BRANDS: yes")
|
| 247 |
+
# Extracting the product name
|
| 248 |
+
lines = text.split('\n')
|
| 249 |
+
product_name = ""
|
| 250 |
+
found_brand = False
|
| 251 |
+
name_started = False
|
| 252 |
+
for line in lines:
|
| 253 |
+
if any(brand in line for brand in brands):
|
| 254 |
+
found_brand = True
|
| 255 |
+
#print("FOUND BRAND", line)
|
| 256 |
+
continue
|
| 257 |
+
if found_brand:
|
| 258 |
+
#print('current line:', line)
|
| 259 |
+
if line.strip() == "": # Skip blank lines
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 260 |
continue
|
| 261 |
+
if name_started and (line[0].isupper() or any(char.isdigit() for char in line)):
|
| 262 |
+
break
|
| 263 |
+
product_name += line.strip() + " "
|
| 264 |
+
name_started = True
|
| 265 |
+
product_name = product_name.strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
|
| 267 |
+
else:
|
| 268 |
+
# Regex to match sequences of uppercase letters
|
| 269 |
+
uppercase_words = re.findall(r'\b[A-Z]+\b', text)
|
| 270 |
|
| 271 |
+
# Joining the extracted words with a space
|
| 272 |
+
product_name = ' '.join(uppercase_words)
|
| 273 |
|
| 274 |
#print("PRODUCT NAME: ", product_name)
|
| 275 |
|
| 276 |
+
for ref in ref_numbers:
|
| 277 |
+
print("ref", ref)
|
| 278 |
+
if search_google:
|
| 279 |
+
# Use Google Search API to find items with the SKU
|
| 280 |
+
to_seach = str(selected_shop) + ' ' + str(ref)
|
| 281 |
+
# print("to_search: ", to_seach)
|
| 282 |
+
request = build_request(to_seach)
|
| 283 |
+
search_query = make_request(request)
|
| 284 |
+
# print(f"First Result URL: {search_query}")
|
| 285 |
+
if search_query is None:
|
|
|
|
| 286 |
search_query = search_url + urllib.parse.quote(ref)
|
| 287 |
+
else:
|
| 288 |
+
search_query = search_url + urllib.parse.quote(ref)
|
| 289 |
+
if ref not in sku:
|
| 290 |
+
sku.append(ref)
|
| 291 |
+
# if search_query not in hotspots_sku_links:
|
| 292 |
+
hotspots_sku_links.append([{'sku': ref, 'url': search_query, 'prices': prices, 'product_name': product_name}])
|
| 293 |
+
hostpots.append(((int(coord[0]), int(coord[1]), int(coord[2]), int(coord[3])), str(ref)))
|
| 294 |
+
|
| 295 |
+
for data in hotspots_sku_links:
|
| 296 |
+
for item in data:
|
| 297 |
+
product_table_data.append({
|
| 298 |
+
'Reference Number': item['sku'],
|
| 299 |
+
'Product Name': item['product_name'] if item['product_name'] else "Not Found",
|
| 300 |
+
# 'Price': ", ".join(item['prices']) if item['prices'] else " ",
|
| 301 |
+
'URL': item['url']
|
| 302 |
+
})
|
| 303 |
+
|
| 304 |
+
# Create a DataFrame
|
| 305 |
+
product_dataframe_data = pd.DataFrame(product_table_data)
|
| 306 |
+
|
| 307 |
+
# flattern the list hotspots_sku_links
|
| 308 |
+
# hotspots_sku_links = [item for sublist in hotspots_sku_links for item in sublist]
|
| 309 |
print("hotspots_sku_links: ", hotspots_sku_links)
|
| 310 |
+
print('length of hotspots_sku_links: ', len(hotspots_sku_links))
|
| 311 |
+
print('shape of hotspots_sku_links: ', np.shape(hotspots_sku_links))
|
| 312 |
print("skus: ", sku)
|
| 313 |
+
print('length of skus: ', len(sku))
|
| 314 |
+
assert len(hotspots_sku_links) == len(sku)
|
| 315 |
+
return (img, hostpots), product_dataframe_data
|
| 316 |
+
|
| 317 |
|
| 318 |
+
section_btn.click(section, [img_input, selected_shop, confidence_threshold], [img_output, product_dataframe])
|
| 319 |
|
|
|
|
| 320 |
|
| 321 |
|
| 322 |
def select_section(evt: gr.SelectData):
|
app_file.py
CHANGED
|
@@ -17,8 +17,8 @@ search_google = False
|
|
| 17 |
# GOOGLE_CSE_ID = "b536303d151b94476"
|
| 18 |
# GOOGLE_API_KEY = "AIzaSyBUvPKAZa2TddKYDJI9t0ac2A_JJqdgWHo"
|
| 19 |
# GOOGLE_CSE_ID = "f3446c60c52cd4dc2"
|
| 20 |
-
GOOGLE_API_KEY = "AIzaSyCoBYZK4khX_W5eW-AqEXKOclUIer6CiC8"
|
| 21 |
-
GOOGLE_CSE_ID = "c3ba01991c1a14c7d"
|
| 22 |
mode = 'local'
|
| 23 |
# mode = 'rbf'
|
| 24 |
|
|
|
|
| 17 |
# GOOGLE_CSE_ID = "b536303d151b94476"
|
| 18 |
# GOOGLE_API_KEY = "AIzaSyBUvPKAZa2TddKYDJI9t0ac2A_JJqdgWHo"
|
| 19 |
# GOOGLE_CSE_ID = "f3446c60c52cd4dc2"
|
| 20 |
+
# GOOGLE_API_KEY = "AIzaSyCoBYZK4khX_W5eW-AqEXKOclUIer6CiC8"
|
| 21 |
+
# GOOGLE_CSE_ID = "c3ba01991c1a14c7d"
|
| 22 |
mode = 'local'
|
| 23 |
# mode = 'rbf'
|
| 24 |
|