# QRDet
**QRDet** is a robust **QR Detector** based on <a href="https://github.com/ultralytics/ultralytics" target="_blank">YOLOv8</a>.
**QRDet** will detect & 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 <a href="https://github.com/Eric-Canas/qreader" target="_blank">QReader</a>.
## Installation
To install **QRDet**, simply run:
```bash
pip install qrdet
```
## Usage
There is only one function you'll need to call to use **QRDet**, ``detect``:
```python
from qrdet import QRDetector
import cv2
detector = QRDetector(model_size='s')
image = cv2.imread(filename='resources/qreader_test_image.jpeg')
detections = detector.detect(image=image, is_bgr=True)
# Draw the detections
for detection in detections:
x1, y1, x2, y2 = detections['bbox_xyxy']
confidence = detections['confidence']
segmenation_xy = detections['quadrilateral_xy']
cv2.rectangle(image, (x1, y1), (x2, y2), color=(0, 255, 0), thickness=2)
cv2.putText(image, f'{confidence:.2f}', (x1, y1 - 10), fontFace=cv2.FONT_HERSHEY_SIMPLEX,
fontScale=1, color=(0, 255, 0), thickness=2)
# Save the results
cv2.imwrite(filename='resources/qreader_test_image_detections.jpeg', img=image)
```
<img alt="detections_output" title="detections_output" src="https://raw.githubusercontent.com/Eric-Canas/qrdet/main/resources/qreader_test_image_detections.jpeg" width="100%">
## API Reference
### QReader.detect(image, is_bgr = False, **kwargs)
- ``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.
- ``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`
- ``legacy``: **bool**. If sent as **kwarg**, will parse the output to make it identical to 1.x versions. Not Recommended. Default: False.
- **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.
| Key | Value Desc. | Value Type | Value Form |
|------------------|---------------------------------------------|----------------------------|-----------------------------|
| `confidence` | Detection confidence | `float` | `conf.` |
| `bbox_xyxy` | Bounding box | np.ndarray (**4**) | `[x1, y1, x2, y2]` |
| `cxcy` | Center of bounding box | tuple[`float`, `float`] | `(x, y)` |
| `wh` | Bounding box width and height | tuple[`float`, `float`] | `(w, h)` |
| `polygon_xy` | Precise polygon that segments the _QR_ | np.ndarray (**N**, **2**) | `[[x1, y1], [x2, y2], ...]` |
| `quad_xy` | Four corners polygon that segments the _QR_ | np.ndarray (**4**, **2**) | `[[x1, y1], ..., [x4, y4]]` |
| `padded_quad_xy` |`quad_xy` padded to fully cover `polygon_xy` | np.ndarray (**4**, **2**) | `[[x1, y1], ..., [x4, y4]]` |
| `image_shape` | Shape of the input image | tuple[`float`, `float`] | `(h, w)` |
> **NOTE:**
> - All `np.ndarray` values are of type `np.float32`
> - 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.].
> - `bbox_xyxy[n]` and `polygon_xy[n]` are clipped to `image_shape`. You can use them for indexing without further management
## Acknowledgements
This library is based on the following projects:
- <a href="https://github.com/ultralytics/ultralytics" target="_blank">YoloV8</a> model for **Object Segmentation**.
- <a href="https://github.com/Eric-Canas/quadrilateral-fitter" target="_blank">QuadrilateralFitter</a> for fitting 4 corners polygons from noisy **segmentation outputs**.