diff --git a/modules/objdetect/src/face_recognize.cpp b/modules/objdetect/src/face_recognize.cpp index b024c787eb..639aa4b471 100644 --- a/modules/objdetect/src/face_recognize.cpp +++ b/modules/objdetect/src/face_recognize.cpp @@ -61,9 +61,10 @@ public: } double match(InputArray _face_feature1, InputArray _face_feature2, int dis_type) const override { - Mat face_feature1 = _face_feature1.getMat(), face_feature2 = _face_feature2.getMat(); - normalize(face_feature1, face_feature1); - normalize(face_feature2, face_feature2); + // match() is const and takes InputArray: never write through to the caller's buffers. + Mat face_feature1, face_feature2; + normalize(_face_feature1, face_feature1); + normalize(_face_feature2, face_feature2); if(dis_type == DisType::FR_COSINE){ return sum(face_feature1.mul(face_feature2))[0]; diff --git a/modules/objdetect/test/test_face.cpp b/modules/objdetect/test/test_face.cpp index e55401c061..34b80bd334 100644 --- a/modules/objdetect/test/test_face.cpp +++ b/modules/objdetect/test/test_face.cpp @@ -213,4 +213,25 @@ TEST(Objdetect_face_recognition, regression) } } +TEST(Objdetect_face_recognition, match_does_not_modify_input) +{ + std::string recog_model = findDataFile("dnn/onnx/models/face_recognizer_fast.onnx", false); + Ptr faceRecognizer = FaceRecognizerSF::create(recog_model, ""); + + // match() is declared const and takes both features as InputArray, so it must leave + // the caller's data untouched. + Mat feature1(1, 128, CV_32F), feature2(1, 128, CV_32F); + randu(feature1, Scalar::all(-10), Scalar::all(10)); + randu(feature2, Scalar::all(-10), Scalar::all(10)); + Mat expected1 = feature1.clone(), expected2 = feature2.clone(); + + faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_COSINE); + EXPECT_EQ(0, cvtest::norm(expected1, feature1, NORM_INF)) << "FR_COSINE changed input 1"; + EXPECT_EQ(0, cvtest::norm(expected2, feature2, NORM_INF)) << "FR_COSINE changed input 2"; + + faceRecognizer->match(feature1, feature2, FaceRecognizerSF::DisType::FR_NORM_L2); + EXPECT_EQ(0, cvtest::norm(expected1, feature1, NORM_INF)) << "FR_NORM_L2 changed input 1"; + EXPECT_EQ(0, cvtest::norm(expected2, feature2, NORM_INF)) << "FR_NORM_L2 changed input 2"; +} + }} // namespace