Commit 2f2f06b9 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

rewrote color conversion functions; added sRGB<->CIE Lab/Luv conversion; added…

rewrote color conversion functions; added sRGB<->CIE Lab/Luv conversion; added RGB<->YUV conversion; improved [s]RGB->Lab conversion speed
parent 74300f5f
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "jpeglib.h" #include "jpeglib.h"
#include "jversion.h" #include "jversion.h"
#include "jerror.h" #include "jerror.h"
#include <stdlib.h>
#ifdef USE_WINDOWS_MESSAGEBOX #ifdef USE_WINDOWS_MESSAGEBOX
#include <windows.h> #include <windows.h>
......
...@@ -3266,6 +3266,41 @@ partition( const vector<_Tp>& _vec, vector<int>& labels, ...@@ -3266,6 +3266,41 @@ partition( const vector<_Tp>& _vec, vector<int>& labels,
return nclasses; return nclasses;
} }
// computes cubic spline coefficients for a function: (xi=i, yi=f[i]), i=0..n
template<typename _Tp> static void splineBuild(const _Tp* f, int n, _Tp* tab)
{
_Tp cn = 0;
int i;
tab[0] = tab[1] = (_Tp)0;
for(i = 1; i < n-1; i++)
{
_Tp t = 3*(f[i+1] - 2*f[i] + f[i-1]);
_Tp l = 1/(4 - tab[(i-1)*4]);
tab[i*4] = l; tab[i*4+1] = (t - tab[(i-1)*4+1])*l;
}
for(i = n-1; i >= 0; i--)
{
_Tp c = tab[i*4+1] - tab[i*4]*cn;
_Tp b = f[i+1] - f[i] - (cn + c*2)*(_Tp)0.3333333333333333;
_Tp d = (cn - c)*(_Tp)0.3333333333333333;
tab[i*4] = f[i]; tab[i*4+1] = b;
tab[i*4+2] = c; tab[i*4+3] = d;
cn = c;
}
}
// interpolates value of a function at x, 0 <= x <= n using a cubic spline.
template<typename _Tp> static inline _Tp splineInterpolate(_Tp x, const _Tp* tab, int n)
{
int ix = cvFloor(x);
ix = std::min(std::max(ix, 0), n-1);
x -= ix;
tab += ix*4;
return ((tab[3]*x + tab[2])*x + tab[1])*x + tab[0];
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// bridge C++ => C Seq API // bridge C++ => C Seq API
......
...@@ -206,6 +206,21 @@ enum ...@@ -206,6 +206,21 @@ enum
CV_HLS2BGR_FULL = 72, CV_HLS2BGR_FULL = 72,
CV_HLS2RGB_FULL = 73, CV_HLS2RGB_FULL = 73,
CV_LBGR2Lab = 74,
CV_LRGB2Lab = 75,
CV_LBGR2Luv = 76,
CV_LRGB2Luv = 77,
CV_Lab2LBGR = 78,
CV_Lab2LRGB = 79,
CV_Luv2LBGR = 80,
CV_Luv2LRGB = 81,
CV_BGR2YUV = 82,
CV_RGB2YUV = 83,
CV_YUV2BGR = 84,
CV_YUV2RGB = 85,
CV_COLORCVT_MAX =100 CV_COLORCVT_MAX =100
}; };
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -90,6 +90,7 @@ protected: ...@@ -90,6 +90,7 @@ protected:
int fwd_code, inv_code; int fwd_code, inv_code;
int timing_code; int timing_code;
bool test_cpp; bool test_cpp;
bool hue_channel;
}; };
...@@ -116,6 +117,7 @@ CV_ColorCvtBaseTestImpl::CV_ColorCvtBaseTestImpl( const char* test_name, const c ...@@ -116,6 +117,7 @@ CV_ColorCvtBaseTestImpl::CV_ColorCvtBaseTestImpl( const char* test_name, const c
default_timing_param_names = 0; default_timing_param_names = 0;
test_cpp = false; test_cpp = false;
hue_channel = false;
} }
...@@ -258,6 +260,18 @@ void CV_ColorCvtBaseTestImpl::prepare_to_validation( int /*test_case_idx*/ ) ...@@ -258,6 +260,18 @@ void CV_ColorCvtBaseTestImpl::prepare_to_validation( int /*test_case_idx*/ )
convert_forward( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0] ); convert_forward( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0] );
convert_backward( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0], convert_backward( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0],
&test_mat[REF_OUTPUT][1] ); &test_mat[REF_OUTPUT][1] );
int depth = CV_MAT_DEPTH(test_mat[REF_OUTPUT][0].type);
if( depth == CV_8U && hue_channel )
{
for( int y = 0; y < test_mat[REF_OUTPUT][0].rows; y++ )
for( int x = 0; x < test_mat[REF_OUTPUT][0].cols; x++ )
{
uchar* h0 = test_mat[REF_OUTPUT][0].data.ptr + test_mat[REF_OUTPUT][0].step*y + x*3;
uchar* h = test_mat[OUTPUT][0].data.ptr + test_mat[OUTPUT][0].step*y + x*3;
if( abs(*h - *h0) == 180 )
if( *h == 0 ) *h = 180;
}
}
} }
...@@ -393,7 +407,7 @@ void CV_ColorCvtBaseTestImpl::convert_backward( const CvMat* src, const CvMat* d ...@@ -393,7 +407,7 @@ void CV_ColorCvtBaseTestImpl::convert_backward( const CvMat* src, const CvMat* d
dst_row[j*cn + 1] = CV_CAST_8U(g); dst_row[j*cn + 1] = CV_CAST_8U(g);
dst_row[j*cn + (blue_idx^2)] = CV_CAST_8U(r); dst_row[j*cn + (blue_idx^2)] = CV_CAST_8U(r);
if( cn == 4 ) if( cn == 4 )
dst_row[j*cn + 3] = 0; dst_row[j*cn + 3] = 255;
} }
} }
break; break;
...@@ -416,7 +430,7 @@ void CV_ColorCvtBaseTestImpl::convert_backward( const CvMat* src, const CvMat* d ...@@ -416,7 +430,7 @@ void CV_ColorCvtBaseTestImpl::convert_backward( const CvMat* src, const CvMat* d
dst_row[j*cn + 1] = CV_CAST_16U(g); dst_row[j*cn + 1] = CV_CAST_16U(g);
dst_row[j*cn + (blue_idx^2)] = CV_CAST_16U(r); dst_row[j*cn + (blue_idx^2)] = CV_CAST_16U(r);
if( cn == 4 ) if( cn == 4 )
dst_row[j*cn + 3] = 0; dst_row[j*cn + 3] = 65535;
} }
} }
break; break;
...@@ -436,7 +450,7 @@ void CV_ColorCvtBaseTestImpl::convert_backward( const CvMat* src, const CvMat* d ...@@ -436,7 +450,7 @@ void CV_ColorCvtBaseTestImpl::convert_backward( const CvMat* src, const CvMat* d
dst_row[j*cn + 1] = g; dst_row[j*cn + 1] = g;
dst_row[j*cn + (blue_idx^2)] = r; dst_row[j*cn + (blue_idx^2)] = r;
if( cn == 4 ) if( cn == 4 )
dst_row[j*cn + 3] = 0; dst_row[j*cn + 3] = 1.f;
} }
} }
break; break;
...@@ -701,6 +715,7 @@ CV_ColorHSVTest::CV_ColorHSVTest() ...@@ -701,6 +715,7 @@ CV_ColorHSVTest::CV_ColorHSVTest()
{ {
INIT_FWD_INV_CODES( BGR2HSV, HSV2BGR ); INIT_FWD_INV_CODES( BGR2HSV, HSV2BGR );
depth_list = cvtcolor_depths_8_32; depth_list = cvtcolor_depths_8_32;
hue_channel = true;
} }
...@@ -809,7 +824,7 @@ void CV_ColorHSVTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d ...@@ -809,7 +824,7 @@ void CV_ColorHSVTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* d
} }
//CV_ColorHSVTest color_hsv_test; CV_ColorHSVTest color_hsv_test;
...@@ -831,6 +846,7 @@ CV_ColorHLSTest::CV_ColorHLSTest() ...@@ -831,6 +846,7 @@ CV_ColorHLSTest::CV_ColorHLSTest()
{ {
INIT_FWD_INV_CODES( BGR2HLS, HLS2BGR ); INIT_FWD_INV_CODES( BGR2HLS, HLS2BGR );
depth_list = cvtcolor_depths_8_32; depth_list = cvtcolor_depths_8_32;
hue_channel = true;
} }
...@@ -1100,16 +1116,16 @@ void CV_ColorLabTest::get_test_array_types_and_sizes( int test_case_idx, CvSize* ...@@ -1100,16 +1116,16 @@ void CV_ColorLabTest::get_test_array_types_and_sizes( int test_case_idx, CvSize*
CV_ColorCvtBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); CV_ColorCvtBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
if( blue_idx == 0 ) if( blue_idx == 0 )
fwd_code = CV_BGR2Lab, inv_code = CV_Lab2BGR; fwd_code = CV_LBGR2Lab, inv_code = CV_Lab2LBGR;
else else
fwd_code = CV_RGB2Lab, inv_code = CV_Lab2RGB; fwd_code = CV_LRGB2Lab, inv_code = CV_Lab2LRGB;
} }
double CV_ColorLabTest::get_success_error_level( int /*test_case_idx*/, int i, int j ) double CV_ColorLabTest::get_success_error_level( int /*test_case_idx*/, int i, int j )
{ {
int depth = CV_MAT_DEPTH(test_mat[i][j].type); int depth = CV_MAT_DEPTH(test_mat[i][j].type);
return depth == CV_8U ? 16 : depth == CV_16U ? 32 : 1e-4; return depth == CV_8U ? 16 : depth == CV_16U ? 32 : 1e-3;
} }
...@@ -1234,16 +1250,16 @@ void CV_ColorLuvTest::get_test_array_types_and_sizes( int test_case_idx, CvSize* ...@@ -1234,16 +1250,16 @@ void CV_ColorLuvTest::get_test_array_types_and_sizes( int test_case_idx, CvSize*
CV_ColorCvtBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types ); CV_ColorCvtBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
if( blue_idx == 0 ) if( blue_idx == 0 )
fwd_code = CV_BGR2Luv, inv_code = CV_Luv2BGR; fwd_code = CV_LBGR2Luv, inv_code = CV_Luv2LBGR;
else else
fwd_code = CV_RGB2Luv, inv_code = CV_Luv2RGB; fwd_code = CV_LRGB2Luv, inv_code = CV_Luv2LRGB;
} }
double CV_ColorLuvTest::get_success_error_level( int /*test_case_idx*/, int i, int j ) double CV_ColorLuvTest::get_success_error_level( int /*test_case_idx*/, int i, int j )
{ {
int depth = CV_MAT_DEPTH(test_mat[i][j].type); int depth = CV_MAT_DEPTH(test_mat[i][j].type);
return depth == CV_8U ? 48 : depth == CV_16U ? 32 : 5e-3; return depth == CV_8U ? 48 : depth == CV_16U ? 32 : 1e-2;
} }
...@@ -1480,6 +1496,8 @@ void CV_ColorRGBTest::convert_forward( const CvMat* src, CvMat* dst ) ...@@ -1480,6 +1496,8 @@ void CV_ColorRGBTest::convert_forward( const CvMat* src, CvMat* dst )
int g = src_row[j*cn + 1] >> g_rshift; int g = src_row[j*cn + 1] >> g_rshift;
int r = src_row[j*cn + (blue_idx^2)] >> 3; int r = src_row[j*cn + (blue_idx^2)] >> 3;
((ushort*)dst_row)[j] = (ushort)(b | (g << 5) | (r << r_lshift)); ((ushort*)dst_row)[j] = (ushort)(b | (g << 5) | (r << r_lshift));
if( cn == 4 && src_row[j*4+3] )
((ushort*)dst_row)[j] |= 1 << (r_lshift+5);
} }
} }
} }
...@@ -1558,7 +1576,7 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src, ...@@ -1558,7 +1576,7 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src,
dst_row[j*cn + (blue_idx^2)] = r; dst_row[j*cn + (blue_idx^2)] = r;
if( cn == 4 ) if( cn == 4 )
dst_row[j*cn + 3] = 0; dst_row[j*cn + 3] = 255;
} }
} }
else else
...@@ -1575,7 +1593,10 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src, ...@@ -1575,7 +1593,10 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src,
dst_row[j*cn + (blue_idx^2)] = r; dst_row[j*cn + (blue_idx^2)] = r;
if( cn == 4 ) if( cn == 4 )
dst_row[j*cn + 3] = 0; {
uchar alpha = r_rshift == 11 || (val & 0x8000) != 0 ? 255 : 0;
dst_row[j*cn + 3] = alpha;
}
} }
} }
} }
...@@ -1596,7 +1617,7 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src, ...@@ -1596,7 +1617,7 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src,
dst_row[j*cn + (blue_idx^2)] = r; dst_row[j*cn + (blue_idx^2)] = r;
if( cn == 4 ) if( cn == 4 )
dst_row[j*cn + 3] = 0; dst_row[j*cn + 3] = 65535;
} }
} }
break; break;
...@@ -1616,7 +1637,7 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src, ...@@ -1616,7 +1637,7 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src,
dst_row[j*cn + (blue_idx^2)] = r; dst_row[j*cn + (blue_idx^2)] = r;
if( cn == 4 ) if( cn == 4 )
dst_row[j*cn + 3] = 0; dst_row[j*cn + 3] = 1.f;
} }
} }
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment