RGB2Gray ushort specialization not defined for SSE2 && !SSE4_1 (Bug #4460)
Description
I was getting a test failure running the OCL_ImgProc/CvtColor.BGRA2GRAY/3
unit test. The results were different between X86 and OpenCL on device.
I found out that it's because the kernel was doing this in the RGB2Gray kernel (modules/imgproc/src/opencl/cvtcolor.cl
:156):
dst[0] = (DATA_TYPE)CV_DESCALE(mad24(src_pix.B_COMP, B2Y, mad24(src_pix.G_COMP, G2Y, mul24(src_pix.R_COMP, R2Y))), yuv_shift);
whereas on host it was doing this in the default RGB2Gray templated struct (modules/imgproc/src/color.cpp
:1269)
dst[i] = saturate_cast<_Tp>(src[0]*cb + src[1]*cg + src[2]*cr);
This means the host is doing floating-point arithmetic and comparing it against integer (short) arithmetic on the device. Due to floating-point rounding, 61.4444...9 was being rounded to 61.5 and then to 62 in the call to saturate_cast
. The device's integer arithmetic produced 61.
I then found that there's a suitable-looking RGB2Gray ushort specialization further down in @modules/imgproc/src/color.cpp:1679:
template<> struct RGB2Gray<ushort> { typedef ushort channel_type; RGB2Gray(int _srccn, int blueIdx, const int* _coeffs) : srccn(_srccn) { static const int coeffs0[] = { R2Y, G2Y, B2Y }; memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 3*sizeof(coeffs[0])); if( blueIdx == 0 ) std::swap(coeffs[0], coeffs[2]); } void operator()(const ushort* src, ushort* dst, int n) const { int scn = srccn, cb = coeffs[0], cg = coeffs[1], cr = coeffs[2]; for(int i = 0; i < n; i++, src += scn) dst[i] = (ushort)CV_DESCALE((unsigned)(src[0]*cb + src[1]*cg + src[2]*cr), yuv_shift); } int srccn; int coeffs[3]; };
I bet if this was used then the test wouldn't fail. The problem is that my X86 machine has SSE2 but not SSE4, so some preprocessor guards further up in that file prevent this from being defined.
It's something like this:
#if CV_NEON template<> struct RGB2Gray<ushort> ... #elif CV_SSE2 #if CV_SSE4_1 template<> struct RGB2Gray<ushort> ... #endif #else template<> struct RGB2Gray<ushort> ... #endif
Shouldn't this last ushort specialization be declared in all cases, as a fall-back?
This might also apply to other colour conversion helpers in that same file: I haven't checked.
History
Updated by Philip L over 9 years ago
yes your assumption is correct, checking this...
- Status changed from New to Open
Updated by Philip L over 9 years ago
created PR for this
https://github.com/Itseez/opencv/pull/4180
btw. i checked other branches and this seems to be the only one were this was wrong atleast for the color.cpp.
If you find more of such errors pleases report.
- % Done changed from 0 to 100
Updated by Alexander Alekhin over 9 years ago
- Pull request set to https://github.com/Itseez/opencv/pull/4193
- Status changed from Open to Done
Updated by Fraser Cormack over 9 years ago
Thanks, this fixes the issue I was seeing!