{"id":15293030,"url":"https://github.com/eric-canas/qrdet","last_synced_at":"2025-05-16T09:03:39.912Z","repository":{"id":64630741,"uuid":"577016570","full_name":"Eric-Canas/qrdet","owner":"Eric-Canas","description":"Robust QR Detector based on YOLOv8","archived":false,"fork":false,"pushed_at":"2025-02-23T08:37:53.000Z","size":45885,"stargazers_count":130,"open_issues_count":8,"forks_count":22,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-16T09:03:31.179Z","etag":null,"topics":["easy-to-use","object-detection","pip","pytorch","qr-detection","qrcode","yolov8"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Eric-Canas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"Eric-Canas"}},"created_at":"2022-12-11T18:05:49.000Z","updated_at":"2025-05-05T01:55:50.000Z","dependencies_parsed_at":"2024-03-01T09:39:13.226Z","dependency_job_id":"0ccb7064-239a-49d8-95e3-4e85f4933df8","html_url":"https://github.com/Eric-Canas/qrdet","commit_stats":{"total_commits":21,"total_committers":1,"mean_commits":21.0,"dds":0.0,"last_synced_commit":"1838ee2d239483ad4a1c15558e2301616d6ff707"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eric-Canas%2Fqrdet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eric-Canas%2Fqrdet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eric-Canas%2Fqrdet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Eric-Canas%2Fqrdet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Eric-Canas","download_url":"https://codeload.github.com/Eric-Canas/qrdet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254501554,"owners_count":22081528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["easy-to-use","object-detection","pip","pytorch","qr-detection","qrcode","yolov8"],"created_at":"2024-09-30T16:37:47.350Z","updated_at":"2025-05-16T09:03:39.880Z","avatar_url":"https://github.com/Eric-Canas.png","language":"Python","funding_links":["https://github.com/sponsors/Eric-Canas"],"categories":[],"sub_categories":[],"readme":"# QRDet\n**QRDet** is a robust **QR Detector** based on \u003ca href=\"https://github.com/ultralytics/ultralytics\" target=\"_blank\"\u003eYOLOv8\u003c/a\u003e.\n\n**QRDet** will detect \u0026 segment **QR** codes even in **difficult** positions or **tricky** images. If you are looking for a complete **QR Detection** + **Decoding** pipeline, take a look at \u003ca href=\"https://github.com/Eric-Canas/qreader\" target=\"_blank\"\u003eQReader\u003c/a\u003e.  \n\n## Installation\n\nTo install **QRDet**, simply run:\n\n```bash\npip install qrdet\n```\n\n## Usage\n\nThere is only one function you'll need to call to use **QRDet**, ``detect``:\n\n```python\n\nfrom qrdet import QRDetector\nimport cv2\n\ndetector = QRDetector(model_size='s')\nimage = cv2.imread(filename='resources/qreader_test_image.jpeg')\ndetections = detector.detect(image=image, is_bgr=True)\n\n# Draw the detections\nfor detection in detections:\n    x1, y1, x2, y2 = detection['bbox_xyxy']\n    confidence = detection['confidence']\n    cv2.rectangle(image, (x1, y1), (x2, y2), color=(0, 255, 0), thickness=2)\n    cv2.putText(image, f'{confidence:.2f}', (x1, y1 - 10), fontFace=cv2.FONT_HERSHEY_SIMPLEX,\n                fontScale=1, color=(0, 255, 0), thickness=2)\n# Save the results\ncv2.imwrite(filename='resources/qreader_test_image_detections.jpeg', img=image)\n```\n\n\u003cimg alt=\"detections_output\" title=\"detections_output\" src=\"https://raw.githubusercontent.com/Eric-Canas/qrdet/main/resources/qreader_test_image_detections.jpeg\" width=\"100%\"\u003e\n\n## API Reference\n\n### QRDetector(model_size = 's', conf_th = 0.5, nms_iou = 0.3, weights_folder = '\u003cqrdet_package\u003e/.model')\n\n- ``model_size``: **\"n\"|\"s\"|\"m\"|\"l\"**. Size of the model to load. Smaller models will be faster, while larger models will be more capable for difficult situations. Default: `'s'`.\n- ``conf_th``: **float**. Confidence threshold to consider that a detection is valid. Incresing this value will reduce _false positives_ while decreasing will reduce _false_negatives_. Default: `0.5`.\n- ``nms_iou``: **float**. _Intersection over Union_ (IoU) threshold for _Non-Maximum Suppression_ (NMS). NMS is a technique used to eliminate redundant bounding boxes for the same object. Increase this number if you find problems with duplicated detections. Default: `0.3`\n- ``weights_folder``: **str**. Folder where detection model will be downloaded. By default, it points out to an internal folder within the package, making sure that it gets correctly removed when uninstalling. You could need to change it when working in environments like [AWS Lambda](https://aws.amazon.com/es/pm/lambda/) where only [/tmp folder is writable](https://docs.aws.amazon.com/lambda/latest/api/API_EphemeralStorage.html), as issued in [#11](https://github.com/Eric-Canas/qrdet/issues/11). Default: `'\u003cqrdet_package\u003e/.model'`.\n\n### QRDetector.detect(image, is_bgr = False, **kwargs)\n\n- ``image``: **np.ndarray|'PIL.Image'|'torch.Tensor'|str**. `np.ndarray` of shape **(H, W, 3)**, `PIL.Image`, `Tensor` of shape **(1, 3, H, W)**, or `path`/`url` to the image to predict. `'screen'` for grabbing a screenshot.\n- ``is_bgr``: **bool**. If `True` the image is expected to be in **BGR**. Otherwise, it will be expected to be **RGB**. Only used when image is `np.ndarray` or `torch.tensor`. Default: `False`\n- ``legacy``: **bool**. If sent as **kwarg**, will parse the output to make it identical to 1.x versions. Not Recommended. Default: False.\n\n- **Returns**: **tuple[dict[str, np.ndarray|float|tuple[float|int, float|int]]]**. A tuple of dictionaries containing all the information of every detection. Contains the following keys.\n\n| Key              | Value Desc.                                 | Value Type                 | Value Form                  |\n|------------------|---------------------------------------------|----------------------------|-----------------------------|\n| `confidence`     | Detection confidence                        | `float`                    | `conf.`                     |\n| `bbox_xyxy`      | Bounding box                                | np.ndarray (**4**)         | `[x1, y1, x2, y2]`          |\n| `cxcy`           | Center of bounding box                      | tuple[`float`, `float`]    | `(x, y)`                    |\n| `wh`             | Bounding box width and height               | tuple[`float`, `float`]    | `(w, h)`                    |\n| `polygon_xy`     | Precise polygon that segments the _QR_      | np.ndarray (**N**, **2**)  | `[[x1, y1], [x2, y2], ...]` |\n| `quad_xy`        | Four corners polygon that segments the _QR_ | np.ndarray (**4**, **2**)  | `[[x1, y1], ..., [x4, y4]]` |\n| `padded_quad_xy` |`quad_xy` padded to fully cover `polygon_xy` | np.ndarray (**4**, **2**)  | `[[x1, y1], ..., [x4, y4]]` |\n| `image_shape`    | Shape of the input image                    | tuple[`float`, `float`]    | `(h, w)`                    |  \n\n\u003e **NOTE:**\n\u003e - All `np.ndarray` values are of type `np.float32` \n\u003e - All keys (except `confidence` and `image_shape`) have a normalized ('n') version. For example,`bbox_xyxy` represents the bbox of the QR in image coordinates [[0., im_w], [0., im_h]], while `bbox_xyxyn` contains the same bounding box in normalized coordinates [0., 1.].\n\u003e - `bbox_xyxy[n]` and `polygon_xy[n]` are clipped to `image_shape`. You can use them for indexing without further management\n\n## Acknowledgements\n\nThis library is based on the following projects:\n\n- \u003ca href=\"https://github.com/ultralytics/ultralytics\" target=\"_blank\"\u003eYoloV8\u003c/a\u003e model for **Object Segmentation**.\n- \u003ca href=\"https://github.com/Eric-Canas/quadrilateral-fitter\" target=\"_blank\"\u003eQuadrilateralFitter\u003c/a\u003e for fitting 4 corners polygons from noisy **segmentation outputs**.\n\n## Licensing clarifications\n\nThis model was trained from scratch with a dataset tagged by myself. However, the base `qrdet` model is [YoloV8 from Ultralytics](https://docs.ultralytics.com/es/models/yolov8/), and was trained with their [`.train()`](https://docs.ultralytics.com/es/modes/train/#multi-gpu-training) pipeline which has *AGPL-3.0* license. Be aware of that when using the library to met with that *AGPL-3.0* requirements when running inferences.\n\nOffering an alternative pure MIT Licensed backend is a work in progress. Just waiting for [segmentation support](https://github.com/MultimediaTechLab/YOLO/issues/153#issuecomment-2676675255) on [MultimediaTechLab YOLO version](https://github.com/MultimediaTechLab/YOLO). \nIf you wanna offer some contribution, please help them to develop the support for segmentation training and inference \u003c3.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feric-canas%2Fqrdet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feric-canas%2Fqrdet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feric-canas%2Fqrdet/lists"}