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 β€” 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

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 β€” input image_tensor:0, outputs detection_boxes:0, detection_scores:0, detection_classes:0, num_detections:0. Requires tensorflow, tf2onnx and onnx.

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 β€” Apache License 2.0, taken from the upstream opencv_zoo repository that distributes the original frozen graph.