rewrote color conversion functions; added sRGB<->CIE Lab/Luv conversion; added RGB<->YUV conversion; improved [s]RGB->Lab conversion speed

This commit is contained in:
Vadim Pisarevsky 2010-07-27 14:10:14 +00:00
parent 74300f5f42
commit 2f2f06b925
5 changed files with 1787 additions and 2212 deletions

View File

@ -23,6 +23,7 @@
#include "jpeglib.h"
#include "jversion.h"
#include "jerror.h"
#include <stdlib.h>
#ifdef USE_WINDOWS_MESSAGEBOX
#include <windows.h>

View File

@ -3266,6 +3266,41 @@ partition( const vector<_Tp>& _vec, vector<int>& labels,
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

View File

@ -206,6 +206,21 @@ enum
CV_HLS2BGR_FULL = 72,
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
};

File diff suppressed because it is too large Load Diff

View File

@ -90,6 +90,7 @@ protected:
int fwd_code, inv_code;
int timing_code;
bool test_cpp;
bool hue_channel;
};
@ -116,6 +117,7 @@ CV_ColorCvtBaseTestImpl::CV_ColorCvtBaseTestImpl( const char* test_name, const c
default_timing_param_names = 0;
test_cpp = false;
hue_channel = false;
}
@ -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_backward( &test_mat[INPUT][0], &test_mat[REF_OUTPUT][0],
&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
dst_row[j*cn + 1] = CV_CAST_8U(g);
dst_row[j*cn + (blue_idx^2)] = CV_CAST_8U(r);
if( cn == 4 )
dst_row[j*cn + 3] = 0;
dst_row[j*cn + 3] = 255;
}
}
break;
@ -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 + (blue_idx^2)] = CV_CAST_16U(r);
if( cn == 4 )
dst_row[j*cn + 3] = 0;
dst_row[j*cn + 3] = 65535;
}
}
break;
@ -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 + (blue_idx^2)] = r;
if( cn == 4 )
dst_row[j*cn + 3] = 0;
dst_row[j*cn + 3] = 1.f;
}
}
break;
@ -701,6 +715,7 @@ CV_ColorHSVTest::CV_ColorHSVTest()
{
INIT_FWD_INV_CODES( BGR2HSV, HSV2BGR );
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
}
//CV_ColorHSVTest color_hsv_test;
CV_ColorHSVTest color_hsv_test;
@ -831,6 +846,7 @@ CV_ColorHLSTest::CV_ColorHLSTest()
{
INIT_FWD_INV_CODES( BGR2HLS, HLS2BGR );
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*
CV_ColorCvtBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
if( blue_idx == 0 )
fwd_code = CV_BGR2Lab, inv_code = CV_Lab2BGR;
fwd_code = CV_LBGR2Lab, inv_code = CV_Lab2LBGR;
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 )
{
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*
CV_ColorCvtBaseTest::get_test_array_types_and_sizes( test_case_idx, sizes, types );
if( blue_idx == 0 )
fwd_code = CV_BGR2Luv, inv_code = CV_Luv2BGR;
fwd_code = CV_LBGR2Luv, inv_code = CV_Luv2LBGR;
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 )
{
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 )
int g = src_row[j*cn + 1] >> g_rshift;
int r = src_row[j*cn + (blue_idx^2)] >> 3;
((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,
dst_row[j*cn + (blue_idx^2)] = r;
if( cn == 4 )
dst_row[j*cn + 3] = 0;
dst_row[j*cn + 3] = 255;
}
}
else
@ -1575,7 +1593,10 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src,
dst_row[j*cn + (blue_idx^2)] = r;
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,
dst_row[j*cn + (blue_idx^2)] = r;
if( cn == 4 )
dst_row[j*cn + 3] = 0;
dst_row[j*cn + 3] = 65535;
}
}
break;
@ -1616,7 +1637,7 @@ void CV_ColorRGBTest::convert_backward( const CvMat* /*src*/, const CvMat* src,
dst_row[j*cn + (blue_idx^2)] = r;
if( cn == 4 )
dst_row[j*cn + 3] = 0;
dst_row[j*cn + 3] = 1.f;
}
}
break;