abhishek-gola's picture
added lapsrn an macbeth onnx (#16)
1387a61
|
Raw History Blame Contribute Delete
4.58 kB
# Macbeth Chart Detector
Detects a Macbeth / ColorChecker Classic colour chart in a photograph and returns its bounding
box. This is the detection model used by OpenCV's `mcc` colour-correction code
(`objdetect`, `checker_detector.cpp`) to locate a chart before reading its patches.
The model is a Faster R-CNN with an Inception V2 backbone, trained as a single-class detector
with the TensorFlow Object Detection API. It was originally distributed as a frozen TensorFlow
graph (`frozen_inference_graph.pb`) and converted to ONNX for use with OpenCV's DNN module.
## Model Details
- **Architecture**: Faster R-CNN, Inception V2 backbone, one class (the chart)
- **Input**: `image_tensor:0`, **NHWC** `[1, H, W, 3]`, **raw uint8 RGB** (0-255, no scaling and
no mean subtraction). `H`/`W` are dynamic β€” feed the image at its own resolution. The graph
resizes internally (keep aspect ratio, min side 768, max side 1024), so do not pre-resize,
and do not use `blobFromImage`: that produces NCHW.
- **Outputs** (all four must be requested together):
- `detection_boxes:0` β€” `[1, 300, 4]`, normalized, **`[ymin, xmin, ymax, xmax]`** (y first)
- `detection_scores:0` β€” `[1, 300]`, descending
- `detection_classes:0` β€” `[1, 300]`, always `1.0` (single class, so it carries no information)
- `num_detections:0` β€” `[1]`
- **Framework**: ONNX (converted from the TensorFlow frozen graph via tf2onnx, opset 18)
- **Original weights**: [gursimarsingh/opencv_zoo @ `mcc_model`](https://github.com/gursimarsingh/opencv_zoo/tree/mcc_model/models/macbeth_chart_detector)
β€” `frozen_inference_graph.pb`, sha1 `fae7dbef14c4ae1fca76f3662220fbd460ed5ed6`
> **`num_detections` is not a detection count.** It reports the post-NMS slot count β€” 100 on the
> example image, where exactly one chart is present. Threshold on `detection_scores` instead;
> iterating `num_detections` yields 99 phantom boxes.
## Usage
### Python
```bash
python demo.py --model macbeth_chart_detector_2026sep.onnx --image example_outputs/input_image.png --output example_outputs/output_image.png --conf 0.3
```
On the provided `example_outputs/input_image.png` (900x463) it reports one detection:
```
macbeth_chart_detector 1 detections
0.582 x1=237 y1=79 x2=650 y2=368
```
`demo.py` requires OpenCV 5.1 or newer, for `cv.dnn.ENGINE_OPENCV`. On OpenCV 5.0 that constant
does not exist (it has `ENGINE_CLASSIC` / `ENGINE_NEW`); drop the second argument to
`readNetFromONNX` to use the default engine instead.
## Conversion
Exported from the frozen TensorFlow graph with tf2onnx (opset 18) via
[convert_to_onnx.py](./convert_to_onnx.py) β€” input `image_tensor:0`, outputs
`detection_boxes:0`, `detection_scores:0`, `detection_classes:0`, `num_detections:0`.
Requires `tensorflow`, `tf2onnx` and `onnx`.
```bash
python convert_to_onnx.py --pb frozen_inference_graph.pb
```
The graph needs no special handling: its weights are plain float32 (no `quantize_weights` /
`Dequantize` nodes) and all four detection heads are present in the frozen graph.
### Conversion accuracy
Verified against the original `.pb` under TensorFlow 2.15.1, feeding both the identical uint8
buffer:
| | top score | box |
|---|---|---|
| TensorFlow `.pb` | 0.582205 | `0.171078 0.263475 0.794357 0.721806` |
| ONNX (onnxruntime) | 0.582205 | `0.171078 0.263475 0.794356 0.721806` |
The conversion is faithful to within one float32 ULP.
## Known issue: OpenCV's DNN engine
The conversion is correct, but **OpenCV's built-in DNN engine cannot currently run this model.**
On OpenCV 5.0.0 it aborts before producing output:
```
net_impl2.cpp: (-215:Assertion failed) buf.shape() == m.shape() in function 'forwardGraph'
```
The same failure affects the other converted Faster R-CNN / Mask R-CNN models in this
repository, so it is a limitation of the engine's handling of these graphs rather than
something specific to this model. On builds where the graph does run, the score comes out
around 0.02 instead of 0.582, because `Resize` with
`coordinate_transformation_mode="tf_crop_and_resize"` and a dynamic ROI β€” the ROI-pooling step
of the second stage β€” is not evaluated correctly, so every region proposal is classified from
the wrong features.
Until that is fixed in `modules/dnn`, treat the ONNX file as correct (onnxruntime and
TensorFlow agree exactly) and the OpenCV-engine results as unreliable.
## License
See [LICENSE](./LICENSE) β€” Apache License 2.0, taken from the upstream
[opencv_zoo](https://github.com/gursimarsingh/opencv_zoo) repository that distributes the
original frozen graph.