mirror of
https://github.com/opencv/opencv.git
synced 2024-11-29 05:29:54 +08:00
improved CV_RGBHSV_FULL accuracy (ticket #938)
This commit is contained in:
parent
da9e3ed6fb
commit
1a0b1d2aea
@ -787,50 +787,37 @@ struct RGB2HSV_b
|
|||||||
typedef uchar channel_type;
|
typedef uchar channel_type;
|
||||||
|
|
||||||
RGB2HSV_b(int _srccn, int _blueIdx, int _hrange)
|
RGB2HSV_b(int _srccn, int _blueIdx, int _hrange)
|
||||||
: srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange) {}
|
: srccn(_srccn), blueIdx(_blueIdx), hrange(_hrange)
|
||||||
|
{
|
||||||
|
CV_Assert( hrange == 180 || hrange == 256 );
|
||||||
|
}
|
||||||
|
|
||||||
void operator()(const uchar* src, uchar* dst, int n) const
|
void operator()(const uchar* src, uchar* dst, int n) const
|
||||||
{
|
{
|
||||||
int i, bidx = blueIdx, scn = srccn;
|
int i, bidx = blueIdx, scn = srccn;
|
||||||
const int hsv_shift = 12;
|
const int hsv_shift = 12;
|
||||||
|
|
||||||
static const int div_table[] = {
|
static int sdiv_table[256];
|
||||||
0, 1044480, 522240, 348160, 261120, 208896, 174080, 149211,
|
static int hdiv_table180[256];
|
||||||
130560, 116053, 104448, 94953, 87040, 80345, 74606, 69632,
|
static int hdiv_table256[256];
|
||||||
65280, 61440, 58027, 54973, 52224, 49737, 47476, 45412,
|
static volatile bool initialized = false;
|
||||||
43520, 41779, 40172, 38684, 37303, 36017, 34816, 33693,
|
|
||||||
32640, 31651, 30720, 29842, 29013, 28229, 27486, 26782,
|
int hr = hrange;
|
||||||
26112, 25475, 24869, 24290, 23738, 23211, 22706, 22223,
|
const int* hdiv_table = hr == 180 ? hdiv_table180 : hdiv_table256;
|
||||||
21760, 21316, 20890, 20480, 20086, 19707, 19342, 18991,
|
|
||||||
18651, 18324, 18008, 17703, 17408, 17123, 16846, 16579,
|
|
||||||
16320, 16069, 15825, 15589, 15360, 15137, 14921, 14711,
|
|
||||||
14507, 14308, 14115, 13926, 13743, 13565, 13391, 13221,
|
|
||||||
13056, 12895, 12738, 12584, 12434, 12288, 12145, 12006,
|
|
||||||
11869, 11736, 11605, 11478, 11353, 11231, 11111, 10995,
|
|
||||||
10880, 10768, 10658, 10550, 10445, 10341, 10240, 10141,
|
|
||||||
10043, 9947, 9854, 9761, 9671, 9582, 9495, 9410,
|
|
||||||
9326, 9243, 9162, 9082, 9004, 8927, 8852, 8777,
|
|
||||||
8704, 8632, 8561, 8492, 8423, 8356, 8290, 8224,
|
|
||||||
8160, 8097, 8034, 7973, 7913, 7853, 7795, 7737,
|
|
||||||
7680, 7624, 7569, 7514, 7461, 7408, 7355, 7304,
|
|
||||||
7253, 7203, 7154, 7105, 7057, 7010, 6963, 6917,
|
|
||||||
6872, 6827, 6782, 6739, 6695, 6653, 6611, 6569,
|
|
||||||
6528, 6487, 6447, 6408, 6369, 6330, 6292, 6254,
|
|
||||||
6217, 6180, 6144, 6108, 6073, 6037, 6003, 5968,
|
|
||||||
5935, 5901, 5868, 5835, 5803, 5771, 5739, 5708,
|
|
||||||
5677, 5646, 5615, 5585, 5556, 5526, 5497, 5468,
|
|
||||||
5440, 5412, 5384, 5356, 5329, 5302, 5275, 5249,
|
|
||||||
5222, 5196, 5171, 5145, 5120, 5095, 5070, 5046,
|
|
||||||
5022, 4998, 4974, 4950, 4927, 4904, 4881, 4858,
|
|
||||||
4836, 4813, 4791, 4769, 4748, 4726, 4705, 4684,
|
|
||||||
4663, 4642, 4622, 4601, 4581, 4561, 4541, 4522,
|
|
||||||
4502, 4483, 4464, 4445, 4426, 4407, 4389, 4370,
|
|
||||||
4352, 4334, 4316, 4298, 4281, 4263, 4246, 4229,
|
|
||||||
4212, 4195, 4178, 4161, 4145, 4128, 4112, 4096
|
|
||||||
};
|
|
||||||
int hr = hrange, hscale = hr == 180 ? 15 : 21;
|
|
||||||
n *= 3;
|
n *= 3;
|
||||||
|
|
||||||
|
if( !initialized )
|
||||||
|
{
|
||||||
|
sdiv_table[0] = hdiv_table180[0] = hdiv_table256[0] = 0;
|
||||||
|
for( i = 1; i < 256; i++ )
|
||||||
|
{
|
||||||
|
sdiv_table[i] = saturate_cast<int>((255 << hsv_shift)/(1.*i));
|
||||||
|
hdiv_table180[i] = saturate_cast<int>((180 << hsv_shift)/(6.*i));
|
||||||
|
hdiv_table256[i] = saturate_cast<int>((256 << hsv_shift)/(6.*i));
|
||||||
|
}
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
for( i = 0; i < n; i += 3, src += scn )
|
for( i = 0; i < n; i += 3, src += scn )
|
||||||
{
|
{
|
||||||
int b = src[bidx], g = src[1], r = src[bidx^2];
|
int b = src[bidx], g = src[1], r = src[bidx^2];
|
||||||
@ -847,13 +834,13 @@ struct RGB2HSV_b
|
|||||||
vr = v == r ? -1 : 0;
|
vr = v == r ? -1 : 0;
|
||||||
vg = v == g ? -1 : 0;
|
vg = v == g ? -1 : 0;
|
||||||
|
|
||||||
s = diff * div_table[v] >> hsv_shift;
|
s = (diff * sdiv_table[v] + (1 << (hsv_shift-1))) >> hsv_shift;
|
||||||
h = (vr & (g - b)) +
|
h = (vr & (g - b)) +
|
||||||
(~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
|
(~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
|
||||||
h = (h * div_table[diff] * hscale + (1 << (hsv_shift + 6))) >> (7 + hsv_shift);
|
h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
|
||||||
h += h < 0 ? hr : 0;
|
h += h < 0 ? hr : 0;
|
||||||
|
|
||||||
dst[i] = (uchar)h;
|
dst[i] = saturate_cast<uchar>(h);
|
||||||
dst[i+1] = (uchar)s;
|
dst[i+1] = (uchar)s;
|
||||||
dst[i+2] = (uchar)v;
|
dst[i+2] = (uchar)v;
|
||||||
}
|
}
|
||||||
@ -2808,7 +2795,7 @@ void cv::cvtColor( const InputArray& _src, OutputArray _dst, int code, int dcn )
|
|||||||
bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||
|
bidx = code == CV_BGR2HSV || code == CV_BGR2HLS ||
|
||||||
code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;
|
code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2;
|
||||||
int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||
|
int hrange = depth == CV_32F ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV ||
|
||||||
code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 255;
|
code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256;
|
||||||
|
|
||||||
_dst.create(sz, CV_MAKETYPE(depth, 3));
|
_dst.create(sz, CV_MAKETYPE(depth, 3));
|
||||||
dst = _dst.getMat();
|
dst = _dst.getMat();
|
||||||
|
@ -78,7 +78,7 @@ protected:
|
|||||||
bool custom_inv_transform;
|
bool custom_inv_transform;
|
||||||
int fwd_code, inv_code;
|
int fwd_code, inv_code;
|
||||||
bool test_cpp;
|
bool test_cpp;
|
||||||
bool hue_channel;
|
int hue_range;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ CV_ColorCvtBaseTest::CV_ColorCvtBaseTest( bool _custom_inv_transform, bool _allo
|
|||||||
fwd_code_str = inv_code_str = 0;
|
fwd_code_str = inv_code_str = 0;
|
||||||
|
|
||||||
test_cpp = false;
|
test_cpp = false;
|
||||||
hue_channel = false;
|
hue_range = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -183,17 +183,17 @@ void CV_ColorCvtBaseTest::prepare_to_validation( int /*test_case_idx*/ )
|
|||||||
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 = test_mat[REF_OUTPUT][0].depth();
|
int depth = test_mat[REF_OUTPUT][0].depth();
|
||||||
if( depth == CV_8U && hue_channel )
|
if( depth == CV_8U && hue_range )
|
||||||
{
|
{
|
||||||
for( int y = 0; y < test_mat[REF_OUTPUT][0].rows; y++ )
|
for( int y = 0; y < test_mat[REF_OUTPUT][0].rows; y++ )
|
||||||
{
|
{
|
||||||
const uchar* h0 = test_mat[REF_OUTPUT][0].ptr(y);
|
uchar* h0 = test_mat[REF_OUTPUT][0].ptr(y);
|
||||||
uchar* h = test_mat[OUTPUT][0].ptr(y);
|
uchar* h = test_mat[OUTPUT][0].ptr(y);
|
||||||
|
|
||||||
for( int x = 0; x < test_mat[REF_OUTPUT][0].cols; x++, h0 += 3, h += 3 )
|
for( int x = 0; x < test_mat[REF_OUTPUT][0].cols; x++, h0 += 3, h += 3 )
|
||||||
{
|
{
|
||||||
if( abs(*h - *h0) == 180 && *h == 0 )
|
if( abs(*h - *h0) >= hue_range-1 && (*h <= 1 || *h0 <= 1) )
|
||||||
*h = 180;
|
*h = *h0 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -595,18 +595,32 @@ protected:
|
|||||||
CV_ColorHSVTest::CV_ColorHSVTest() : CV_ColorCvtBaseTest( true, true, false )
|
CV_ColorHSVTest::CV_ColorHSVTest() : CV_ColorCvtBaseTest( true, true, false )
|
||||||
{
|
{
|
||||||
INIT_FWD_INV_CODES( BGR2HSV, HSV2BGR );
|
INIT_FWD_INV_CODES( BGR2HSV, HSV2BGR );
|
||||||
hue_channel = true;
|
hue_range = 180;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CV_ColorHSVTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
void CV_ColorHSVTest::get_test_array_types_and_sizes( int test_case_idx, vector<vector<Size> >& sizes, vector<vector<int> >& types )
|
||||||
{
|
{
|
||||||
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 );
|
||||||
|
RNG& rng = ts->get_rng();
|
||||||
|
|
||||||
|
bool full_hrange = (rng.next() & 256) != 0;
|
||||||
|
if( full_hrange )
|
||||||
|
{
|
||||||
|
if( blue_idx == 0 )
|
||||||
|
fwd_code = CV_BGR2HSV_FULL, inv_code = CV_HSV2BGR_FULL;
|
||||||
|
else
|
||||||
|
fwd_code = CV_RGB2HSV_FULL, inv_code = CV_HSV2RGB_FULL;
|
||||||
|
hue_range = 256;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if( blue_idx == 0 )
|
if( blue_idx == 0 )
|
||||||
fwd_code = CV_BGR2HSV, inv_code = CV_HSV2BGR;
|
fwd_code = CV_BGR2HSV, inv_code = CV_HSV2BGR;
|
||||||
else
|
else
|
||||||
fwd_code = CV_RGB2HSV, inv_code = CV_HSV2RGB;
|
fwd_code = CV_RGB2HSV, inv_code = CV_HSV2RGB;
|
||||||
|
hue_range = 180;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -620,7 +634,7 @@ double CV_ColorHSVTest::get_success_error_level( int /*test_case_idx*/, int i, i
|
|||||||
void CV_ColorHSVTest::convert_row_bgr2abc_32f_c3( const float* src_row, float* dst_row, int n )
|
void CV_ColorHSVTest::convert_row_bgr2abc_32f_c3( const float* src_row, float* dst_row, int n )
|
||||||
{
|
{
|
||||||
int depth = test_mat[INPUT][0].depth();
|
int depth = test_mat[INPUT][0].depth();
|
||||||
float h_scale = depth == CV_8U ? 30.f : 60.f;
|
float h_scale = depth == CV_8U ? hue_range*30.f/180 : 60.f;
|
||||||
float scale = depth == CV_8U ? 255.f : depth == CV_16U ? 65535.f : 1.f;
|
float scale = depth == CV_8U ? 255.f : depth == CV_16U ? 65535.f : 1.f;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
@ -659,7 +673,7 @@ void CV_ColorHSVTest::convert_row_bgr2abc_32f_c3( const float* src_row, float* d
|
|||||||
void CV_ColorHSVTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* dst_row, int n )
|
void CV_ColorHSVTest::convert_row_abc2bgr_32f_c3( const float* src_row, float* dst_row, int n )
|
||||||
{
|
{
|
||||||
int depth = test_mat[INPUT][0].depth();
|
int depth = test_mat[INPUT][0].depth();
|
||||||
float h_scale = depth == CV_8U ? 1.f/30 : 1.f/60;
|
float h_scale = depth == CV_8U ? 180/(hue_range*30.f) : 1.f/60;
|
||||||
float scale = depth == CV_8U ? 1.f/255 : depth == CV_16U ? 1.f/65535 : 1;
|
float scale = depth == CV_8U ? 1.f/255 : depth == CV_16U ? 1.f/65535 : 1;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
@ -720,7 +734,7 @@ protected:
|
|||||||
CV_ColorHLSTest::CV_ColorHLSTest() : CV_ColorCvtBaseTest( true, true, false )
|
CV_ColorHLSTest::CV_ColorHLSTest() : CV_ColorCvtBaseTest( true, true, false )
|
||||||
{
|
{
|
||||||
INIT_FWD_INV_CODES( BGR2HLS, HLS2BGR );
|
INIT_FWD_INV_CODES( BGR2HLS, HLS2BGR );
|
||||||
hue_channel = true;
|
hue_range = 180;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1634,12 +1648,12 @@ void CV_ColorBayerTest::prepare_to_validation( int /*test_case_idx*/ )
|
|||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TEST(Imgcore_ColorGray, accuracy) { CV_ColorGrayTest test; test.safe_run(); }
|
TEST(Imgproc_ColorGray, accuracy) { CV_ColorGrayTest test; test.safe_run(); }
|
||||||
TEST(Imgcore_ColorYCrCb, accuracy) { CV_ColorYCrCbTest test; test.safe_run(); }
|
TEST(Imgproc_ColorYCrCb, accuracy) { CV_ColorYCrCbTest test; test.safe_run(); }
|
||||||
TEST(Imgcore_ColorHSV, accuracy) { CV_ColorHSVTest test; test.safe_run(); }
|
TEST(Imgproc_ColorHSV, accuracy) { CV_ColorHSVTest test; test.safe_run(); }
|
||||||
TEST(Imgcore_ColorHLS, accuracy) { CV_ColorHLSTest test; test.safe_run(); }
|
TEST(Imgproc_ColorHLS, accuracy) { CV_ColorHLSTest test; test.safe_run(); }
|
||||||
TEST(Imgcore_ColorXYZ, accuracy) { CV_ColorXYZTest test; test.safe_run(); }
|
TEST(Imgproc_ColorXYZ, accuracy) { CV_ColorXYZTest test; test.safe_run(); }
|
||||||
TEST(Imgcore_ColorLab, accuracy) { CV_ColorLabTest test; test.safe_run(); }
|
TEST(Imgproc_ColorLab, accuracy) { CV_ColorLabTest test; test.safe_run(); }
|
||||||
TEST(Imgcore_ColorLuv, accuracy) { CV_ColorLuvTest test; test.safe_run(); }
|
TEST(Imgproc_ColorLuv, accuracy) { CV_ColorLuvTest test; test.safe_run(); }
|
||||||
TEST(Imgcore_ColorRGB, accuracy) { CV_ColorRGBTest test; test.safe_run(); }
|
TEST(Imgproc_ColorRGB, accuracy) { CV_ColorRGBTest test; test.safe_run(); }
|
||||||
TEST(Imgcore_ColorBayer, accuracy) { CV_ColorBayerTest test; test.safe_run(); }
|
TEST(Imgproc_ColorBayer, accuracy) { CV_ColorBayerTest test; test.safe_run(); }
|
||||||
|
Loading…
Reference in New Issue
Block a user