diff --git a/.gitignore b/.gitignore index 591b3f0..e94022a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ build /detection/model /api/db.sqlite3 /emblemscanner-release -/models +models diff --git a/emblem5/ai/common.py b/emblem5/ai/common.py index b4484b7..40690cb 100644 --- a/emblem5/ai/common.py +++ b/emblem5/ai/common.py @@ -174,7 +174,13 @@ def predict(model, transforms, image, ncells=1): r = predict_multi(model, transforms, [image], ncells) return r[0] -qr_detector = cv2.wechat_qrcode_WeChatQRCode() +_qr_detector = None + +def _get_qr_detector(): + global _qr_detector + if _qr_detector is None: + _qr_detector = cv2.wechat_qrcode_WeChatQRCode() + return _qr_detector def find_qr(img, scale=1.0): # Convert PIL Image to OpenCV format @@ -189,6 +195,7 @@ def find_qr(img, scale=1.0): new_size = orig_size resized_img = img img_cv = cv2.cvtColor(np.array(resized_img), cv2.COLOR_RGB2BGR) + qr_detector = _get_qr_detector() qr, corners = qr_detector.detectAndDecode(img_cv) if not qr: if scale > 0.05: diff --git a/requirements.txt b/requirements.txt index a31c158..b8de11d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,7 +19,6 @@ seaborn torch torchvision kornia -opencv-python opencv-contrib-python # RAG dependencies diff --git a/scripts/emcli b/scripts/emcli index 50bfa2a..8de6330 100755 --- a/scripts/emcli +++ b/scripts/emcli @@ -6,6 +6,7 @@ import json import requests import argparse import logging +import base64 from multiprocessing import Pool from tqdm import tqdm import oss2 @@ -352,6 +353,63 @@ class ListModelsCommand(SubCommand): print(f"Error listing models: {e}", file=sys.stderr) return 1 +class QrVerifyCommand(SubCommand): + name = "qr-verify" + want_argv = False + help = "Post image to qr-verify endpoint" + + def setup_args(self, parser): + parser.add_argument("--image", required=True, help="Path to image file") + parser.add_argument("--qrcode", required=True, help="QR code value") + + def do(self, args, argv): + if not os.path.exists(args.image): + print(f"Error: Image file not found: {args.image}", file=sys.stderr) + return 1 + + # Read image and convert to base64 data URL + with open(args.image, 'rb') as f: + image_data = f.read() + + # Determine MIME type from file extension + ext = os.path.splitext(args.image)[1].lower() + mime_types = { + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png': 'image/png', + '.gif': 'image/gif', + '.webp': 'image/webp', + } + mime_type = mime_types.get(ext, 'image/jpeg') + + # Encode to base64 data URL + base64_data = base64.b64encode(image_data).decode('utf-8') + data_url = f"data:{mime_type};base64,{base64_data}" + + # Prepare request data + data = { + 'qrcode': args.qrcode, + 'image_data_urls': [data_url], + } + + # Post to qr-verify endpoint + server = self.get_server() + url = f'{server}/api/v1/qr-verify/' + headers = { + 'Content-Type': 'application/json', + } + headers.update(self.make_headers()) + + try: + r = requests.post(url, headers=headers, json=data) + r.raise_for_status() + print(json.dumps(r.json(), indent=2)) + except Exception as e: + print(f"Error posting to qr-verify: {e}", file=sys.stderr) + if hasattr(e, 'response') and e.response is not None: + print(f"Response: {e.response.text}", file=sys.stderr) + return 1 + def global_args(parser): parser.add_argument("--env", "-E", help="Env", default="prod") parser.add_argument("-D", "--debug", action="store_true",