From 7255ede3af7bf3dcc0db841103d1e2e3b3a790d7 Mon Sep 17 00:00:00 2001 From: Daniil Osokin Date: Sun, 24 Feb 2013 21:50:08 +0400 Subject: [PATCH 01/10] Added implementation for RGB to YUV420p color conversion --- .../imgproc/include/opencv2/imgproc/types_c.h | 16 +++- modules/imgproc/src/color.cpp | 79 ++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/types_c.h b/modules/imgproc/include/opencv2/imgproc/types_c.h index 0e4f0a244..ba25af9f9 100644 --- a/modules/imgproc/include/opencv2/imgproc/types_c.h +++ b/modules/imgproc/include/opencv2/imgproc/types_c.h @@ -309,8 +309,22 @@ enum // alpha premultiplication CV_RGBA2mRGBA = 125, CV_mRGBA2RGBA = 126, + + CV_RGB2YUV_I420 = 127, + CV_BGR2YUV_I420 = 128, + CV_RGB2YUV_IYUV = CV_RGB2YUV_I420, + CV_BGR2YUV_IYUV = CV_BGR2YUV_I420, - CV_COLORCVT_MAX = 127 + CV_RGBA2YUV_I420 = 129, + CV_BGRA2YUV_I420 = 130, + CV_RGBA2YUV_IYUV = CV_RGBA2YUV_I420, + CV_BGRA2YUV_IYUV = CV_BGRA2YUV_I420, + CV_RGB2YUV_YV12 = 131, + CV_BGR2YUV_YV12 = 132, + CV_RGBA2YUV_YV12 = 133, + CV_BGRA2YUV_YV12 = 134, + + CV_COLORCVT_MAX = 135 }; diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index e85acea3f..82c219568 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -3076,6 +3076,58 @@ inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const ucha converter(BlockedRange(0, _dst.rows/2)); } +///////////////////////////////////// RGB -> YUV420p ///////////////////////////////////// + +template +static void cvtRGBtoYUV420p(const Mat& src, Mat& dst) +{ + //const float coeffs[] = { 0.257f, 0.504f, 0.098f, + // -0.148f, -0.291f, 0.439f, + // -0.368f, -0.071f }; + const int coeffs[] = { 269484, 528482, 102760, + -155188, -305135, 460324, + -385875, -74448 }; + + const int w = src.cols; + const int h = src.rows; + + const int cn = src.channels(); + for( int i = 0; i < h / 2; i++ ) + { + const uchar* row0 = src.ptr(2*i); + const uchar* row1 = src.ptr(2*i + 1); + + uchar* y = dst.ptr(2*i); + uchar* u = dst.ptr(h + i/2) + (i % 2) * (w/2); + uchar* v = dst.ptr(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2); + if( uIdx == 2 ) std::swap(u, v); + + for( int j = 0, k = 0; j < w * cn; j += 2*cn, k++ ) + { + int r00 = row0[2-bIdx + j]; int g00 = row0[1 + j]; int b00 = row0[bIdx + j]; + int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j]; + int r10 = row1[2-bIdx + j]; int g10 = row1[1 + j]; int b10 = row1[bIdx + j]; + int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j]; + + int y00 = coeffs[0]*r00 + coeffs[1]*g00 + coeffs[2]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); + int y01 = coeffs[0]*r01 + coeffs[1]*g01 + coeffs[2]*b01 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); + int y10 = coeffs[0]*r10 + coeffs[1]*g10 + coeffs[2]*b10 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); + int y11 = coeffs[0]*r11 + coeffs[1]*g11 + coeffs[2]*b11 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); + + y[2*k + 0] = saturate_cast(y00 >> ITUR_BT_601_SHIFT); + y[2*k + 1] = saturate_cast(y01 >> ITUR_BT_601_SHIFT); + y[2*k + dst.step + 0] = saturate_cast(y10 >> ITUR_BT_601_SHIFT); + y[2*k + dst.step + 1] = saturate_cast(y11 >> ITUR_BT_601_SHIFT); + + int u00 = coeffs[3]*r00 + coeffs[4]*g00 + coeffs[5]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (128 << ITUR_BT_601_SHIFT); + int v00 = coeffs[5]*r00 + coeffs[6]*g00 + coeffs[7]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (128 << ITUR_BT_601_SHIFT); + + u[k] = saturate_cast(u00 >> ITUR_BT_601_SHIFT); + v[k] = saturate_cast(v00 >> ITUR_BT_601_SHIFT); + } + } +} + ///////////////////////////////////// YUV422 -> RGB ///////////////////////////////////// template @@ -3713,6 +3765,31 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) src(Range(0, dstSz.height), Range::all()).copyTo(dst); } break; + case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12: + case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV: + { + if (dcn <= 0) dcn = 1; + const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2; + const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2; + + CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U ); + CV_Assert( dcn == 1 ); + CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0 ); + + Size dstSz(sz.width, sz.height / 2 * 3); + _dst.create(dstSz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + + switch(bIdx + uIdx*10) + { + case 10: cvtRGBtoYUV420p<0, 1>(src, dst); break; + case 12: cvtRGBtoYUV420p<2, 1>(src, dst); break; + case 20: cvtRGBtoYUV420p<0, 2>(src, dst); break; + case 22: cvtRGBtoYUV420p<2, 2>(src, dst); break; + default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break; + }; + } + break; case CV_YUV2RGB_UYVY: case CV_YUV2BGR_UYVY: case CV_YUV2RGBA_UYVY: case CV_YUV2BGRA_UYVY: case CV_YUV2RGB_YUY2: case CV_YUV2BGR_YUY2: case CV_YUV2RGB_YVYU: case CV_YUV2BGR_YVYU: case CV_YUV2RGBA_YUY2: case CV_YUV2BGRA_YUY2: case CV_YUV2RGBA_YVYU: case CV_YUV2BGRA_YVYU: @@ -3795,7 +3872,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) CV_Error( CV_StsBadArg, "Unsupported image depth" ); } } - break; + break; default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); } From d8f538d67becd29df4f6953a5d7bb40f5a0fb1f2 Mon Sep 17 00:00:00 2001 From: Daniil Osokin Date: Sun, 24 Feb 2013 23:52:06 +0400 Subject: [PATCH 02/10] Added tests for RGB to YUV420p color conversion --- modules/imgproc/perf/perf_cvt_color.cpp | 32 +++ modules/imgproc/test/test_cvtyuv.cpp | 292 +++++++++++++++++++++--- 2 files changed, 290 insertions(+), 34 deletions(-) diff --git a/modules/imgproc/perf/perf_cvt_color.cpp b/modules/imgproc/perf/perf_cvt_color.cpp index 3919539ef..6f09163f9 100644 --- a/modules/imgproc/perf/perf_cvt_color.cpp +++ b/modules/imgproc/perf/perf_cvt_color.cpp @@ -115,6 +115,9 @@ CV_ENUM(CvtMode2, CV_YUV2BGR_NV12, CV_YUV2BGRA_NV12, CV_YUV2RGB_NV12, CV_YUV2RGB COLOR_YUV2GRAY_420, CV_YUV2RGB_UYVY, CV_YUV2BGR_UYVY, CV_YUV2RGBA_UYVY, CV_YUV2BGRA_UYVY, CV_YUV2RGB_YUY2, CV_YUV2BGR_YUY2, CV_YUV2RGB_YVYU, CV_YUV2BGR_YVYU, CV_YUV2RGBA_YUY2, CV_YUV2BGRA_YUY2, CV_YUV2RGBA_YVYU, CV_YUV2BGRA_YVYU) +CV_ENUM(CvtMode3, CV_RGB2YUV_IYUV, CV_BGR2YUV_IYUV, CV_RGBA2YUV_IYUV, CV_BGRA2YUV_IYUV, + CV_RGB2YUV_YV12, CV_BGR2YUV_YV12, CV_RGBA2YUV_YV12, CV_BGRA2YUV_YV12) + struct ChPair { ChPair(int _scn, int _dcn): scn(_scn), dcn(_dcn) {} @@ -162,6 +165,8 @@ ChPair getConversionInfo(int cvtMode) case CV_BGR5652BGRA: case CV_BGR5652RGBA: return ChPair(2,4); case CV_BGR2GRAY: case CV_RGB2GRAY: + case CV_RGB2YUV_IYUV: case CV_RGB2YUV_YV12: + case CV_BGR2YUV_IYUV: case CV_BGR2YUV_YV12: return ChPair(3,1); case CV_BGR2BGR555: case CV_BGR2BGR565: case CV_RGB2BGR555: case CV_RGB2BGR565: @@ -204,6 +209,8 @@ ChPair getConversionInfo(int cvtMode) case CX_YUV2BGRA: case CX_YUV2RGBA: return ChPair(3,4); case CV_BGRA2GRAY: case CV_RGBA2GRAY: + case CV_RGBA2YUV_IYUV: case CV_RGBA2YUV_YV12: + case CV_BGRA2YUV_IYUV: case CV_BGRA2YUV_YV12: return ChPair(4,1); case CV_BGRA2BGR555: case CV_BGRA2BGR565: case CV_RGBA2BGR555: case CV_RGBA2BGR565: @@ -306,3 +313,28 @@ PERF_TEST_P(Size_CvtMode2, cvtColorYUV420, SANITY_CHECK(dst, 1); } + +typedef std::tr1::tuple Size_CvtMode3_t; +typedef perf::TestBaseWithParam Size_CvtMode3; + +PERF_TEST_P(Size_CvtMode3, cvtColorRGB2YUV420p, + testing::Combine( + testing::Values(szVGA, sz720p, sz1080p, Size(130, 60)), + testing::ValuesIn(CvtMode3::all()) + ) + ) +{ + Size sz = get<0>(GetParam()); + int mode = get<1>(GetParam()); + ChPair ch = getConversionInfo(mode); + + Mat src(sz, CV_8UC(ch.scn)); + Mat dst(sz.height + sz.height / 2, sz.width, CV_8UC(ch.dcn)); + + declare.time(100); + declare.in(src, WARMUP_RNG).out(dst); + + TEST_CYCLE() cvtColor(src, dst, mode, ch.dcn); + + SANITY_CHECK(dst, 1); +} diff --git a/modules/imgproc/test/test_cvtyuv.cpp b/modules/imgproc/test/test_cvtyuv.cpp index 1a2ab018b..61bc9bd8d 100644 --- a/modules/imgproc/test/test_cvtyuv.cpp +++ b/modules/imgproc/test/test_cvtyuv.cpp @@ -30,6 +30,16 @@ public: static YUVreader* getReader(int code); }; +class RGBreader +{ +public: + virtual ~RGBreader() {} + virtual RGB read(const Mat& rgb, int row, int col) = 0; + virtual int channels() = 0; + + static RGBreader* getReader(int code); +}; + class RGBwriter { public: @@ -56,6 +66,21 @@ public: static GRAYwriter* getWriter(int code); }; +class YUVwriter +{ +public: + virtual ~YUVwriter() {} + + virtual void write(Mat& yuv, int row, int col, const YUV& val) = 0; + virtual int channels() = 0; + virtual Size size(Size imgSize) = 0; + + virtual bool requiresEvenHeight() { return true; } + virtual bool requiresEvenWidth() { return true; } + + static YUVwriter* getWriter(int code); +}; + class RGB888Writer : public RGBwriter { void write(Mat& rgb, int row, int col, const RGB& val) @@ -99,6 +124,42 @@ class BGRA8888Writer : public RGBwriter int channels() { return 4; } }; +class YUV420pWriter: public YUVwriter +{ + int channels() { return 1; } + Size size(Size imgSize) { return Size(imgSize.width, imgSize.height + imgSize.height/2); } +}; + +class YV12Writer: public YUV420pWriter +{ + void write(Mat& yuv, int row, int col, const YUV& val) + { + int h = yuv.rows * 2 / 3; + + yuv.ptr(row)[col] = val[0]; + if( row % 2 == 0 && col % 2 == 0 ) + { + yuv.ptr(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)] = val[2]; + yuv.ptr(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)] = val[1]; + } + } +}; + +class I420Writer: public YUV420pWriter +{ + void write(Mat& yuv, int row, int col, const YUV& val) + { + int h = yuv.rows * 2 / 3; + + yuv.ptr(row)[col] = val[0]; + if( row % 2 == 0 && col % 2 == 0 ) + { + yuv.ptr(h + row/4)[col/2 + ((row/2) % 2) * (yuv.cols/2)] = val[1]; + yuv.ptr(h + (row/2 + h/2)/2)[col/2 + ((row/2 + h/2) % 2) * (yuv.cols/2)] = val[2]; + } + } +}; + class YUV420Reader: public YUVreader { int channels() { return 1; } @@ -212,6 +273,49 @@ class YUV888Reader : public YUVreader bool requiresEvenWidth() { return false; } }; +class RGB888Reader : public RGBreader +{ + RGB read(const Mat& rgb, int row, int col) + { + return rgb.at(row, col); + } + + int channels() { return 3; } +}; + +class BGR888Reader : public RGBreader +{ + RGB read(const Mat& rgb, int row, int col) + { + RGB tmp = rgb.at(row, col); + return RGB(tmp[2], tmp[1], tmp[0]); + } + + int channels() { return 3; } +}; + +class RGBA8888Reader : public RGBreader +{ + RGB read(const Mat& rgb, int row, int col) + { + Vec4b rgba = rgb.at(row, col); + return RGB(rgba[0], rgba[1], rgba[2]); + } + + int channels() { return 4; } +}; + +class BGRA8888Reader : public RGBreader +{ + RGB read(const Mat& rgb, int row, int col) + { + Vec4b rgba = rgb.at(row, col); + return RGB(rgba[2], rgba[1], rgba[0]); + } + + int channels() { return 4; } +}; + class YUV2RGB_Converter { public: @@ -237,6 +341,23 @@ public: } }; +class RGB2YUV_Converter +{ +public: + YUV convert(RGB rgb) + { + int r = rgb[0]; + int g = rgb[1]; + int b = rgb[2]; + + uchar y = saturate_cast((int)( 0.257f*r + 0.504f*g + 0.098f*b + 0.5f) + 16); + uchar u = saturate_cast((int)(-0.148f*r - 0.291f*g + 0.439f*b + 0.5f) + 128); + uchar v = saturate_cast((int)( 0.439f*r - 0.368f*g - 0.071f*b + 0.5f) + 128); + + return YUV(y, u, v); + } +}; + YUVreader* YUVreader::getReader(int code) { switch(code) @@ -295,6 +416,27 @@ YUVreader* YUVreader::getReader(int code) } } +RGBreader* RGBreader::getReader(int code) +{ + switch(code) + { + case CV_RGB2YUV_YV12: + case CV_RGB2YUV_I420: + return new RGB888Reader(); + case CV_BGR2YUV_YV12: + case CV_BGR2YUV_I420: + return new BGR888Reader(); + case CV_RGBA2YUV_I420: + case CV_RGBA2YUV_YV12: + return new RGBA8888Reader(); + case CV_BGRA2YUV_YV12: + case CV_BGRA2YUV_I420: + return new BGRA8888Reader(); + default: + return 0; + }; +} + RGBwriter* RGBwriter::getWriter(int code) { switch(code) @@ -355,6 +497,25 @@ GRAYwriter* GRAYwriter::getWriter(int code) } } +YUVwriter* YUVwriter::getWriter(int code) +{ + switch(code) + { + case CV_RGB2YUV_YV12: + case CV_BGR2YUV_YV12: + case CV_RGBA2YUV_YV12: + case CV_BGRA2YUV_YV12: + return new YV12Writer(); + case CV_RGB2YUV_I420: + case CV_BGR2YUV_I420: + case CV_RGBA2YUV_I420: + case CV_BGRA2YUV_I420: + return new I420Writer(); + default: + return 0; + }; +} + template void referenceYUV2RGB(const Mat& yuv, Mat& rgb, YUVreader* yuvReader, RGBwriter* rgbWriter) { @@ -375,6 +536,64 @@ void referenceYUV2GRAY(const Mat& yuv, Mat& rgb, YUVreader* yuvReader, GRAYwrite grayWriter->write(rgb, row, col, cvt.convert(yuvReader->read(yuv, row, col))); } +template +void referenceRGB2YUV(const Mat& rgb, Mat& yuv, RGBreader* rgbReader, YUVwriter* yuvWriter) +{ + convertor cvt; + + for(int row = 0; row < rgb.rows; ++row) + for(int col = 0; col < rgb.cols; ++col) + yuvWriter->write(yuv, row, col, cvt.convert(rgbReader->read(rgb, row, col))); +} + +struct ConversionYUV +{ + ConversionYUV( const int code ) + { + yuvReader_ = YUVreader :: getReader(code); + yuvWriter_ = YUVwriter :: getWriter(code); + rgbReader_ = RGBreader :: getReader(code); + rgbWriter_ = RGBwriter :: getWriter(code); + grayWriter_ = GRAYwriter:: getWriter(code); + } + + int getDcn() + { + return (rgbWriter_ != 0) ? rgbWriter_->channels() : ((grayWriter_ != 0) ? grayWriter_->channels() : yuvWriter_->channels()); + } + + int getScn() + { + return (yuvReader_ != 0) ? yuvReader_->channels() : rgbReader_->channels(); + } + + Size getSrcSize( const Size& imgSize ) + { + return (yuvReader_ != 0) ? yuvReader_->size(imgSize) : imgSize; + } + + Size getDstSize( const Size& imgSize ) + { + return (yuvWriter_ != 0) ? yuvWriter_->size(imgSize) : imgSize; + } + + bool requiresEvenHeight() + { + return (yuvReader_ != 0) ? yuvReader_->requiresEvenHeight() : ((yuvWriter_ != 0) ? yuvWriter_->requiresEvenHeight() : false); + } + + bool requiresEvenWidth() + { + return (yuvReader_ != 0) ? yuvReader_->requiresEvenWidth() : ((yuvWriter_ != 0) ? yuvWriter_->requiresEvenWidth() : false); + } + + YUVreader* yuvReader_; + YUVwriter* yuvWriter_; + RGBreader* rgbReader_; + RGBwriter* rgbWriter_; + GRAYwriter* grayWriter_; +}; + CV_ENUM(YUVCVTS, CV_YUV2RGB_NV12, CV_YUV2BGR_NV12, CV_YUV2RGB_NV21, CV_YUV2BGR_NV21, CV_YUV2RGBA_NV12, CV_YUV2BGRA_NV12, CV_YUV2RGBA_NV21, CV_YUV2BGRA_NV21, CV_YUV2RGB_YV12, CV_YUV2BGR_YV12, CV_YUV2RGB_IYUV, CV_YUV2BGR_IYUV, @@ -383,7 +602,8 @@ CV_ENUM(YUVCVTS, CV_YUV2RGB_NV12, CV_YUV2BGR_NV12, CV_YUV2RGB_NV21, CV_YUV2BGR_N CV_YUV2RGB_YUY2, CV_YUV2BGR_YUY2, CV_YUV2RGB_YVYU, CV_YUV2BGR_YVYU, CV_YUV2RGBA_YUY2, CV_YUV2BGRA_YUY2, CV_YUV2RGBA_YVYU, CV_YUV2BGRA_YVYU, CV_YUV2GRAY_420, CV_YUV2GRAY_UYVY, CV_YUV2GRAY_YUY2, - CV_YUV2BGR, CV_YUV2RGB); + CV_YUV2BGR, CV_YUV2RGB, CV_RGB2YUV_YV12, CV_BGR2YUV_YV12, CV_RGBA2YUV_YV12, + CV_BGRA2YUV_YV12, CV_RGB2YUV_I420, CV_BGR2YUV_I420, CV_RGBA2YUV_I420, CV_BGRA2YUV_I420); typedef ::testing::TestWithParam Imgproc_ColorYUV; @@ -392,31 +612,32 @@ TEST_P(Imgproc_ColorYUV, accuracy) int code = GetParam(); RNG& random = theRNG(); - YUVreader* yuvReader = YUVreader::getReader(code); - RGBwriter* rgbWriter = RGBwriter::getWriter(code); - GRAYwriter* grayWriter = GRAYwriter::getWriter(code); - - int dcn = (rgbWriter == 0) ? grayWriter->channels() : rgbWriter->channels(); + ConversionYUV cvt(code); + const int scn = cvt.getScn(); + const int dcn = cvt.getDcn(); for(int iter = 0; iter < 30; ++iter) { Size sz(random.uniform(1, 641), random.uniform(1, 481)); - if(yuvReader->requiresEvenWidth()) sz.width += sz.width % 2; - if(yuvReader->requiresEvenHeight()) sz.height += sz.height % 2; + if(cvt.requiresEvenWidth()) sz.width += sz.width % 2; + if(cvt.requiresEvenHeight()) sz.height += sz.height % 2; - Size ysz = yuvReader->size(sz); - Mat src = Mat(ysz.height, ysz.width * yuvReader->channels(), CV_8UC1).reshape(yuvReader->channels()); + Size srcSize = cvt.getSrcSize(sz); + Mat src = Mat(srcSize.height, srcSize.width * scn, CV_8UC1).reshape(scn); - Mat dst = Mat(sz.height, sz.width * dcn, CV_8UC1).reshape(dcn); - Mat gold(sz, CV_8UC(dcn)); + Size dstSize = cvt.getDstSize(sz); + Mat dst = Mat(dstSize.height, dstSize.width * dcn, CV_8UC1).reshape(dcn); + Mat gold(dstSize, CV_8UC(dcn)); random.fill(src, RNG::UNIFORM, 0, 256); - if(rgbWriter) - referenceYUV2RGB(src, gold, yuvReader, rgbWriter); - else - referenceYUV2GRAY(src, gold, yuvReader, grayWriter); + if(cvt.rgbWriter_) + referenceYUV2RGB (src, gold, cvt.yuvReader_, cvt.rgbWriter_); + else if(cvt.grayWriter_) + referenceYUV2GRAY(src, gold, cvt.yuvReader_, cvt.grayWriter_); + else if(cvt.yuvWriter_) + referenceRGB2YUV (src, gold, cvt.rgbReader_, cvt.yuvWriter_); cv::cvtColor(src, dst, code, -1); @@ -429,40 +650,41 @@ TEST_P(Imgproc_ColorYUV, roi_accuracy) int code = GetParam(); RNG& random = theRNG(); - YUVreader* yuvReader = YUVreader::getReader(code); - RGBwriter* rgbWriter = RGBwriter::getWriter(code); - GRAYwriter* grayWriter = GRAYwriter::getWriter(code); - - int dcn = (rgbWriter == 0) ? grayWriter->channels() : rgbWriter->channels(); + ConversionYUV cvt(code); + const int scn = cvt.getScn(); + const int dcn = cvt.getDcn(); for(int iter = 0; iter < 30; ++iter) { Size sz(random.uniform(1, 641), random.uniform(1, 481)); - if(yuvReader->requiresEvenWidth()) sz.width += sz.width % 2; - if(yuvReader->requiresEvenHeight()) sz.height += sz.height % 2; + if(cvt.requiresEvenWidth()) sz.width += sz.width % 2; + if(cvt.requiresEvenHeight()) sz.height += sz.height % 2; int roi_offset_top = random.uniform(0, 6); int roi_offset_bottom = random.uniform(0, 6); int roi_offset_left = random.uniform(0, 6); int roi_offset_right = random.uniform(0, 6); - Size ysz = yuvReader->size(sz); + Size srcSize = cvt.getSrcSize(sz); + Mat src_full(srcSize.height + roi_offset_top + roi_offset_bottom, srcSize.width + roi_offset_left + roi_offset_right, CV_8UC(scn)); - Mat src_full(ysz.height + roi_offset_top + roi_offset_bottom, ysz.width + roi_offset_left + roi_offset_right, CV_8UC(yuvReader->channels())); - Mat dst_full(sz.height + roi_offset_left + roi_offset_right, sz.width + roi_offset_top + roi_offset_bottom, CV_8UC(dcn), Scalar::all(0)); + Size dstSize = cvt.getDstSize(sz); + Mat dst_full(dstSize.height + roi_offset_left + roi_offset_right, dstSize.width + roi_offset_top + roi_offset_bottom, CV_8UC(dcn), Scalar::all(0)); Mat gold_full(dst_full.size(), CV_8UC(dcn), Scalar::all(0)); random.fill(src_full, RNG::UNIFORM, 0, 256); - Mat src = src_full(Range(roi_offset_top, roi_offset_top + ysz.height), Range(roi_offset_left, roi_offset_left + ysz.width)); - Mat dst = dst_full(Range(roi_offset_left, roi_offset_left + sz.height), Range(roi_offset_top, roi_offset_top + sz.width)); - Mat gold = gold_full(Range(roi_offset_left, roi_offset_left + sz.height), Range(roi_offset_top, roi_offset_top + sz.width)); + Mat src = src_full(Range(roi_offset_top, roi_offset_top + srcSize.height), Range(roi_offset_left, roi_offset_left + srcSize.width)); + Mat dst = dst_full(Range(roi_offset_left, roi_offset_left + dstSize.height), Range(roi_offset_top, roi_offset_top + dstSize.width)); + Mat gold = gold_full(Range(roi_offset_left, roi_offset_left + dstSize.height), Range(roi_offset_top, roi_offset_top + dstSize.width)); - if(rgbWriter) - referenceYUV2RGB(src, gold, yuvReader, rgbWriter); - else - referenceYUV2GRAY(src, gold, yuvReader, grayWriter); + if(cvt.rgbWriter_) + referenceYUV2RGB (src, gold, cvt.yuvReader_, cvt.rgbWriter_); + else if(cvt.grayWriter_) + referenceYUV2GRAY(src, gold, cvt.yuvReader_, cvt.grayWriter_); + else if(cvt.yuvWriter_) + referenceRGB2YUV (src, gold, cvt.rgbReader_, cvt.yuvWriter_); cv::cvtColor(src, dst, code, -1); @@ -475,7 +697,9 @@ INSTANTIATE_TEST_CASE_P(cvt420, Imgproc_ColorYUV, (int)CV_YUV2RGBA_NV12, (int)CV_YUV2BGRA_NV12, (int)CV_YUV2RGBA_NV21, (int)CV_YUV2BGRA_NV21, (int)CV_YUV2RGB_YV12, (int)CV_YUV2BGR_YV12, (int)CV_YUV2RGB_IYUV, (int)CV_YUV2BGR_IYUV, (int)CV_YUV2RGBA_YV12, (int)CV_YUV2BGRA_YV12, (int)CV_YUV2RGBA_IYUV, (int)CV_YUV2BGRA_IYUV, - (int)CV_YUV2GRAY_420)); + (int)CV_YUV2GRAY_420, (int)CV_RGB2YUV_YV12, (int)CV_BGR2YUV_YV12, (int)CV_RGBA2YUV_YV12, + (int)CV_BGRA2YUV_YV12, (int)CV_RGB2YUV_I420, (int)CV_BGR2YUV_I420, (int)CV_RGBA2YUV_I420, + (int)CV_BGRA2YUV_I420)); INSTANTIATE_TEST_CASE_P(cvt422, Imgproc_ColorYUV, ::testing::Values((int)CV_YUV2RGB_UYVY, (int)CV_YUV2BGR_UYVY, (int)CV_YUV2RGBA_UYVY, (int)CV_YUV2BGRA_UYVY, From cf5e272878a75c9819d0fee89bd11ce4fcf3f43c Mon Sep 17 00:00:00 2001 From: Daniil Osokin Date: Sun, 24 Feb 2013 23:17:40 +0400 Subject: [PATCH 03/10] Added multithreaded implementation for RGB to YUV420p color conversion --- modules/imgproc/src/color.cpp | 126 ++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 45 deletions(-) diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 82c219568..3799d435e 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -2744,6 +2744,16 @@ const int ITUR_BT_601_CVG = -852492; const int ITUR_BT_601_CVR = 1673527; const int ITUR_BT_601_SHIFT = 20; +// Coefficients for RGB to YUV420p conversion +const int ITUR_BT_601_CRY = 269484; +const int ITUR_BT_601_CGY = 528482; +const int ITUR_BT_601_CBY = 102760; +const int ITUR_BT_601_CRU = -155188; +const int ITUR_BT_601_CGU = -305135; +const int ITUR_BT_601_CBU = 460324; +const int ITUR_BT_601_CGV = -385875; +const int ITUR_BT_601_CBV = -74448; + template struct YUV420sp2RGB888Invoker { @@ -3078,54 +3088,80 @@ inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const ucha ///////////////////////////////////// RGB -> YUV420p ///////////////////////////////////// +template +struct RGB888toYUV420pInvoker: public ParallelLoopBody +{ + RGB888toYUV420pInvoker( const Mat& src, Mat* dst, const int uIdx ) + : src_(src), + dst_(dst), + uIdx_(uIdx) { } + + void operator()(const Range& rowRange) const + { + const int w = src_.cols; + const int h = src_.rows; + + const int cn = src_.channels(); + for( int i = rowRange.start; i < rowRange.end; i++ ) + { + const uchar* row0 = src_.ptr(2 * i); + const uchar* row1 = src_.ptr(2 * i + 1); + + uchar* y = dst_->ptr(2*i); + uchar* u = dst_->ptr(h + i/2) + (i % 2) * (w/2); + uchar* v = dst_->ptr(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2); + if( uIdx_ == 2 ) std::swap(u, v); + + for( int j = 0, k = 0; j < w * cn; j += 2 * cn, k++ ) + { + int r00 = row0[2-bIdx + j]; int g00 = row0[1 + j]; int b00 = row0[bIdx + j]; + int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j]; + int r10 = row1[2-bIdx + j]; int g10 = row1[1 + j]; int b10 = row1[bIdx + j]; + int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j]; + + const int shifted16 = (16 << ITUR_BT_601_SHIFT); + const int halfShift = (1 << (ITUR_BT_601_SHIFT - 1)); + int y00 = ITUR_BT_601_CRY * r00 + ITUR_BT_601_CGY * g00 + ITUR_BT_601_CBY * b00 + halfShift + shifted16; + int y01 = ITUR_BT_601_CRY * r01 + ITUR_BT_601_CGY * g01 + ITUR_BT_601_CBY * b01 + halfShift + shifted16; + int y10 = ITUR_BT_601_CRY * r10 + ITUR_BT_601_CGY * g10 + ITUR_BT_601_CBY * b10 + halfShift + shifted16; + int y11 = ITUR_BT_601_CRY * r11 + ITUR_BT_601_CGY * g11 + ITUR_BT_601_CBY * b11 + halfShift + shifted16; + + y[2*k + 0] = saturate_cast(y00 >> ITUR_BT_601_SHIFT); + y[2*k + 1] = saturate_cast(y01 >> ITUR_BT_601_SHIFT); + y[2*k + dst_->step + 0] = saturate_cast(y10 >> ITUR_BT_601_SHIFT); + y[2*k + dst_->step + 1] = saturate_cast(y11 >> ITUR_BT_601_SHIFT); + + const int shifted128 = (128 << ITUR_BT_601_SHIFT); + int u00 = ITUR_BT_601_CRU * r00 + ITUR_BT_601_CGU * g00 + ITUR_BT_601_CBU * b00 + halfShift + shifted128; + int v00 = ITUR_BT_601_CBU * r00 + ITUR_BT_601_CGV * g00 + ITUR_BT_601_CBV * b00 + halfShift + shifted128; + + u[k] = saturate_cast(u00 >> ITUR_BT_601_SHIFT); + v[k] = saturate_cast(v00 >> ITUR_BT_601_SHIFT); + } + } + } + + static bool isFit( const Mat& src ) + { + return (src.total() >= 320*240); + } + +private: + RGB888toYUV420pInvoker& operator=(const RGB888toYUV420pInvoker&); + + const Mat& src_; + Mat* const dst_; + const int uIdx_; +}; + template static void cvtRGBtoYUV420p(const Mat& src, Mat& dst) { - //const float coeffs[] = { 0.257f, 0.504f, 0.098f, - // -0.148f, -0.291f, 0.439f, - // -0.368f, -0.071f }; - const int coeffs[] = { 269484, 528482, 102760, - -155188, -305135, 460324, - -385875, -74448 }; - - const int w = src.cols; - const int h = src.rows; - - const int cn = src.channels(); - for( int i = 0; i < h / 2; i++ ) - { - const uchar* row0 = src.ptr(2*i); - const uchar* row1 = src.ptr(2*i + 1); - - uchar* y = dst.ptr(2*i); - uchar* u = dst.ptr(h + i/2) + (i % 2) * (w/2); - uchar* v = dst.ptr(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2); - if( uIdx == 2 ) std::swap(u, v); - - for( int j = 0, k = 0; j < w * cn; j += 2*cn, k++ ) - { - int r00 = row0[2-bIdx + j]; int g00 = row0[1 + j]; int b00 = row0[bIdx + j]; - int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j]; - int r10 = row1[2-bIdx + j]; int g10 = row1[1 + j]; int b10 = row1[bIdx + j]; - int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j]; - - int y00 = coeffs[0]*r00 + coeffs[1]*g00 + coeffs[2]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); - int y01 = coeffs[0]*r01 + coeffs[1]*g01 + coeffs[2]*b01 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); - int y10 = coeffs[0]*r10 + coeffs[1]*g10 + coeffs[2]*b10 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); - int y11 = coeffs[0]*r11 + coeffs[1]*g11 + coeffs[2]*b11 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); - - y[2*k + 0] = saturate_cast(y00 >> ITUR_BT_601_SHIFT); - y[2*k + 1] = saturate_cast(y01 >> ITUR_BT_601_SHIFT); - y[2*k + dst.step + 0] = saturate_cast(y10 >> ITUR_BT_601_SHIFT); - y[2*k + dst.step + 1] = saturate_cast(y11 >> ITUR_BT_601_SHIFT); - - int u00 = coeffs[3]*r00 + coeffs[4]*g00 + coeffs[5]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (128 << ITUR_BT_601_SHIFT); - int v00 = coeffs[5]*r00 + coeffs[6]*g00 + coeffs[7]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (128 << ITUR_BT_601_SHIFT); - - u[k] = saturate_cast(u00 >> ITUR_BT_601_SHIFT); - v[k] = saturate_cast(v00 >> ITUR_BT_601_SHIFT); - } - } + RGB888toYUV420pInvoker colorConverter(src, &dst, uIdx); + if( RGB888toYUV420pInvoker::isFit(src) ) + parallel_for_(Range(0, src.rows/2), colorConverter); + else + colorConverter(Range(0, src.rows/2)); } ///////////////////////////////////// YUV422 -> RGB ///////////////////////////////////// From 116d3be9c05f3bcf3aaec97ec1f018e316155d5c Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Tue, 5 Mar 2013 18:41:44 +0400 Subject: [PATCH 04/10] moving JNI library to 'build/lib' dir on non-Win --- modules/java/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 2639fe5a5..4dcde5e92 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -303,15 +303,16 @@ set_target_properties(${the_module} PROPERTIES OUTPUT_NAME "${the_module}${LIB_NAME_SUFIX}" #DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} + LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} INSTALL_NAME_DIR ${OPENCV_LIB_INSTALL_PATH} LINK_INTERFACE_LIBRARIES "" ) -if(ANDROID) - set_target_properties(${the_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}) -else() +if(WIN32) set_target_properties(${the_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) +else() + set_target_properties(${the_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}) endif() if(ENABLE_SOLUTION_FOLDERS) From 23fb570cbd1087d0b9d0365c42e24c1edc3e2628 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Tue, 5 Mar 2013 18:42:14 +0400 Subject: [PATCH 05/10] updating JNI lib location for Unix; formatting update --- .../desktop_java/java_dev_intro.rst | 126 +++++++++--------- 1 file changed, 62 insertions(+), 64 deletions(-) diff --git a/doc/tutorials/introduction/desktop_java/java_dev_intro.rst b/doc/tutorials/introduction/desktop_java/java_dev_intro.rst index 367687144..7e071d85f 100644 --- a/doc/tutorials/introduction/desktop_java/java_dev_intro.rst +++ b/doc/tutorials/introduction/desktop_java/java_dev_intro.rst @@ -5,8 +5,6 @@ Introduction to Java Development ******************************** -Last updated: 28 February, 2013. - As of OpenCV 2.4.4, OpenCV supports desktop Java development using nearly the same interface as for Android development. This guide will help you to create your first Java (or Scala) application using OpenCV. We will use either `Eclipse `_, `Apache Ant `_ or the @@ -15,7 +13,7 @@ We will use either `Eclipse `_, `Apache Ant `_. @@ -50,7 +48,7 @@ In order to build OpenCV with Java bindings you need :abbr:`JDK (Java Developmen `Apache Ant `_ and `Python` v2.6 or higher to be installed. Build -##### +----- Let's build OpenCV: @@ -111,11 +109,11 @@ or Besides all this will create a ``jar`` containing the Java interface (:file:`bin/opencv-244.jar`) and a native dynamic library containing Java bindings and all the OpenCV stuff -(:file:`bin/Release/opencv_java244.dll` or :file:`lib/libopencv_java244.so` respectively). +(:file:`lib/libopencv_java244.so` or :file:`bin/Release/opencv_java244.dll` respectively). We'll use these files later. Java sample with Ant -******************** +==================== .. note:: The described sample is provided with OpenCV library in the :file:`opencv/samples/java/ant` folder. @@ -236,99 +234,99 @@ Java sample with Ant :align: center Java project in Eclipse -*********************** +======================= Now let's look at the possiblity of using OpenCV in Java when developing in Eclipse IDE. * Create a new Eclipse workspace * Create a new Java project via :guilabel:`File --> New --> Java Project` - .. image:: images/eclipse_new_java_prj.png - :alt: Eclipse: new Java project - :align: center + .. image:: images/eclipse_new_java_prj.png + :alt: Eclipse: new Java project + :align: center - Call it say "HelloCV". + Call it say "HelloCV". * Open :guilabel:`Java Build Path` tab on :guilabel:`Project Properties` dialog - and configure additional library (OpenCV) reference (jar and native library location): + and configure additional library (OpenCV) reference (jar and native library location): - .. image:: images/eclipse_user_lib.png - :alt: Eclipse: external JAR - :align: center + .. image:: images/eclipse_user_lib.png + :alt: Eclipse: external JAR + :align: center - ` ` + | - .. image:: images/eclipse_user_lib2.png - :alt: Eclipse: external JAR - :align: center + .. image:: images/eclipse_user_lib2.png + :alt: Eclipse: external JAR + :align: center - ` ` + | - .. image:: images/eclipse_user_lib3.png - :alt: Eclipse: external JAR - :align: center + .. image:: images/eclipse_user_lib3.png + :alt: Eclipse: external JAR + :align: center - ` ` + | - .. image:: images/eclipse_user_lib4.png - :alt: Eclipse: external JAR - :align: center + .. image:: images/eclipse_user_lib4.png + :alt: Eclipse: external JAR + :align: center - ` ` + | - .. image:: images/eclipse_user_lib5.png - :alt: Eclipse: external JAR - :align: center + .. image:: images/eclipse_user_lib5.png + :alt: Eclipse: external JAR + :align: center - ` ` + | - .. image:: images/eclipse_user_lib6.png - :alt: Eclipse: external JAR - :align: center + .. image:: images/eclipse_user_lib6.png + :alt: Eclipse: external JAR + :align: center - ` ` + | - .. image:: images/eclipse_user_lib7.png - :alt: Eclipse: external JAR - :align: center + .. image:: images/eclipse_user_lib7.png + :alt: Eclipse: external JAR + :align: center - ` ` + | - .. image:: images/eclipse_user_lib8.png - :alt: Eclipse: external JAR - :align: center + .. image:: images/eclipse_user_lib8.png + :alt: Eclipse: external JAR + :align: center - ` ` * Add a new Java class (say ``Main``) containing the application entry: - .. image:: images/eclipse_main_class.png - :alt: Eclipse: Main class - :align: center + .. image:: images/eclipse_main_class.png + :alt: Eclipse: Main class + :align: center * Put some simple OpenCV calls there, e.g.: - .. code-block:: java - import org.opencv.core.Core; - import org.opencv.core.CvType; - import org.opencv.core.Mat; + .. code-block:: java - public class Main { - public static void main(String[] args) { - System.loadLibrary(Core.NATIVE_LIBRARY_NAME); - Mat m = Mat.eye(3, 3, CvType.CV_8UC1); - System.out.println("m = " + m.dump()); - } + import org.opencv.core.Core; + import org.opencv.core.CvType; + import org.opencv.core.Mat; + + public class Main { + public static void main(String[] args) { + System.loadLibrary(Core.NATIVE_LIBRARY_NAME); + Mat m = Mat.eye(3, 3, CvType.CV_8UC1); + System.out.println("m = " + m.dump()); } + } * Press :guilabel:`Run` button and find the identity matrix content in the Eclipse ``Console`` window. - .. image:: images/eclipse_run.png - :alt: Eclipse: run - :align: center + .. image:: images/eclipse_run.png + :alt: Eclipse: run + :align: center SBT project for Java and Scala -****************************** +============================== Now we'll create a simple Java application using SBT. This serves as a brief introduction to those unfamiliar with this build tool. We're using SBT because it is particularly easy and powerful. @@ -427,7 +425,7 @@ You should see something like this: :align: center Running SBT samples -################### +------------------- Now we'll create a simple face detection application using OpenCV. From aaefd318441d4ccdf96eaa26c22fb9cbf3e734ab Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Tue, 5 Mar 2013 19:03:36 +0400 Subject: [PATCH 06/10] more formatting --- .../desktop_java/java_dev_intro.rst | 186 +++++++++--------- 1 file changed, 93 insertions(+), 93 deletions(-) diff --git a/doc/tutorials/introduction/desktop_java/java_dev_intro.rst b/doc/tutorials/introduction/desktop_java/java_dev_intro.rst index 7e071d85f..17aeca13f 100644 --- a/doc/tutorials/introduction/desktop_java/java_dev_intro.rst +++ b/doc/tutorials/introduction/desktop_java/java_dev_intro.rst @@ -52,26 +52,26 @@ Build Let's build OpenCV: - .. code-block:: bash +.. code-block:: bash - git clone git://github.com/Itseez/opencv.git - cd opencv - git checkout 2.4 - mkdir build - cd build + git clone git://github.com/Itseez/opencv.git + cd opencv + git checkout 2.4 + mkdir build + cd build Generate a Makefile or a MS Visual Studio* solution, or whatever you use for building executables in your system: - .. code-block:: bash +.. code-block:: bash - cmake -DBUILD_SHARED_LIBS=OFF .. + cmake -DBUILD_SHARED_LIBS=OFF .. or - .. code-block:: bat +.. code-block:: bat - cmake -DBUILD_SHARED_LIBS=OFF -G "Visual Studio 10" .. + cmake -DBUILD_SHARED_LIBS=OFF -G "Visual Studio 10" .. .. note:: When OpenCV is built as a set of **static** libraries (``-DBUILD_SHARED_LIBS=OFF`` option) the Java bindings dynamic library is all-sufficient, @@ -81,9 +81,9 @@ Examine the output of CMake and ensure ``java`` is one of the modules "To be bui If not, it's likely you're missing a dependency. You should troubleshoot by looking through the CMake output for any Java-related tools that aren't found and installing them. - .. image:: images/cmake_output.png - :alt: CMake output - :align: center +.. image:: images/cmake_output.png + :alt: CMake output + :align: center .. note:: If ``CMake`` can't find Java in your system set the ``JAVA_HOME`` environment variable with the path to installed JDK @@ -97,15 +97,15 @@ through the CMake output for any Java-related tools that aren't found and instal Now start the build: - .. code-block:: bash +.. code-block:: bash - make -j8 + make -j8 or - .. code-block:: bat +.. code-block:: bat - msbuild /m OpenCV.sln /t:Build /p:Configuration=Release /v:m + msbuild /m OpenCV.sln /t:Build /p:Configuration=Release /v:m Besides all this will create a ``jar`` containing the Java interface (:file:`bin/opencv-244.jar`) and a native dynamic library containing Java bindings and all the OpenCV stuff @@ -122,8 +122,8 @@ Java sample with Ant * In this folder create the :file:`build.xml` file with the following content using any text editor: - .. code-block:: xml - :linenos: + .. code-block:: xml + :linenos: @@ -175,18 +175,18 @@ Java sample with Ant - .. note:: - This XML file can be reused for building other Java applications. - It describes a common folder structure in the lines 3 - 12 and common targets - for compiling and running the application. + .. note:: + This XML file can be reused for building other Java applications. + It describes a common folder structure in the lines 3 - 12 and common targets + for compiling and running the application. - When reusing this XML don't forget to modify the project name in the line 1, - that is also the name of the `main` class (line 14). - The paths to OpenCV `jar` and `jni lib` are expected as parameters - (``"${ocvJarDir}"`` in line 5 and ``"${ocvLibDir}"`` in line 37), but - you can hardcode these paths for your convenience. - See `Ant documentation `_ for detailed description - of its build file format. + When reusing this XML don't forget to modify the project name in the line 1, + that is also the name of the `main` class (line 14). + The paths to OpenCV `jar` and `jni lib` are expected as parameters + (``"${ocvJarDir}"`` in line 5 and ``"${ocvLibDir}"`` in line 37), but + you can hardcode these paths for your convenience. + See `Ant documentation `_ for detailed description + of its build file format. * Create an :file:`src` folder next to the :file:`build.xml` file and a :file:`SimpleSample.java` file in it. @@ -336,66 +336,66 @@ First, download and install `SBT `_ using the instruc Next, navigate to a new directory where you'd like the application source to live (outside :file:`opencv` dir). Let's call it "JavaSample" and create a directory for it: - .. code-block:: bash +.. code-block:: bash - cd - mkdir JavaSample + cd + mkdir JavaSample Now we will create the necessary folders and an SBT project: - .. code-block:: bash +.. code-block:: bash - cd JavaSample - mkdir -p src/main/java # This is where SBT expects to find Java sources - mkdir project # This is where the build definitions live + cd JavaSample + mkdir -p src/main/java # This is where SBT expects to find Java sources + mkdir project # This is where the build definitions live Now open :file:`project/build.scala` in your favorite editor and paste the following. It defines your project: - .. code-block:: scala +.. code-block:: scala - import sbt._ - import Keys._ + import sbt._ + import Keys._ - object JavaSampleBuild extends Build { - def scalaSettings = Seq( - scalaVersion := "2.10.0", - scalacOptions ++= Seq( - "-optimize", - "-unchecked", - "-deprecation" - ) - ) + object JavaSampleBuild extends Build { + def scalaSettings = Seq( + scalaVersion := "2.10.0", + scalacOptions ++= Seq( + "-optimize", + "-unchecked", + "-deprecation" + ) + ) - def buildSettings = - Project.defaultSettings ++ - scalaSettings + def buildSettings = + Project.defaultSettings ++ + scalaSettings - lazy val root = { - val settings = buildSettings ++ Seq(name := "JavaSample") - Project(id = "JavaSample", base = file("."), settings = settings) - } - } + lazy val root = { + val settings = buildSettings ++ Seq(name := "JavaSample") + Project(id = "JavaSample", base = file("."), settings = settings) + } + } Now edit :file:`project/plugins.sbt` and paste the following. This will enable auto-generation of an Eclipse project: - .. code-block:: scala +.. code-block:: scala - addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0") + addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.1.0") Now run ``sbt`` from the :file:`JavaSample` root and from within SBT run ``eclipse`` to generate an eclipse project: - .. code-block:: bash +.. code-block:: bash - sbt # Starts the sbt console - > eclipse # Running "eclipse" from within the sbt console + sbt # Starts the sbt console + > eclipse # Running "eclipse" from within the sbt console You should see something like this: - .. image:: images/sbt_eclipse.png - :alt: SBT output - :align: center +.. image:: images/sbt_eclipse.png + :alt: SBT output + :align: center You can now import the SBT project to Eclipse using :guilabel:`Import ... -> Existing projects into workspace`. Whether you actually do this is optional for the guide; @@ -404,25 +404,25 @@ we'll be using SBT to build the project, so if you choose to use Eclipse it will To test that everything is working, create a simple "Hello OpenCV" application. Do this by creating a file :file:`src/main/java/HelloOpenCV.java` with the following contents: - .. code-block:: java +.. code-block:: java - public class HelloOpenCV { - public static void main(String[] args) { - System.out.println("Hello, OpenCV"); - } - } + public class HelloOpenCV { + public static void main(String[] args) { + System.out.println("Hello, OpenCV"); + } + } Now execute ``run`` from the sbt console, or more concisely, run ``sbt run`` from the command line: - .. code-block:: bash +.. code-block:: bash - sbt run + sbt run You should see something like this: - .. image:: images/sbt_run.png - :alt: SBT run - :align: center +.. image:: images/sbt_run.png + :alt: SBT run + :align: center Running SBT samples ------------------- @@ -433,17 +433,17 @@ First, create a :file:`lib/` folder and copy the OpenCV jar into it. By default, SBT adds jars in the lib folder to the Java library search path. You can optionally rerun ``sbt eclipse`` to update your Eclipse project. - .. code-block:: bash +.. code-block:: bash - mkdir lib - cp /build/bin/opencv_.jar lib/ - sbt eclipse + mkdir lib + cp /build/bin/opencv_.jar lib/ + sbt eclipse Next, create the directory :file:`src/main/resources` and download this Lena image into it: - .. image:: images/lena.png - :alt: Lena - :align: center +.. image:: images/lena.png + :alt: Lena + :align: center Make sure it's called :file:`"lena.png"`. Items in the resources directory are available to the Java application at runtime. @@ -451,9 +451,9 @@ Items in the resources directory are available to the Java application at runtim Next, copy :file:`lbpcascade_frontalface.xml` from :file:`opencv/data/lbpcascades/` into the :file:`resources` directory: - .. code-block:: bash +.. code-block:: bash - cp /data/lbpcascades/lbpcascade_frontalface.xml src/main/resources/ + cp /data/lbpcascades/lbpcascade_frontalface.xml src/main/resources/ Now modify src/main/java/HelloOpenCV.java so it contains the following Java code: @@ -517,21 +517,21 @@ You will also get errors if you try to load OpenCV when it has already been load Now run the face detection app using ``sbt run``: - .. code-block:: bash +.. code-block:: bash - sbt run + sbt run You should see something like this: - .. image:: images/sbt_run_face.png - :alt: SBT run - :align: center +.. image:: images/sbt_run_face.png + :alt: SBT run + :align: center It should also write the following image to :file:`faceDetection.png`: - .. image:: images/faceDetection.png - :alt: Detected face - :align: center +.. image:: images/faceDetection.png + :alt: Detected face + :align: center You're done! Now you have a sample Java application working with OpenCV, so you can start the work on your own. From de3767df0addf70dfcd506009436cdaaa3865ebc Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Wed, 6 Mar 2013 12:59:38 +0400 Subject: [PATCH 07/10] minor formatting --- doc/tutorials/introduction/desktop_java/java_dev_intro.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/tutorials/introduction/desktop_java/java_dev_intro.rst b/doc/tutorials/introduction/desktop_java/java_dev_intro.rst index 17aeca13f..1b20bec25 100644 --- a/doc/tutorials/introduction/desktop_java/java_dev_intro.rst +++ b/doc/tutorials/introduction/desktop_java/java_dev_intro.rst @@ -354,8 +354,8 @@ It defines your project: .. code-block:: scala - import sbt._ - import Keys._ + import sbt._ + import Keys._ object JavaSampleBuild extends Build { def scalaSettings = Seq( From 0e64baaec5a6454f59972af7fac09e811b3af5f2 Mon Sep 17 00:00:00 2001 From: Andrey Pavlenko Date: Wed, 6 Mar 2013 13:00:00 +0400 Subject: [PATCH 08/10] removing redundant code --- modules/java/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/java/CMakeLists.txt b/modules/java/CMakeLists.txt index 4dcde5e92..cf99226ee 100644 --- a/modules/java/CMakeLists.txt +++ b/modules/java/CMakeLists.txt @@ -301,7 +301,6 @@ endif() # Additional target properties set_target_properties(${the_module} PROPERTIES OUTPUT_NAME "${the_module}${LIB_NAME_SUFIX}" - #DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}" ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH} RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} @@ -311,8 +310,6 @@ set_target_properties(${the_module} PROPERTIES if(WIN32) set_target_properties(${the_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) -else() - set_target_properties(${the_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}) endif() if(ENABLE_SOLUTION_FOLDERS) From ec8637a9902e378b83cdbae901cab27b15804770 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Mon, 11 Mar 2013 14:52:22 +0400 Subject: [PATCH 09/10] Fix build errors --- modules/contrib/src/spinimages.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/contrib/src/spinimages.cpp b/modules/contrib/src/spinimages.cpp index 21cbc8b9f..b01090057 100644 --- a/modules/contrib/src/spinimages.cpp +++ b/modules/contrib/src/spinimages.cpp @@ -85,10 +85,10 @@ namespace }; size_t colors_mum = sizeof(colors)/sizeof(colors[0]); -#if (defined __cplusplus && __cplusplus > 199711L) || defined _STLPORT_MAJOR -#else -template void iota(FwIt first, FwIt last, T value) { while(first != last) *first++ = value++; } -#endif +template inline void _iota(FwIt first, FwIt last, T value) +{ + while(first != last) *first++ = value++; +} void computeNormals( const Octree& Octree, const vector& centers, vector& normals, vector& mask, float normalRadius, int minNeighbors = 20) @@ -799,14 +799,14 @@ void cv::SpinImageModel::selectRandomSubset(float ratio) else if (setSize == vtxSize) { subset.resize(vtxSize); - iota(subset.begin(), subset.end(), 0); + _iota(subset.begin(), subset.end(), 0); } else { RNG& rnd = theRNG(); vector left(vtxSize); - iota(left.begin(), left.end(), (size_t)0); + _iota(left.begin(), left.end(), (size_t)0); subset.resize(setSize); for(size_t i = 0; i < setSize; ++i) @@ -879,7 +879,7 @@ void cv::SpinImageModel::compute() { mesh.computeNormals(normalRadius, minNeighbors); subset.resize(mesh.vtx.size()); - iota(subset.begin(), subset.end(), 0); + _iota(subset.begin(), subset.end(), 0); } else mesh.computeNormals(subset, normalRadius, minNeighbors); From 980fc93b4d3a87b38ec3975db2a5214331c38dda Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Mon, 11 Mar 2013 18:40:40 +0400 Subject: [PATCH 10/10] Fix clang + ccache build warnings --- modules/python/src2/cv2.cpp | 10 +++++----- modules/python/src2/cv2.cv.hpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/python/src2/cv2.cpp b/modules/python/src2/cv2.cpp index 02e1b4642..a650f23f0 100644 --- a/modules/python/src2/cv2.cpp +++ b/modules/python/src2/cv2.cpp @@ -510,7 +510,7 @@ static bool pyopencv_to(PyObject* obj, double& value, const char* name = "(c.real); @@ -638,7 +638,7 @@ static inline bool pyopencv_to(PyObject* obj, Point2f& p, const char* name = "(c.real); @@ -989,7 +989,7 @@ static bool pyopencv_to(PyObject *o, cv::flann::IndexParams& p, const char *name const char* value = PyString_AsString(item); p.setString(k, value); } - else if( PyBool_Check(item) ) + else if( !!PyBool_Check(item) ) p.setBool(k, item == Py_True); else if( PyInt_Check(item) ) { diff --git a/modules/python/src2/cv2.cv.hpp b/modules/python/src2/cv2.cv.hpp index 09d3c4723..06c37cbb3 100644 --- a/modules/python/src2/cv2.cv.hpp +++ b/modules/python/src2/cv2.cv.hpp @@ -1158,7 +1158,7 @@ static PyObject* cvseq_map_getitem(PyObject *o, PyObject *item) if (i < 0) i += (int)cvseq_seq_length(o); return cvseq_seq_getitem(o, i); - } else if (PySlice_Check(item)) { + } else if (!!PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, cur, i; PyObject* result; @@ -1975,7 +1975,7 @@ struct dims static int convert_to_dim(PyObject *item, int i, dims *dst, CvArr *cva, const char *name = "no_name") { - if (PySlice_Check(item)) { + if (!!PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; PySlice_GetIndicesEx((PySliceObject*)item, cvGetDimSize(cva, i), &start, &stop, &step, &slicelength); dst->i[i] = (int)start;