diff --git a/modules/dnn/src/graph_fusion_qdq.cpp b/modules/dnn/src/graph_fusion_qdq.cpp index 4ac53fdefa..7ef3da8113 100644 --- a/modules/dnn/src/graph_fusion_qdq.cpp +++ b/modules/dnn/src/graph_fusion_qdq.cpp @@ -486,7 +486,16 @@ struct ModelFusionQDQ symmetric_pads = false; } - if (all_wzp_zero && symmetric_pads) { + // Conv2Int8's VNNI kernel processes K0=8 output channels per + // SIMD iteration. When ngroups>1 and Kgngroups, 1); + const bool kernelSupportsGrouping = + conv->ngroups <= 1 || outChannelsPerGroup >= 8; + + if (all_wzp_zero && symmetric_pads && kernelSupportsGrouping) { Mat bias = Mat::zeros(1, outCn, CV_32S); bool biasOk = true; int dq_bias_idx = -1; diff --git a/modules/dnn/test/test_onnx_importer.cpp b/modules/dnn/test/test_onnx_importer.cpp index a6ee94f5b0..d43fe21717 100644 --- a/modules/dnn/test/test_onnx_importer.cpp +++ b/modules/dnn/test/test_onnx_importer.cpp @@ -2197,6 +2197,11 @@ TEST_P(Test_ONNX_layers, Quantized_Convolution) testONNXModels("quantized_conv_int8_weights", npy, 0.03, 0.5); testONNXModels("quantized_conv_per_channel_weights", npy, 0.06, 0.4); testONNXModels("quantized_conv_asymmetric_pads_int8_weights"); + // Regression test for https://github.com/opencv/opencv/issues/28798: + // depthwise QLinearConv (Kg=1 < kernel SIMD width K0=8) used to be + // miscompiled by Conv2Int8's VNNI kernel because multiple groups + // wrote into the same K0-wide output slot. + testONNXModels("quantized_depthwise_conv_int8_weights", npy, 0.06, 0.5); } { diff --git a/samples/dnn/face_detect.cpp b/samples/dnn/face_detect.cpp index 1f9e6a0ae0..b8c3b622e6 100644 --- a/samples/dnn/face_detect.cpp +++ b/samples/dnn/face_detect.cpp @@ -46,7 +46,7 @@ int main(int argc, char** argv) "{scale sc | 1.0 | Scale factor used to resize input video frames}" "{fd_model fd | face_detection_yunet_2023mar.onnx| Path to the model. Download yunet.onnx in https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet}" "{fr_model fr | face_recognition_sface_2021dec.onnx | Path to the face recognition model. Download the model at https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface}" - "{score_threshold | 0.9 | Filter out faces of score < score_threshold}" + "{score_threshold | 0.85 | Filter out faces of score < score_threshold}" "{nms_threshold | 0.3 | Suppress bounding boxes of iou >= nms_threshold}" "{top_k | 5000 | Keep top_k bounding boxes before NMS}" "{save s | false | Set true to save results. This flag is invalid when using camera}" diff --git a/samples/dnn/face_detect.py b/samples/dnn/face_detect.py index f07c5f3be1..95012fdbba 100644 --- a/samples/dnn/face_detect.py +++ b/samples/dnn/face_detect.py @@ -18,7 +18,7 @@ parser.add_argument('--video', '-v', type=str, help='Path to the input video.') parser.add_argument('--scale', '-sc', type=float, default=1.0, help='Scale factor used to resize input video frames.') parser.add_argument('--face_detection_model', '-fd', type=str, default='face_detection_yunet_2023mar.onnx', help='Path to the face detection model. Download the model at https://github.com/opencv/opencv_zoo/tree/master/models/face_detection_yunet') parser.add_argument('--face_recognition_model', '-fr', type=str, default='face_recognition_sface_2021dec.onnx', help='Path to the face recognition model. Download the model at https://github.com/opencv/opencv_zoo/tree/master/models/face_recognition_sface') -parser.add_argument('--score_threshold', type=float, default=0.9, help='Filtering out faces of score < score_threshold.') +parser.add_argument('--score_threshold', type=float, default=0.85, help='Filtering out faces of score < score_threshold.') parser.add_argument('--nms_threshold', type=float, default=0.3, help='Suppress bounding boxes of iou >= nms_threshold.') parser.add_argument('--top_k', type=int, default=5000, help='Keep top_k bounding boxes before NMS.') parser.add_argument('--save', '-s', type=str2bool, default=False, help='Set true to save results. This flag is invalid when using camera.')