This commit is contained in:
2025-09-27 22:57:59 +08:00
parent 8a458ff0a4
commit ed26244cdb
12585 changed files with 1914308 additions and 3474 deletions

View File

@@ -0,0 +1,2 @@

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,162 @@
import os
import tkinter as tk
from tkinter import filedialog, messagebox
from typing import Optional
import cv2
from PIL import Image, ImageTk
from ..config_loader import load_config
from ..io_utils import read_image_bgr
from ..pipeline import EAN13Recognizer
class TkEAN13App:
def __init__(self) -> None:
self.config = load_config()
self.root = tk.Tk()
self.root.title(self.config["app"]["ui"]["window_title"])
self.image_panel = tk.Label(self.root)
self.image_panel.pack(side=tk.TOP, padx=10, pady=10)
btn_frame = tk.Frame(self.root)
btn_frame.pack(side=tk.TOP, pady=5)
self.btn_open = tk.Button(btn_frame, text="选择图片", command=self.on_open)
self.btn_open.pack(side=tk.LEFT, padx=5)
self.btn_recognize = tk.Button(btn_frame, text="识别条码", command=self.on_recognize)
self.btn_recognize.pack(side=tk.LEFT, padx=5)
self.btn_camera = tk.Button(btn_frame, text="摄像头识别", command=self.on_camera)
self.btn_camera.pack(side=tk.LEFT, padx=5)
self.result_var = tk.StringVar(value="结果:-")
self.result_label = tk.Label(self.root, textvariable=self.result_var)
self.result_label.pack(side=tk.TOP, pady=5)
self.current_image_path: Optional[str] = None
self.recognizer = EAN13Recognizer()
self.cap = None
self.cam_running = False
def on_open(self) -> None:
path = filedialog.askopenfilename(
title="选择条码图片",
filetypes=[("Image Files", "*.png;*.jpg;*.jpeg;*.bmp;*.tif;*.tiff")],
)
if not path:
return
self.current_image_path = path
img_bgr = read_image_bgr(path)
if img_bgr is None:
messagebox.showerror("错误", "无法读取图片")
return
img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
# 限制显示尺寸
max_w = 800
h, w = img_rgb.shape[:2]
if w > max_w:
scale = max_w / float(w)
img_rgb = cv2.resize(img_rgb, (max_w, int(h * scale)), interpolation=cv2.INTER_AREA)
im = Image.fromarray(img_rgb)
self.tk_img = ImageTk.PhotoImage(im)
self.image_panel.configure(image=self.tk_img)
self.result_var.set("结果:-")
def on_recognize(self) -> None:
if not self.current_image_path:
messagebox.showinfo("提示", "请先选择图片")
return
result = self.recognizer.recognize_any_from_path(self.current_image_path)
ean13 = result.get("ean13", "")
if ean13:
self.result_var.set(f"结果EAN-13 {ean13}")
return
others = result.get("others", [])
if others:
first = others[0]
self.result_var.set(f"结果:{first.get('type')} {first.get('code')}")
return
self.result_var.set("结果:未识别")
def on_camera(self) -> None:
if self.cam_running:
# 若已在运行,视为停止
self.stop_camera()
return
cam_cfg = self.config.get("camera", {})
index = int(cam_cfg.get("index", 0))
self.cap = cv2.VideoCapture(index, cv2.CAP_DSHOW)
if not self.cap.isOpened():
messagebox.showerror("错误", f"无法打开摄像头 index={index}")
self.cap.release()
self.cap = None
return
# 设置分辨率(尽力设置)
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, float(cam_cfg.get("width", 1280)))
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, float(cam_cfg.get("height", 720)))
self.cam_running = True
self.result_var.set("结果:摄像头开启,正在识别...")
self.btn_camera.configure(text="停止摄像头")
self._camera_loop()
def stop_camera(self) -> None:
self.cam_running = False
try:
if self.cap is not None:
self.cap.release()
finally:
self.cap = None
self.btn_camera.configure(text="摄像头识别")
def _camera_loop(self) -> None:
if not self.cam_running or self.cap is None:
return
ret, frame = self.cap.read()
if not ret:
# 读取失败,稍后重试
self.root.after(int(self.config.get("camera", {}).get("interval_ms", 80)), self._camera_loop)
return
# 显示到面板
show = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
max_w = 800
h, w = show.shape[:2]
if w > max_w:
scale = max_w / float(w)
show = cv2.resize(show, (max_w, int(h * scale)), interpolation=cv2.INTER_AREA)
im = Image.fromarray(show)
self.tk_img = ImageTk.PhotoImage(im)
self.image_panel.configure(image=self.tk_img)
# 识别
result = self.recognizer.recognize_any_from_image(frame)
ean13 = result.get("ean13", "")
if ean13:
self.result_var.set(f"结果EAN-13 {ean13}")
self.stop_camera()
return
others = result.get("others", [])
if others:
first = others[0]
self.result_var.set(f"结果:{first.get('type')} {first.get('code')}")
self.stop_camera()
return
# 未识别,继续下一帧
self.root.after(int(self.config.get("camera", {}).get("interval_ms", 80)), self._camera_loop)
def run(self) -> None:
self.root.mainloop()
def main() -> None:
app = TkEAN13App()
app.run()
if __name__ == "__main__":
main()