diff --git a/modules/features2d/src/draw.cpp b/modules/features2d/src/draw.cpp index ee0c4822ca..dc74ecb080 100644 --- a/modules/features2d/src/draw.cpp +++ b/modules/features2d/src/draw.cpp @@ -95,9 +95,9 @@ void drawKeypoints( InputArray image, const std::vector& keypoints, In if( !(flags & DrawMatchesFlags::DRAW_OVER_OUTIMG) ) { - if( image.type() == CV_8UC3 ) + if (image.type() == CV_8UC3 || image.type() == CV_8UC4) { - image.copyTo( outImage ); + image.copyTo(outImage); } else if( image.type() == CV_8UC1 ) { @@ -105,7 +105,7 @@ void drawKeypoints( InputArray image, const std::vector& keypoints, In } else { - CV_Error( Error::StsBadArg, "Incorrect type of input image.\n" ); + CV_Error( Error::StsBadArg, "Incorrect type of input image: " + typeToString(image.type()) ); } } @@ -122,6 +122,25 @@ void drawKeypoints( InputArray image, const std::vector& keypoints, In } } +static void _prepareImage(InputArray src, const Mat& dst) +{ + CV_CheckType(src.type(), src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4, "Unsupported source image"); + CV_CheckType(dst.type(), dst.type() == CV_8UC3 || dst.type() == CV_8UC4, "Unsupported destination image"); + const int src_cn = src.channels(); + const int dst_cn = dst.channels(); + + if (src_cn == dst_cn) + src.copyTo(dst); + else if (src_cn == 1) + cvtColor(src, dst, dst_cn == 3 ? COLOR_GRAY2BGR : COLOR_GRAY2BGRA); + else if (src_cn == 3 && dst_cn == 4) + cvtColor(src, dst, COLOR_BGR2BGRA); + else if (src_cn == 4 && dst_cn == 3) + cvtColor(src, dst, COLOR_BGRA2BGR); + else + CV_Error(Error::StsInternal, ""); +} + static void _prepareImgAndDrawKeypoints( InputArray img1, const std::vector& keypoints1, InputArray img2, const std::vector& keypoints2, InputOutputArray _outImg, Mat& outImg1, Mat& outImg2, @@ -140,21 +159,16 @@ static void _prepareImgAndDrawKeypoints( InputArray img1, const std::vector(11, 11) << + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 15, 54, 15, 1, 1, 1, 1, + 1, 1, 1, 76, 217, 217, 221, 81, 1, 1, 1, + 1, 1, 100, 224, 111, 57, 115, 225, 101, 1, 1, + 1, 44, 215, 100, 1, 1, 1, 101, 214, 44, 1, + 1, 54, 212, 57, 1, 1, 1, 55, 212, 55, 1, + 1, 40, 215, 104, 1, 1, 1, 105, 215, 40, 1, + 1, 1, 102, 221, 111, 55, 115, 222, 103, 1, 1, + 1, 1, 1, 76, 218, 217, 220, 81, 1, 1, 1, + 1, 1, 1, 1, 15, 55, 15, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + Mat res; + cvtColor(ref, res, (cn == 4) ? COLOR_GRAY2BGRA : COLOR_GRAY2BGR); + return res; +} + +typedef testing::TestWithParam Features2D_drawKeypoints; +TEST_P(Features2D_drawKeypoints, Accuracy) +{ + const int cn = CV_MAT_CN(GetParam()); + Mat inpImg(11, 11, GetParam(), Scalar(1, 1, 1, 255)), outImg; + + std::vector keypoints(1, KeyPoint(5, 5, 1)); + drawKeypoints(inpImg, keypoints, outImg, Scalar::all(255)); + ASSERT_EQ(outImg.channels(), (cn == 4) ? 4 : 3); + + Mat ref_ = getReference_DrawKeypoint(cn); + EXPECT_EQ(0, cv::norm(outImg, ref_, NORM_INF)); +} +INSTANTIATE_TEST_CASE_P(/**/, Features2D_drawKeypoints, Values(CV_8UC1, CV_8UC3, CV_8UC4)); + +typedef testing::TestWithParam > Features2D_drawMatches; +TEST_P(Features2D_drawMatches, Accuracy) +{ + Mat inpImg1(11, 11, get<0>(GetParam()), Scalar(1, 1, 1, 255)); + Mat inpImg2(11, 11, get<1>(GetParam()), Scalar(2, 2, 2, 255)), outImg2, outImg; + + std::vector keypoints(1, KeyPoint(5, 5, 1)); + + // Get outImg2 using drawKeypoints assuming that it works correctly (see the test above). + drawKeypoints(inpImg2, keypoints, outImg2, Scalar::all(255)); + ASSERT_EQ(outImg2.channels(), (inpImg2.channels() == 4) ? 4 : 3); + + // Merge both references. + const int cn = max(3, max(inpImg1.channels(), inpImg2.channels())); + if (cn == 4 && outImg2.channels() == 3) + cvtColor(outImg2, outImg2, COLOR_BGR2BGRA); + Mat ref_ = getReference_DrawKeypoint(cn); + Mat concattedRef; + hconcat(ref_, outImg2, concattedRef); + + std::vector matches; + drawMatches(inpImg1, keypoints, inpImg2, keypoints, matches, outImg, + Scalar::all(255), Scalar::all(255)); + ASSERT_EQ(outImg.channels(), cn); + + EXPECT_EQ(0, cv::norm(outImg, concattedRef, NORM_INF)); +} +INSTANTIATE_TEST_CASE_P(/**/, Features2D_drawMatches, Combine( + Values(CV_8UC1, CV_8UC3, CV_8UC4), + Values(CV_8UC1, CV_8UC3, CV_8UC4) +)); + +}} // namespace