cvtColor: CV_RGB2HSV_FULL is inaccurate (Bug #938)


Added by Udo Richter about 14 years ago. Updated almost 14 years ago.


Status:Done Start date:
Priority:Normal Due date:
Assignee:Vadim Pisarevsky % Done:

0%

Category:imgproc, video
Target version:-
Affected version: Operating System:
Difficulty: HW Platform:
Pull request:

Description

Hi,

I've read the rgb to hsv conversion code, and found some inaccuracies especially with the _FULL mode that uses 0..255 as H range. After doing some tests, I found the biggest error at rgb=(251,2,255), giving an exact h value of 212.66, but computes to 208 by OpenCV.

Some more in-detail code analysis: In color.cpp, function cvtColor():

int hrange = depth CV_32F ? 360 : code CV_BGR2HSV || code CV_RGB2HSV ||
code CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 255;

For _FULL, hrange should be 256 not 255. The actual range will be 0..hrange-1.

See also color.cpp, RGB2HSV_b::operator():

h += h < 0 ? hr : 0;

This should add 256 to negative values. (And could be replaced by h=uchar(h) in this case.)

int hr = hrange, hscale = hr == 180 ? 15 : 21;
...
h = (h * div_table[diff] * hscale + (1 << (hsv_shift + 6))) >> (7 + hsv_shift);

hscale is actually hrange*128/6/255, which evaluates to acceptable 15.05 for hrange=180, but 21.42 for hrange=256, which introduces serious rounding errors. This is the main source of h inaccuracy. Worst case error here is 5*diff*0.42/128, which can be up to +4.18 for the h component.

This can be avoided by using another division table
table[diff] = Round((hrange << shift)/(6.0*diff)), and
h = (h * table[diff] + (1 << (shift-1))) >> shift.
This will also be faster.

In color.cpp, RGB2HSV_b::operator():

s = diff * div_table[v] >> hsv_shift;

This should use rounding, eg. +(1<<(hsv_shift-1)) to avoid embarrassing rounding errors, like rgb=(0,0,9) having saturation 254 instead of 255.


Associated revisions

Revision 1a0b1d2a
Added by Vadim Pisarevsky almost 14 years ago

improved CV_RGBHSV_FULL accuracy (ticket #938)

Revision 267eb99a
Added by Vadim Pisarevsky almost 12 years ago

Merge pull request #938 from pengx17:2.4_surf_sample

Revision 3bfc6974
Added by Roman Donchenko almost 12 years ago

Merge remote-tracking branch 'origin/2.4' into merge-2.4

Merged pull requests:
#890 from caorong:patch-1
#893 from jet47:gpu-arm-fixes
#933 from pengx17:2.4_macfix_cont
#935 from pengx17:2.4_filter2d_fix
#936 from bitwangyaoyao:2.4_perf
#937 from bitwangyaoyao:2.4_fixPyrLK
#938 from pengx17:2.4_surf_sample
#939 from pengx17:2.4_getDevice
#940 from SpecLad:autolock
#941 from apavlenko:signed_char
#946 from bitwangyaoyao:2.4_samples2
#947 from jet47:fix-gpu-arm-build
#948 from jet47:cuda-5.5-support
#952 from SpecLad:jepg
#953 from jet47:fix-bug-3069
#955 from SpecLad:symlink
#957 from pengx17:2.4_fix_corner_detector
#959 from SpecLad:qt4-build
#960 from SpecLad:extra-modules

Conflicts:
modules/core/include/opencv2/core/core.hpp
modules/gpu/CMakeLists.txt
modules/gpu/include/opencv2/gpu/device/vec_math.hpp
modules/gpu/perf/perf_video.cpp
modules/gpuimgproc/src/cuda/hough.cu
modules/ocl/include/opencv2/ocl/ocl.hpp
modules/ocl/src/pyrlk.cpp
samples/gpu/driver_api_multi.cpp
samples/gpu/driver_api_stereo_multi.cpp
samples/ocl/surf_matcher.cpp

History

Updated by Vadim Pisarevsky almost 14 years ago

thanks! the proposed changes have been integrated into SVN trunk (r5324)

  • Status changed from Open to Done
  • (deleted custom field) set to fixed

Also available in: Atom PDF