From 2759f026e9223c072f2f9634cbc2d1f66c6b2f66 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Mon, 8 Oct 2012 12:59:15 +0400 Subject: [PATCH] fixed Bug #2074 --- modules/imgproc/src/color.cpp | 55 ++++++++------- modules/imgproc/test/test_color.cpp | 129 +++++++++++++++++++++++++++++++++++- 2 files changed, 160 insertions(+), 24 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index bc01127..2b7da03 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2168,11 +2168,11 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) bayer += bstep*2; -#if CV_SSE2 +#ifdef CV_SSE2 bool haveSSE = cv::checkHardwareSupport(CV_CPU_SSE2); #define _mm_absdiff_epu16(a,b) _mm_adds_epu16(_mm_subs_epu16(a, b), _mm_subs_epu16(b, a)) #endif - + for( int y = 2; y < size.height - 4; y++ ) { uchar* dstrow = dst + dststep*y + 6; @@ -2188,7 +2188,7 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) i = 1; -#if CV_SSE2 +#ifdef CV_SSE2 if( haveSSE ) { __m128i z = _mm_setzero_si128(); @@ -2263,7 +2263,7 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) bool greenCell = greenCell0; i = 2; -#if CV_SSE2 +#ifdef CV_SSE2 int limit = !haveSSE ? N-2 : greenCell ? std::min(3, N-2) : 2; #else int limit = N - 2; @@ -2431,12 +2431,13 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) greenCell = !greenCell; } -#if CV_SSE2 +#ifdef CV_SSE2 if( !haveSSE ) break; __m128i emask = _mm_set1_epi32(0x0000ffff), omask = _mm_set1_epi32(0xffff0000), + smask = _mm_set1_epi16(0x7fff), // Get rid of sign bit in u16's z = _mm_setzero_si128(); __m128 _0_5 = _mm_set1_ps(0.5f); @@ -2658,6 +2659,11 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) x2 = _mm_merge_epi16(t0, x0); uchar R[8], G[8], B[8]; + + // Make sure there is no sign bit in the 16 bit values so they can saturate correctly + x1 = _mm_and_si128(x1, smask); + x2 = _mm_and_si128(x2, smask); + t1 = _mm_and_si128(t1, smask); _mm_storel_epi64(blueIdx ? (__m128i*)B : (__m128i*)R, _mm_packus_epi16(x1, z)); _mm_storel_epi64((__m128i*)G, _mm_packus_epi16(x2, z)); @@ -3548,7 +3554,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) if(dcn <= 0) dcn = 1; CV_Assert( scn == 1 && dcn == 1 ); - _dst.create(sz, depth); + _dst.create(sz, CV_MAKETYPE(depth, dcn)); dst = _dst.getMat(); if( depth == CV_8U ) @@ -3561,26 +3567,29 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) case CV_BayerBG2BGR: case CV_BayerGB2BGR: case CV_BayerRG2BGR: case CV_BayerGR2BGR: case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG: - if(dcn <= 0) dcn = 3; - CV_Assert( scn == 1 && dcn == 3 ); + { + if (dcn <= 0) + dcn = 3; + CV_Assert( scn == 1 && dcn == 3 ); - _dst.create(sz, CV_MAKETYPE(depth, dcn)); - dst = _dst.getMat(); + _dst.create(sz, CV_MAKE_TYPE(depth, dcn)); + Mat dst_ = _dst.getMat(); - if( code == CV_BayerBG2BGR || code == CV_BayerGB2BGR || - code == CV_BayerRG2BGR || code == CV_BayerGR2BGR ) - { - if( depth == CV_8U ) - Bayer2RGB_(src, dst, code); - else if( depth == CV_16U ) - Bayer2RGB_ >(src, dst, code); + if( code == CV_BayerBG2BGR || code == CV_BayerGB2BGR || + code == CV_BayerRG2BGR || code == CV_BayerGR2BGR ) + { + if( depth == CV_8U ) + Bayer2RGB_(src, dst_, code); + else if( depth == CV_16U ) + Bayer2RGB_ >(src, dst_, code); + else + CV_Error(CV_StsUnsupportedFormat, "Bayer->RGB demosaicing only supports 8u and 16u types"); + } else - CV_Error(CV_StsUnsupportedFormat, "Bayer->RGB demosaicing only supports 8u and 16u types"); - } - else - { - CV_Assert( depth == CV_8U ); - Bayer2RGB_VNG_8u(src, dst, code); + { + CV_Assert( depth == CV_8U ); + Bayer2RGB_VNG_8u(src, dst_, code); + } } break; case CV_YUV2BGR_NV21: case CV_YUV2RGB_NV21: case CV_YUV2BGR_NV12: case CV_YUV2RGB_NV12: diff --git a/modules/imgproc/test/test_color.cpp b/modules/imgproc/test/test_color.cpp index 1422f4c..9ad6cfa 100644 --- a/modules/imgproc/test/test_color.cpp +++ b/modules/imgproc/test/test_color.cpp @@ -1700,8 +1700,10 @@ TEST(Imgproc_ColorBayerVNG, regression) Mat gold = imread(string(ts.get_data_path()) + "/cvtcolor/bayerVNG_gold.png", CV_LOAD_IMAGE_UNCHANGED); Mat result; + CV_Assert(given.data != NULL); + cvtColor(given, result, CV_BayerBG2BGR_VNG, 3); - + EXPECT_EQ(gold.type(), result.type()); EXPECT_EQ(gold.cols, result.cols); EXPECT_EQ(gold.rows, result.rows); @@ -1711,3 +1713,128 @@ TEST(Imgproc_ColorBayerVNG, regression) EXPECT_EQ(0, countNonZero(diff.reshape(1) > 1)); } + +TEST(Imgproc_ColorBayerVNG_Strict, regression) +{ + cvtest::TS& ts = *cvtest::TS::ptr(); + const char pattern[][3] = { "bg", "gb", "rg", "gr" }; + const std::string image_name = "lena.png"; + const std::string parent_path = string(ts.get_data_path()) + "./cvtcolor_strict/"; + + Mat src, dst, bayer, reference; + std::string full_path = parent_path + image_name; + src = imread(full_path, CV_LOAD_IMAGE_UNCHANGED); + Size ssize = src.size(); + + if (src.data == NULL) + { + ts.set_failed_test_info(cvtest::TS::FAIL_MISSING_TEST_DATA); + ts.printf(cvtest::TS::SUMMARY, "No input image\n"); + return; + } + + int type = -1; + for (int i = 0; i < 4; ++i) + { + // creating Bayer pattern + bayer.create(ssize, CV_MAKETYPE(src.depth(), 1)); + + if (!strcmp(pattern[i], "bg")) + { + for (int y = 0; y < ssize.height; ++y) + for (int x = 0; x < ssize.width; ++x) + { + if ((x + y) % 2) + bayer.at(y, x) = src.at(y, x)[1]; + else if (x % 2) + bayer.at(y, x) = src.at(y, x)[0]; + else + bayer.at(y, x) = src.at(y, x)[2]; + } + type = CV_BayerBG2BGR_VNG; + } + else if (!strcmp(pattern[i], "gb")) + { + for (int y = 0; y < ssize.height; ++y) + for (int x = 0; x < ssize.width; ++x) + { + if ((x + y) % 2 == 0) + bayer.at(y, x) = src.at(y, x)[1]; + else if (x % 2 == 0) + bayer.at(y, x) = src.at(y, x)[0]; + else + bayer.at(y, x) = src.at(y, x)[2]; + } + type = CV_BayerGB2BGR_VNG; + } + else if (!strcmp(pattern[i], "rg")) + { + for (int y = 0; y < ssize.height; ++y) + for (int x = 0; x < ssize.width; ++x) + { + if ((x + y) % 2) + bayer.at(y, x) = src.at(y, x)[1]; + else if (x % 2 == 0) + bayer.at(y, x) = src.at(y, x)[0]; + else + bayer.at(y, x) = src.at(y, x)[2]; + } + type = CV_BayerRG2BGR_VNG; + } + else + { + for (int y = 0; y < ssize.height; ++y) + for (int x = 0; x < ssize.width; ++x) + { + if ((x + y) % 2 == 0) + bayer.at(y, x) = src.at(y, x)[1]; + else if (x % 2) + bayer.at(y, x) = src.at(y, x)[0]; + else + bayer.at(y, x) = src.at(y, x)[2]; + } + type = CV_BayerGR2BGR_VNG; + } + + // calculating a dst image + cvtColor(bayer, dst, type); + + // reading a reference image + full_path = parent_path + pattern[i] + image_name; + reference = imread(full_path, CV_LOAD_IMAGE_UNCHANGED); + if (reference.data == NULL) + { + imwrite(full_path, dst); + continue; + } + + if (reference.depth() != dst.depth() || reference.channels() != dst.channels() || + reference.size() != dst.size()) + { + ts.set_failed_test_info(cvtest::TS::FAIL_MISMATCH); + ts.printf(cvtest::TS::SUMMARY, "\nReference channels: %d\n" + "Actual channels: %d\n", reference.channels(), dst.channels()); + ts.printf(cvtest::TS::SUMMARY, "\nReference depth: %d\n" + "Actual depth: %d\n", reference.depth(), dst.depth()); + ts.printf(cvtest::TS::SUMMARY, "\nReference rows: %d\n" + "Actual rows: %d\n", reference.rows, dst.rows); + ts.printf(cvtest::TS::SUMMARY, "\nReference cols: %d\n" + "Actual cols: %d\n", reference.cols, dst.cols); + ts.set_gtest_status(); + + return; + } + + Mat diff; + absdiff(reference, dst, diff); + + int nonZero = countNonZero(diff.reshape(1) > 1); + if (nonZero != 0) + { + ts.set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY); + ts.printf(cvtest::TS::SUMMARY, "\nCount non zero in absdiff: %d\n", nonZero); + ts.set_gtest_status(); + return; + } + } +} -- 2.7.4