From 088a6597bc8e95e5cf7691c0a2e6c681f068ca91 Mon Sep 17 00:00:00 2001 From: Andrey Kamaev Date: Mon, 2 Jul 2012 12:05:06 +0000 Subject: [PATCH] Merged the trunk 8855,8885,8886 --- modules/features2d/test/test_features2d.cpp | 24 ++++-- .../include/opencv2/imgproc/imgproc.hpp | 6 +- .../imgproc/include/opencv2/imgproc/types_c.h | 6 +- modules/imgproc/src/color.cpp | 83 +++++++++++++++++++ .../src/org/opencv/test/OpenCVTestCase.java | 5 +- .../org/opencv/test/android/UtilsTest.java | 39 +++++++++ modules/java/generator/src/cpp/utils.cpp | 75 +++++++++++------ .../generator/src/java/android+Utils.java | 63 +++++++++----- 8 files changed, 245 insertions(+), 56 deletions(-) diff --git a/modules/features2d/test/test_features2d.cpp b/modules/features2d/test/test_features2d.cpp index aad5a30939..813a8e2377 100644 --- a/modules/features2d/test/test_features2d.cpp +++ b/modules/features2d/test/test_features2d.cpp @@ -292,9 +292,9 @@ public: typedef typename Distance::ValueType ValueType; typedef typename Distance::ResultType DistanceType; - CV_DescriptorExtractorTest( const string _name, DistanceType _maxDist, const Ptr& _dextractor, float _prevTime, + CV_DescriptorExtractorTest( const string _name, DistanceType _maxDist, const Ptr& _dextractor, Distance d = Distance() ): - name(_name), maxDist(_maxDist), prevTime(_prevTime), dextractor(_dextractor), distance(d) {} + name(_name), maxDist(_maxDist), dextractor(_dextractor), distance(d) {} protected: virtual void createDescriptorExtractor() {} @@ -400,7 +400,7 @@ protected: double t = (double)getTickCount(); dextractor->compute( img, keypoints, calcDescriptors ); t = getTickCount() - t; - ts->printf(cvtest::TS::LOG, "\nAverage time of computing one descriptor = %g ms (previous time = %g ms).\n", t/((double)cvGetTickFrequency()*1000.)/calcDescriptors.rows, prevTime ); + ts->printf(cvtest::TS::LOG, "\nAverage time of computing one descriptor = %g ms.\n", t/((double)cvGetTickFrequency()*1000.)/calcDescriptors.rows); if( calcDescriptors.rows != (int)keypoints.size() ) { @@ -485,7 +485,6 @@ protected: string name; const DistanceType maxDist; - const float prevTime; Ptr dextractor; Distance distance; @@ -1027,11 +1026,15 @@ TEST( Features2d_Detector_PyramidFAST, regression ) test.safe_run(); } +/* + * Descriptors + */ + TEST( Features2d_DescriptorExtractor_ORB, regression ) { // TODO adjust the parameters below CV_DescriptorExtractorTest test( "descriptor-orb", (CV_DescriptorExtractorTest::DistanceType)12.f, - DescriptorExtractor::create("ORB"), 0.010f ); + DescriptorExtractor::create("ORB") ); test.safe_run(); } @@ -1039,14 +1042,21 @@ TEST( Features2d_DescriptorExtractor_FREAK, regression ) { // TODO adjust the parameters below CV_DescriptorExtractorTest test( "descriptor-freak", (CV_DescriptorExtractorTest::DistanceType)12.f, - DescriptorExtractor::create("FREAK"), 0.010f ); + DescriptorExtractor::create("FREAK") ); test.safe_run(); } TEST( Features2d_DescriptorExtractor_BRIEF, regression ) { CV_DescriptorExtractorTest test( "descriptor-brief", 1, - DescriptorExtractor::create("BRIEF"), 0.00527548f ); + DescriptorExtractor::create("BRIEF") ); + test.safe_run(); +} + +TEST( Features2d_DescriptorExtractor_OpponentBRIEF, regression ) +{ + CV_DescriptorExtractorTest test( "descriptor-opponent-brief", 1, + DescriptorExtractor::create("OpponentBRIEF") ); test.safe_run(); } diff --git a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp index ae0eca9d18..43ffea06fb 100644 --- a/modules/imgproc/include/opencv2/imgproc/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc/imgproc.hpp @@ -1007,7 +1007,11 @@ enum COLOR_YUV2GRAY_YUYV = COLOR_YUV2GRAY_YUY2, COLOR_YUV2GRAY_YUNV = COLOR_YUV2GRAY_YUY2, - COLOR_COLORCVT_MAX = 125 + // alpha premultiplication + COLOR_RGBA2mRGBA = 125, + COLOR_mRGBA2RGBA = 126, + + COLOR_COLORCVT_MAX = 127 }; diff --git a/modules/imgproc/include/opencv2/imgproc/types_c.h b/modules/imgproc/include/opencv2/imgproc/types_c.h index 601ee39ecd..0e4f0a2445 100644 --- a/modules/imgproc/include/opencv2/imgproc/types_c.h +++ b/modules/imgproc/include/opencv2/imgproc/types_c.h @@ -306,7 +306,11 @@ enum CV_YUV2GRAY_YUYV = CV_YUV2GRAY_YUY2, CV_YUV2GRAY_YUNV = CV_YUV2GRAY_YUY2, - CV_COLORCVT_MAX = 125 + // alpha premultiplication + CV_RGBA2mRGBA = 125, + CV_mRGBA2RGBA = 126, + + CV_COLORCVT_MAX = 127 }; diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index 42f7009e5c..8739e42d07 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -3128,6 +3128,57 @@ inline void cvtYUV422toRGBA(Mat& _dst, int _stride, const uchar* _yuv) converter(BlockedRange(0, _dst.rows)); } +/////////////////////////// RGBA <-> mRGBA (alpha premultiplied) ////////////// + +template +struct RGBA2mRGBA +{ + typedef _Tp channel_type; + + void operator()(const _Tp* src, _Tp* dst, int n) const + { + _Tp max_val = ColorChannel<_Tp>::max(); + _Tp half_val = ColorChannel<_Tp>::half(); + for( int i = 0; i < n; i++ ) + { + _Tp v0 = *src++; + _Tp v1 = *src++; + _Tp v2 = *src++; + _Tp v3 = *src++; + + *dst++ = (v0 * v3 + half_val) / max_val; + *dst++ = (v1 * v3 + half_val) / max_val; + *dst++ = (v2 * v3 + half_val) / max_val; + *dst++ = v3; + } + } +}; + + +template +struct mRGBA2RGBA +{ + typedef _Tp channel_type; + + void operator()(const _Tp* src, _Tp* dst, int n) const + { + _Tp max_val = ColorChannel<_Tp>::max(); + for( int i = 0; i < n; i++ ) + { + _Tp v0 = *src++; + _Tp v1 = *src++; + _Tp v2 = *src++; + _Tp v3 = *src++; + _Tp v3_half = v3 / 2; + + *dst++ = (v3==0)? 0 : (v0 * max_val + v3_half) / v3; + *dst++ = (v3==0)? 0 : (v1 * max_val + v3_half) / v3; + *dst++ = (v3==0)? 0 : (v2 * max_val + v3_half) / v3; + *dst++ = v3; + } + } +}; + }//namespace cv ////////////////////////////////////////////////////////////////////////////////////////// @@ -3640,6 +3691,38 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) extractChannel(_src, _dst, code == CV_YUV2GRAY_UYVY ? 1 : 0); } break; + case CV_RGBA2mRGBA: + { + if (dcn <= 0) dcn = 4; + CV_Assert( scn == 4 && dcn == 4 ); + + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + + if( depth == CV_8U ) + { + CvtColorLoop(src, dst, RGBA2mRGBA()); + } else { + CV_Error( CV_StsBadArg, "Unsupported image depth" ); + } + } + break; + case CV_mRGBA2RGBA: + { + if (dcn <= 0) dcn = 4; + CV_Assert( scn == 4 && dcn == 4 ); + + _dst.create(sz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + + if( depth == CV_8U ) + { + CvtColorLoop(src, dst, mRGBA2RGBA()); + } else { + CV_Error( CV_StsBadArg, "Unsupported image depth" ); + } + } + break; default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); } diff --git a/modules/java/android_test/src/org/opencv/test/OpenCVTestCase.java b/modules/java/android_test/src/org/opencv/test/OpenCVTestCase.java index d9fdca3d61..59b34edf00 100644 --- a/modules/java/android_test/src/org/opencv/test/OpenCVTestCase.java +++ b/modules/java/android_test/src/org/opencv/test/OpenCVTestCase.java @@ -400,12 +400,13 @@ public class OpenCVTestCase extends TestCase { Mat diff = new Mat(); Core.absdiff(expected, actual, diff); + double maxDiff = Core.norm(diff, Core.NORM_INF); if (isEqualityMeasured) - assertTrue("Max difference between expected and actiual Mats is bigger than " + eps, + assertTrue("Max difference between expected and actiual Mats is "+ maxDiff + ", that bigger than " + eps, Core.checkRange(diff, true, 0.0, eps)); else - assertFalse("Max difference between expected and actiual Mats is less than " + eps, + assertFalse("Max difference between expected and actiual Mats is "+ maxDiff + ", that less than " + eps, Core.checkRange(diff, true, 0.0, eps)); } diff --git a/modules/java/android_test/src/org/opencv/test/android/UtilsTest.java b/modules/java/android_test/src/org/opencv/test/android/UtilsTest.java index 8977dca083..43a5c4c29f 100644 --- a/modules/java/android_test/src/org/opencv/test/android/UtilsTest.java +++ b/modules/java/android_test/src/org/opencv/test/android/UtilsTest.java @@ -130,4 +130,43 @@ public class UtilsTest extends OpenCVTestCase { } + public void testAlphaPremultiplication() { + final int size = 256; + Bitmap bmp = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + Mat mOrig = new Mat(size, size, CvType.CV_8UC4); + Mat mUnPre = new Mat(size, size, CvType.CV_8UC4); + for(int y=0; y Mat + Mat m1 = new Mat(); + Mat m2 = new Mat(); + + Utils.bitmapToMat(bmp, m1, false); + Imgproc.cvtColor(mOrig, m2, Imgproc.COLOR_RGBA2mRGBA); + assertMatEqual(m1, m2, 1.1); + + Utils.bitmapToMat(bmp, m1, true); + assertMatEqual(m1, mUnPre, 1.1); + + // Mat -> Bitmap + Bitmap bmp1 = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); + + Utils.matToBitmap(mOrig, bmp1, true); + Utils.bitmapToMat(bmp1, m1, true); + //assertMatEqual(m1, mUnPre, 1.1); + Mat diff = new Mat(); + Core.absdiff(m1, mUnPre, diff); + int numDiff = Core.countNonZero(diff.reshape(1)); + assertTrue(numDiff < size * 4); + } + } diff --git a/modules/java/generator/src/cpp/utils.cpp b/modules/java/generator/src/cpp/utils.cpp index 51fca4b1c8..3193d6be22 100644 --- a/modules/java/generator/src/cpp/utils.cpp +++ b/modules/java/generator/src/cpp/utils.cpp @@ -21,14 +21,14 @@ extern "C" { /* * Class: org_opencv_android_Utils - * Method: void nBitmapToMat(Bitmap b, long m_addr) + * Method: void nBitmapToMat2(Bitmap b, long m_addr, boolean unPremultiplyAlpha) */ -JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat - (JNIEnv * env, jclass, jobject bitmap, jlong m_addr); +JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat2 + (JNIEnv * env, jclass, jobject bitmap, jlong m_addr, jboolean needUnPremultiplyAlpha); -JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat - (JNIEnv * env, jclass, jobject bitmap, jlong m_addr) +JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat2 + (JNIEnv * env, jclass, jobject bitmap, jlong m_addr, jboolean needUnPremultiplyAlpha) { AndroidBitmapInfo info; void* pixels = 0; @@ -46,7 +46,8 @@ JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat { LOGD("nBitmapToMat: RGBA_8888 -> CV_8UC4"); Mat tmp(info.height, info.width, CV_8UC4, pixels); - tmp.copyTo(dst); + if(needUnPremultiplyAlpha) cvtColor(tmp, dst, COLOR_mRGBA2RGBA); + else tmp.copyTo(dst); } else { // info.format == ANDROID_BITMAP_FORMAT_RGB_565 LOGD("nBitmapToMat: RGB_565 -> CV_8UC4"); @@ -71,56 +72,68 @@ JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat } } +// old signature is left for binary compatibility with 2.4.0 & 2.4.1, to removed in 2.5 +JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat + (JNIEnv * env, jclass, jobject bitmap, jlong m_addr); + +JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nBitmapToMat + (JNIEnv * env, jclass, jobject bitmap, jlong m_addr) +{ + Java_org_opencv_android_Utils_nBitmapToMat2(env, 0, bitmap, m_addr, false); +} + /* * Class: org_opencv_android_Utils - * Method: void nMatToBitmap(long m_addr, Bitmap b) + * Method: void nMatToBitmap2(long m_addr, Bitmap b, boolean premultiplyAlpha) */ -JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap - (JNIEnv * env, jclass, jlong m_addr, jobject bitmap); -JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap - (JNIEnv * env, jclass, jlong m_addr, jobject bitmap) +JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap2 + (JNIEnv * env, jclass, jlong m_addr, jobject bitmap, jboolean needPremultiplyAlpha); + +JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap2 + (JNIEnv * env, jclass, jlong m_addr, jobject bitmap, jboolean needPremultiplyAlpha) { AndroidBitmapInfo info; void* pixels = 0; - Mat& dst = *((Mat*)m_addr); + Mat& src = *((Mat*)m_addr); try { LOGD("nMatToBitmap"); CV_Assert( AndroidBitmap_getInfo(env, bitmap, &info) >= 0 ); CV_Assert( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 || info.format == ANDROID_BITMAP_FORMAT_RGB_565 ); - CV_Assert( dst.dims == 2 && info.height == (uint32_t)dst.rows && info.width == (uint32_t)dst.cols ); - CV_Assert( dst.type() == CV_8UC1 || dst.type() == CV_8UC3 || dst.type() == CV_8UC4 ); + CV_Assert( src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols ); + CV_Assert( src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4 ); CV_Assert( AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0 ); CV_Assert( pixels ); if( info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ) { Mat tmp(info.height, info.width, CV_8UC4, pixels); - if(dst.type() == CV_8UC1) + if(src.type() == CV_8UC1) { LOGD("nMatToBitmap: CV_8UC1 -> RGBA_8888"); - cvtColor(dst, tmp, CV_GRAY2RGBA); - } else if(dst.type() == CV_8UC3){ + cvtColor(src, tmp, CV_GRAY2RGBA); + } else if(src.type() == CV_8UC3){ LOGD("nMatToBitmap: CV_8UC3 -> RGBA_8888"); - cvtColor(dst, tmp, CV_RGB2RGBA); - } else if(dst.type() == CV_8UC4){ + cvtColor(src, tmp, CV_RGB2RGBA); + } else if(src.type() == CV_8UC4){ LOGD("nMatToBitmap: CV_8UC4 -> RGBA_8888"); - dst.copyTo(tmp); + if(needPremultiplyAlpha) cvtColor(src, tmp, COLOR_RGBA2mRGBA); + else src.copyTo(tmp); } } else { // info.format == ANDROID_BITMAP_FORMAT_RGB_565 Mat tmp(info.height, info.width, CV_8UC2, pixels); - if(dst.type() == CV_8UC1) + if(src.type() == CV_8UC1) { LOGD("nMatToBitmap: CV_8UC1 -> RGB_565"); - cvtColor(dst, tmp, CV_GRAY2BGR565); - } else if(dst.type() == CV_8UC3){ + cvtColor(src, tmp, CV_GRAY2BGR565); + } else if(src.type() == CV_8UC3){ LOGD("nMatToBitmap: CV_8UC3 -> RGB_565"); - cvtColor(dst, tmp, CV_RGB2BGR565); - } else if(dst.type() == CV_8UC4){ + cvtColor(src, tmp, CV_RGB2BGR565); + } else if(src.type() == CV_8UC4){ LOGD("nMatToBitmap: CV_8UC4 -> RGB_565"); - cvtColor(dst, tmp, CV_RGBA2BGR565); + cvtColor(src, tmp, CV_RGBA2BGR565); } } AndroidBitmap_unlockPixels(env, bitmap); @@ -141,4 +154,14 @@ JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap } } +// old signature is left for binary compatibility with 2.4.0 & 2.4.1, to removed in 2.5 +JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap + (JNIEnv * env, jclass, jlong m_addr, jobject bitmap); + +JNIEXPORT void JNICALL Java_org_opencv_android_Utils_nMatToBitmap + (JNIEnv * env, jclass, jlong m_addr, jobject bitmap) +{ + Java_org_opencv_android_Utils_nMatToBitmap2(env, 0, m_addr, bitmap, false); +} + } // extern "C" diff --git a/modules/java/generator/src/java/android+Utils.java b/modules/java/generator/src/java/android+Utils.java index 7a3c915a0a..28ca261add 100644 --- a/modules/java/generator/src/java/android+Utils.java +++ b/modules/java/generator/src/java/android+Utils.java @@ -81,19 +81,28 @@ public class Utils { *
The output Mat is always created of the same size as the input Bitmap and of the 'CV_8UC4' type, * it keeps the image in RGBA format. *
The function throws an exception if the conversion fails. - * - * @param b is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'. - * @param m is a valid output Mat object, it will be reallocated if needed, so it's possible to pass an empty Mat. + * @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'. + * @param mat is a valid output Mat object, it will be reallocated if needed, so it's possible to pass an empty Mat. + * @param unPremultiplyAlpha is a flag if the bitmap needs to be converted from alpha premultiplied format (like Android keeps 'ARGB_8888' ones) to regular one. The flag is ignored for 'RGB_565' bitmaps. */ - public static void bitmapToMat(Bitmap b, Mat m) { - if (b == null) - throw new java.lang.IllegalArgumentException("Bitmap b == null"); - if (m == null) - throw new java.lang.IllegalArgumentException("Mat m == null"); - nBitmapToMat(b, m.nativeObj); + public static void bitmapToMat(Bitmap bmp, Mat mat, boolean unPremultiplyAlpha) { + if (bmp == null) + throw new java.lang.IllegalArgumentException("bmp == null"); + if (mat == null) + throw new java.lang.IllegalArgumentException("mat == null"); + nBitmapToMat2(bmp, mat.nativeObj, unPremultiplyAlpha); } + /** + * Shortened form of the bitmapToMat(bmp, mat, unPremultiplyAlpha=false) + * @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'. + * @param mat is a valid output Mat object, it will be reallocated if needed, so it's possible to pass an empty Mat. + */ + public static void bitmapToMat(Bitmap bmp, Mat mat) { + bitmapToMat(bmp, mat, false); + } + /** * Converts OpenCV Mat to Android Bitmap. *

@@ -102,18 +111,34 @@ public class Utils { *
The output Bitmap object has to be of the same size as the input Mat and of the types 'ARGB_8888' or 'RGB_565'. *
The function throws an exception if the conversion fails. * - * @param m is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'. - * @param b is a valid Bitmap object of the same size as the Mat m and of type 'ARGB_8888' or 'RGB_565'. + * @param mat is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'. + * @param bmp is a valid Bitmap object of the same size as the Mat m and of type 'ARGB_8888' or 'RGB_565'. + * @param premultiplyAlpha is a flag if the Mat needs to be converted to alpha premultiplied format (like Android keeps 'ARGB_8888' bitmaps). The flag is ignored for 'RGB_565' bitmaps. */ - public static void matToBitmap(Mat m, Bitmap b) { - if (m == null) - throw new java.lang.IllegalArgumentException("Mat m == null"); - if (b == null) - throw new java.lang.IllegalArgumentException("Bitmap b == null"); - nMatToBitmap(m.nativeObj, b); + public static void matToBitmap(Mat mat, Bitmap bmp, boolean premultiplyAlpha) { + if (mat == null) + throw new java.lang.IllegalArgumentException("mat == null"); + if (bmp == null) + throw new java.lang.IllegalArgumentException("bmp == null"); + nMatToBitmap2(mat.nativeObj, bmp, premultiplyAlpha); + } + + /** + * Shortened form of the matToBitmap(mat, bmp, premultiplyAlpha=false) + * @param mat is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'. + * @param bmp is a valid Bitmap object of the same size as the Mat m and of type 'ARGB_8888' or 'RGB_565'. + */ + public static void matToBitmap(Mat mat, Bitmap bmp) { + matToBitmap(mat, bmp, false); + } + + + // native stuff + static { + System.loadLibrary("opencv_java"); } - private static native void nBitmapToMat(Bitmap b, long m_addr); + private static native void nBitmapToMat2(Bitmap b, long m_addr, boolean unPremultiplyAlpha); - private static native void nMatToBitmap(long m_addr, Bitmap b); + private static native void nMatToBitmap2(long m_addr, Bitmap b, boolean premultiplyAlpha); } -- GitLab