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;
i = 1;
-#if CV_SSE2
+#ifdef CV_SSE2
if( haveSSE )
{
__m128i z = _mm_setzero_si128();
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;
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);
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));
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 )
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_<uchar, SIMDBayerInterpolator_8u>(src, dst, code);
- else if( depth == CV_16U )
- Bayer2RGB_<ushort, SIMDBayerStubInterpolator_<ushort> >(src, dst, code);
+ if( code == CV_BayerBG2BGR || code == CV_BayerGB2BGR ||
+ code == CV_BayerRG2BGR || code == CV_BayerGR2BGR )
+ {
+ if( depth == CV_8U )
+ Bayer2RGB_<uchar, SIMDBayerInterpolator_8u>(src, dst_, code);
+ else if( depth == CV_16U )
+ Bayer2RGB_<ushort, SIMDBayerStubInterpolator_<ushort> >(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:
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);
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<uchar>(y, x) = src.at<Vec3b>(y, x)[1];
+ else if (x % 2)
+ bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[0];
+ else
+ bayer.at<uchar>(y, x) = src.at<Vec3b>(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<uchar>(y, x) = src.at<Vec3b>(y, x)[1];
+ else if (x % 2 == 0)
+ bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[0];
+ else
+ bayer.at<uchar>(y, x) = src.at<Vec3b>(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<uchar>(y, x) = src.at<Vec3b>(y, x)[1];
+ else if (x % 2 == 0)
+ bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[0];
+ else
+ bayer.at<uchar>(y, x) = src.at<Vec3b>(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<uchar>(y, x) = src.at<Vec3b>(y, x)[1];
+ else if (x % 2)
+ bayer.at<uchar>(y, x) = src.at<Vec3b>(y, x)[0];
+ else
+ bayer.at<uchar>(y, x) = src.at<Vec3b>(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;
+ }
+ }
+}