|
|
import hashlib |
|
|
from types import SimpleNamespace |
|
|
import gradio as gr |
|
|
from PIL import Image |
|
|
from ultralytics import YOLO |
|
|
from ultralytics.utils.plotting import save_one_box |
|
|
import easyocr |
|
|
import zxingcpp |
|
|
import numpy as np |
|
|
|
|
|
from utils import custom_plot |
|
|
|
|
|
|
|
|
model = YOLO("YOLOV8s_Barcode_Detection.pt") |
|
|
reader = easyocr.Reader(['en']) |
|
|
key_hash = "6734e0268423441620ada6c66bf76c255500139962741833ab33185274b8a010" |
|
|
hash = lambda x: hashlib.sha256(x.encode()).hexdigest() |
|
|
|
|
|
|
|
|
def process_image(input_img, activation_key, progress=gr.Progress()): |
|
|
if input_img is None: |
|
|
return None, "請上傳圖片後再進行辨識。" |
|
|
if hash(activation_key) != key_hash: |
|
|
return None, "金鑰錯誤,請確認後再試一次。" |
|
|
|
|
|
|
|
|
result = model(input_img, imgsz=(1280))[0] |
|
|
|
|
|
crops = [] |
|
|
for d in result.boxes: |
|
|
crops.append(save_one_box( |
|
|
d.xyxy, |
|
|
result.orig_img.copy(), |
|
|
save=False, |
|
|
)) |
|
|
|
|
|
texts = [] |
|
|
|
|
|
for pr, crop in enumerate(crops): |
|
|
progress((pr+1) / len(crops), desc="辨識中") |
|
|
img = Image.fromarray(crop) |
|
|
res = zxingcpp.read_barcodes(img) |
|
|
|
|
|
if not res: |
|
|
|
|
|
for i in range(1, 8): |
|
|
res = zxingcpp.read_barcodes(img.rotate(i, resample=2)) |
|
|
if res: |
|
|
break |
|
|
res = zxingcpp.read_barcodes(img.rotate(-i, resample=2)) |
|
|
if res: |
|
|
break |
|
|
|
|
|
if not res: |
|
|
|
|
|
full_res = reader.readtext(crop, allowlist='-0123456789') |
|
|
res = sorted( |
|
|
[r for r in full_res if ( |
|
|
r[0][3][0] < (img.width/4) and r[0][3][1] > (img.height/3) and |
|
|
r[0][0][0] < (img.width/4) and r[0][0][1] > (img.height/2) |
|
|
)], |
|
|
key=lambda x: x[2], reverse=True, |
|
|
) |
|
|
if res: |
|
|
pred_text = res[0][1] |
|
|
|
|
|
cur_box = res[0] |
|
|
|
|
|
other_boxes = [r for r in full_res if r[1] != cur_box[1]] |
|
|
thrs = np.linalg.norm(img.size) / 25 |
|
|
while other_boxes: |
|
|
upper = np.linalg.norm(cur_box[0][1] - np.array([b[0][0] for b in other_boxes]), axis=1) |
|
|
lower = np.linalg.norm(cur_box[0][2] - np.array([b[0][3] for b in other_boxes]), axis=1) |
|
|
is_same = (upper < thrs) & (lower < thrs) |
|
|
rank = sorted( |
|
|
[(i, dist, s) for (i, dist), s in zip(enumerate(lower + upper), is_same) if s], |
|
|
key=lambda x: x[1] |
|
|
) |
|
|
if rank: |
|
|
cur_box = other_boxes[rank[0][0]] |
|
|
other_boxes = [r for r in other_boxes if r[1] != cur_box[1]] |
|
|
pred_text += cur_box[1] |
|
|
else: |
|
|
break |
|
|
|
|
|
if len(pred_text) != 15: |
|
|
res = [] |
|
|
res = [SimpleNamespace(text=pred_text)] if res else [] |
|
|
|
|
|
texts.append(res[0].text if res else None) |
|
|
|
|
|
output_text = '\n'.join([t for t in texts if isinstance(t, str)]) |
|
|
results_img = custom_plot( |
|
|
result, font_size=40, pil=True, |
|
|
barcode_texts=texts, |
|
|
) |
|
|
return results_img, output_text |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with gr.Blocks() as demo: |
|
|
gr.Markdown("# Barcode") |
|
|
gr.Markdown("請用下方 example 圖片測試條碼辨識功能,或上傳您自己的圖片。") |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(): |
|
|
input_view = gr.Image(type="pil", label="輸入圖片") |
|
|
activation_key = gr.Textbox(label="金鑰") |
|
|
btn = gr.Button("辨識", variant="primary") |
|
|
|
|
|
gr.Examples(examples=[["example1.jpeg", ""], ["example2.jpeg", ""]], inputs=input_view) |
|
|
with gr.Column(): |
|
|
output_view = gr.Image(type="pil", label="辨識結果") |
|
|
with gr.Column(): |
|
|
text_output = gr.Textbox(label="條碼內容") |
|
|
|
|
|
|
|
|
btn.click( |
|
|
fn=process_image, |
|
|
inputs=[input_view, activation_key], |
|
|
outputs=[output_view, text_output] |
|
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |
|
|
|