Spaces:
Runtime error
Runtime error
File size: 11,515 Bytes
5b2fcab |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 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 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# https://planogram-compliance.herokuapp.com/
# https://dashboard.heroku.com/apps/planogram-compliance/deploy/heroku-git
# https://medium.com/@mohcufe/how-to-deploy-your-trained-pytorch-model-on-heroku-ff4b73085ddd\
# https://stackoverflow.com/questions/51730880/where-do-i-get-a-cpu-only-version-of-pytorch
# https://blog.jcharistech.com/2020/02/26/how-to-deploy-a-face-detection-streamlit-app-on-heroku/
# https://towardsdatascience.com/a-quick-tutorial-on-how-to-deploy-your-streamlit-app-to-heroku-
# https://www.analyticsvidhya.com/blog/2021/06/deploy-your-ml-dl-streamlit-application-on-heroku/
# https://gist.github.com/jeremyjordan/6b506257509e8ba673f145baa568a1ea
import json
# https://www.r-bloggers.com/2020/12/creating-a-streamlit-web-app-building-with-docker-github-actions-and-hosting-on-heroku/
# https://devcenter.heroku.com/articles/container-registry-and-runtime
# from yolo_inference_util import run_yolo_v5
import os
from tempfile import NamedTemporaryFile
import cv2
import numpy as np
import pandas as pd
import streamlit as st
# import matplotlib.pyplot as plt
from app_utils import annotate_planogram_compliance, bucket_sort, do_sorting, xml_to_csv
from inference import run
# from utils.plots import Annotator, colors
# from utils.general import scale_coords
app_formal_name = "Planogram Compliance"
FILE_UPLOAD_DIR = "tmp"
os.makedirs(FILE_UPLOAD_DIR, exist_ok=True)
# Start the app in wide-mode
st.set_page_config(
layout="wide",
page_title=app_formal_name,
)
# https://github.com/streamlit/streamlit/issues/1361
uploaded_file = st.file_uploader(
"Choose a planogram image to score",
type=["jpg", "JPEG", "PNG", "JPG", "jpeg"],
)
uploaded_master_planogram_file = st.file_uploader(
"Upload a master planogram", type=["jpg", "JPEG", "PNG", "JPG", "jpeg"]
)
annotation_file = st.file_uploader("upload master polanogram", type=["xml"])
temp_file = NamedTemporaryFile(delete=False)
target_names = [
"Bottle,100PLUS ACTIVE 1.5L",
"Bottle,100PLUS ACTIVE 500ML",
"Bottle,100PLUS LEMON LIME 1.5L",
"Bottle,100PLUS ORANGE 500ML",
"Bottle,100PLUS ORIGINAL 1.5L",
"Bottle,100PLUS TANGY ORANGE 1.5L",
"Bottle,100PLUS ZERO 1.5L",
"Bottle,100PLUS ZERO 500ML",
"Packet,F:M MAGNOLIA CHOC 1L",
"Bottle,F&N GINGER ADE 1.5L",
"Bottle,F&N GRAPE 1.5L",
"Bottle,F&N ICE CREAM SODA 1.5L",
"Bottle,F&N LYCHEE PEAR 1.5L",
"Bottle,F&N ORANGE 1.5L",
"Bottle,F&N PINEAPPLE PET 1.5L",
"Bottle,F&N SARSI 1.5L",
"Bottle,F&N SS ICE LEM TEA RS 500ML",
"Bottle,F&N SS ICE LEMON TEA RS 1.5L",
"Bottle,F&N SS ICE LEMON TEA 1.5L",
"Bottle,F&N SS ICE LEMON TEA 500ML",
"Bottle,F&N SS ICE PEACH TEA 1.5L",
"Bottle,SS ICE LEMON GT 1.48L",
"Bottle,SS WHITE CHRYS TEA 1.48L",
"Packet,FARMHOUSE FRESH MILK 1L FNDM",
"Packet,FARMHOUSE PLAIN LF 1L",
"Packet,PURA FRESH MILK 1L FS",
"Packet,NUTRISOY REG NO SUGAR ADDED 1L",
"Packet,NUTRISOY PLAIN 475ML",
"Packet,NUTRISOY PLAIN 1L",
"Packet,NUTRISOY OMEGA RD SUGAR 1L",
"Packet,NUTRISOY OMEGA NSA 1L",
"Packet,NUTRISOY ALMOND 1L",
"Packet,MAGNOLIA FRESH MILK 1L FNDM",
"Packet,FM MAG FC PLAIN 200ML",
"Packet,MAG OMEGA PLUS PLAIN 200ML",
"Packet,MAG KURMA MILK 500ML",
"Packet,MAG KURMA MILK 1L",
"Packet,MAG CHOCOLATE FC 500ML",
"Packet,MAG BROWN SUGAR SS MILK 1L",
"Packet,FM MAG LFHC PLN 500ML",
"Packet,FM MAG LFHC OAT 500ML",
"Packet,FM MAG LFHC OAT 1L",
"Packet,FM MAG FC PLAIN 500ML",
"Void,PARTIAL VOID",
"Void,FULL VOID",
"Bottle,F&N SS ICE LEM TEA 500ML",
]
run_app = st.button("Run the compliance check")
if run_app and uploaded_file is not None:
# Convert the file to an opencv image.
file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
temp_file.write(uploaded_file.getvalue())
uploaded_img = cv2.imdecode(file_bytes, 1)
cv2.imwrite("tmp/to_score_planogram_tmp.png", uploaded_img)
# if uploaded_master_planogram_file is None:
# master = cv2.imread('./sample_master_planogram.jpeg')
names_dict = {name: id for id, name in enumerate(target_names)}
sorted_xml_df = None
# https://discuss.streamlit.io/t/unable-to-read-files-using-standard-file-uploader/2258/2
if uploaded_master_planogram_file and annotation_file:
file_bytes = np.asarray(
bytearray(uploaded_master_planogram_file.read()), dtype=np.uint8
)
master = cv2.imdecode(file_bytes, 1)
cv2.imwrite("tmp/master_tmp.png", master)
# cv2.imwrite("tmp_uploaded_master_planogram_img.png", master)
# xml = annotation_file.read()
# tmp_xml ="tmp_xml_annotation.xml"
# with open(tmp_xml ,'w',encoding='utf-8') as f:
# xml = f.write(xml)
xml_df = xml_to_csv(annotation_file)
xml_df["cls"] = xml_df["cls"].map(names_dict)
sorted_xml_df = do_sorting(xml_df)
sorted_xml_df.line_number.value_counts()
line_data = sorted_xml_df.line_number.value_counts()
n_rows = int(len(line_data))
n_cols = int(max(line_data))
master_table = np.zeros((n_rows, n_cols)) + 101
master_annotations = []
for i, row in sorted_xml_df.groupby("line_number"):
# print(f"Adding products in the row {i} to the detected planogram", row.cls.tolist())
products = row.cls.tolist()
master_table[int(i - 1), 0 : len(products)] = products
annotations = [
(int(k), int(v))
for k, v in list(
zip(row.cls.unique(), row.cls.value_counts().tolist())
)
]
master_annotations.append(annotations)
master_table.shape
# print("Annoatated planogram")
# print(np.matrix(master_table))
elif uploaded_master_planogram_file:
print(
"Finding the amster annotations with the YOLOv5 model predictions"
)
file_bytes = np.asarray(
bytearray(uploaded_master_planogram_file.read()), dtype=np.uint8
)
master = cv2.imdecode(file_bytes, 1)
cv2.imwrite("tmp/master_tmp.png", master)
master_results = run(
weights="base_line_best_model_exp5.pt",
source="tmp/master_tmp.png",
imgsz=[640, 640],
conf_thres=0.6,
iou_thres=0.6,
)
bb_df = pd.DataFrame(
master_results[0][1].tolist(),
columns=["xmin", "ymin", "xmax", "ymax", "conf", "cls"],
)
sorted_df = do_sorting(bb_df)
n_rows = int(sorted_df.line_number.max())
n_cols = int(
sorted_df.groupby("line_number")
.size()
.reset_index(name="counts")["counts"]
.max()
)
non_null_product = 101
print("master size", n_rows, n_cols)
master_annotations = []
master_table = np.zeros((int(n_rows), int(n_cols))) + non_null_product
for i, row in sorted_df.groupby("line_number"):
# print(f"Adding products in the row {i} to the detected planogram", row.cls.tolist())
products = row.cls.tolist()
col_len = min(len(products), n_cols)
print("col size: ", col_len)
print("row size: ", i - 1)
if n_rows <= (i - 1):
print("more rows than expected in the predictions")
break
master_table[int(i - 1), 0:col_len] = products[:col_len]
annotations = [
(int(k), int(v))
for k, v in list(
zip(row.cls.unique(), row.cls.value_counts().tolist())
)
]
master_annotations.append(annotations)
else:
master = cv2.imread("./sample_master_planogram.jpeg")
n_rows = 3
n_cols = 16
master_table = np.zeros((n_rows, n_cols)) + 101
master_annotations = [
[(32, 12), (8, 4)],
[(36, 1), (41, 6), (50, 4), (51, 3), (52, 2)],
[(23, 5), (24, 6), (54, 5)],
]
for i, row in enumerate(master_annotations):
idx = 0
for product, count in row:
master_table[i, idx : idx + count] = product
idx = idx + count
# Now do something with the image! For example, let's display it:
# st.image(opencv_image, channels="BGR")
# uploaded_img = '/content/drive/My Drive/0.CV/0.Planogram_Compliance/planogram_data/images/test/IMG_5718.jpg'
result_list = run(
weights="base_line_best_model_exp5.pt",
source="tmp/to_score_planogram_tmp.png",
imgsz=[640, 640],
conf_thres=0.6,
iou_thres=0.6,
)
bb_df = pd.DataFrame(
result_list[0][1].tolist(),
columns=["xmin", "ymin", "xmax", "ymax", "conf", "cls"],
)
sorted_df = do_sorting(bb_df)
non_null_product = 101
print("master size", n_rows, n_cols)
detected_table = np.zeros((n_rows, n_cols)) + non_null_product
for i, row in sorted_df.groupby("line_number"):
# print(f"Adding products in the row {i} to the detected planogram", row.cls.tolist())
products = row.cls.tolist()
col_len = min(len(products), n_cols)
print("col size: ", col_len)
print("row size: ", i - 1)
if n_rows <= (i - 1):
print("more rows than expected in the predictions")
break
detected_table[int(i - 1), 0:col_len] = products[:col_len]
# score = (master_table == detected_table).sum() / (master_table != non_null_product).sum()
correct_matches = (
np.ma.masked_equal(master_table, non_null_product) == detected_table
).sum()
total_products = (master_table != non_null_product).sum()
score = correct_matches / total_products
# if sorted_xml_df is not None:
# annotate_df = sorted_xml_df[["xmin","ymin", "xmax", "ymax", "line_number","cls"]].astype(int)
# else:
annotate_df = sorted_df[
["xmin", "ymin", "xmax", "ymax", "line_number", "cls"]
].astype(int)
mask = master_table != non_null_product
m_detected_table = np.ma.masked_array(master_table, mask=mask)
m_annotated_table = np.ma.masked_array(detected_table, mask=mask)
# wrong_indexes = np.ravel_multi_index(master_table*mask != detected_table*mask, master_table.shape)
wrong_indexes = np.where(master_table != detected_table)
correct_indexes = np.where(master_table == detected_table)
annotated_planogram = annotate_planogram_compliance(
uploaded_img, annotate_df, correct_indexes, wrong_indexes, target_names
)
st.title("Target Products")
st.write(json.dumps(target_names))
st.title("The master planogram annotation")
st.write(
"The annotations are based on the index of products from Target products list "
)
st.write(json.dumps(master_annotations))
# https://github.com/streamlit/streamlit/issues/888
st.image(
[master, annotated_planogram, result_list[0][0]],
width=512,
caption=[
"Master planogram",
"Planogram Compliance",
"Planogram Predictions",
],
channels="BGR",
)
# st.image([master, annotated_planogram], width=512, caption=["Master planogram", "Planogram Compliance"], channels="BGR")
st.title("Planogram Compiance score")
# st.write(f"{correct_matches} / {total_products}")
st.write(score)
|