00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef __OPENCV_GPU_COLOR_DETAIL_HPP__
00044 #define __OPENCV_GPU_COLOR_DETAIL_HPP__
00045
00046 #include "../common.hpp"
00047 #include "../vec_traits.hpp"
00048 #include "../saturate_cast.hpp"
00049 #include "../limits.hpp"
00050 #include "../functional.hpp"
00051
00052 namespace cv { namespace gpu { namespace device
00053 {
00054 #ifndef CV_DESCALE
00055 #define CV_DESCALE(x, n) (((x) + (1 << ((n)-1))) >> (n))
00056 #endif
00057
00058 namespace color_detail
00059 {
00060 template<typename T> struct ColorChannel
00061 {
00062 typedef float worktype_f;
00063 static __device__ __forceinline__ T max() { return numeric_limits<T>::max(); }
00064 static __device__ __forceinline__ T half() { return (T)(max()/2 + 1); }
00065 };
00066
00067 template<> struct ColorChannel<float>
00068 {
00069 typedef float worktype_f;
00070 static __device__ __forceinline__ float max() { return 1.f; }
00071 static __device__ __forceinline__ float half() { return 0.5f; }
00072 };
00073
00074 template <typename T> static __device__ __forceinline__ void setAlpha(typename TypeVec<T, 3>::vec_type& vec, T val)
00075 {
00076 }
00077
00078 template <typename T> static __device__ __forceinline__ void setAlpha(typename TypeVec<T, 4>::vec_type& vec, T val)
00079 {
00080 vec.w = val;
00081 }
00082
00083 template <typename T> static __device__ __forceinline__ T getAlpha(const typename TypeVec<T, 3>::vec_type& vec)
00084 {
00085 return ColorChannel<T>::max();
00086 }
00087
00088 template <typename T> static __device__ __forceinline__ T getAlpha(const typename TypeVec<T, 4>::vec_type& vec)
00089 {
00090 return vec.w;
00091 }
00092
00093 enum
00094 {
00095 yuv_shift = 14,
00096 xyz_shift = 12,
00097 R2Y = 4899,
00098 G2Y = 9617,
00099 B2Y = 1868,
00100 BLOCK_SIZE = 256
00101 };
00102 }
00103
00105
00106 namespace color_detail
00107 {
00108 template <typename T, int scn, int dcn, int bidx> struct RGB2RGB
00109 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00110 {
00111 __device__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
00112 {
00113 typename TypeVec<T, dcn>::vec_type dst;
00114
00115 dst.x = (&src.x)[bidx];
00116 dst.y = src.y;
00117 dst.z = (&src.x)[bidx^2];
00118 setAlpha(dst, getAlpha<T>(src));
00119
00120 return dst;
00121 }
00122
00123 __device__ __forceinline__ RGB2RGB()
00124 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00125
00126 __device__ __forceinline__ RGB2RGB(const RGB2RGB& other_)
00127 :unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00128 };
00129
00130 template <> struct RGB2RGB<uchar, 4, 4, 2> : unary_function<uint, uint>
00131 {
00132 __device__ uint operator()(uint src) const
00133 {
00134 uint dst = 0;
00135
00136 dst |= (0xffu & (src >> 16));
00137 dst |= (0xffu & (src >> 8)) << 8;
00138 dst |= (0xffu & (src)) << 16;
00139 dst |= (0xffu & (src >> 24)) << 24;
00140
00141 return dst;
00142 }
00143
00144 __device__ __forceinline__ RGB2RGB():unary_function<uint, uint>(){}
00145 __device__ __forceinline__ RGB2RGB(const RGB2RGB& other_):unary_function<uint, uint>(){}
00146 };
00147 }
00148
00149 #define OPENCV_GPU_IMPLEMENT_RGB2RGB_TRAITS(name, scn, dcn, bidx) \
00150 template <typename T> struct name ## _traits \
00151 { \
00152 typedef ::cv::gpu::device::color_detail::RGB2RGB<T, scn, dcn, bidx> functor_type; \
00153 static __host__ __device__ __forceinline__ functor_type create_functor() \
00154 { \
00155 return functor_type(); \
00156 } \
00157 };
00158
00160
00161 namespace color_detail
00162 {
00163 template <int green_bits, int bidx> struct RGB2RGB5x5Converter;
00164 template<int bidx> struct RGB2RGB5x5Converter<6, bidx>
00165 {
00166 static __device__ __forceinline__ ushort cvt(const uchar3& src)
00167 {
00168 return (ushort)(((&src.x)[bidx] >> 3) | ((src.y & ~3) << 3) | (((&src.x)[bidx^2] & ~7) << 8));
00169 }
00170
00171 static __device__ __forceinline__ ushort cvt(uint src)
00172 {
00173 uint b = 0xffu & (src >> (bidx * 8));
00174 uint g = 0xffu & (src >> 8);
00175 uint r = 0xffu & (src >> ((bidx ^ 2) * 8));
00176 return (ushort)((b >> 3) | ((g & ~3) << 3) | ((r & ~7) << 8));
00177 }
00178 };
00179
00180 template<int bidx> struct RGB2RGB5x5Converter<5, bidx>
00181 {
00182 static __device__ __forceinline__ ushort cvt(const uchar3& src)
00183 {
00184 return (ushort)(((&src.x)[bidx] >> 3) | ((src.y & ~7) << 2) | (((&src.x)[bidx^2] & ~7) << 7));
00185 }
00186
00187 static __device__ __forceinline__ ushort cvt(uint src)
00188 {
00189 uint b = 0xffu & (src >> (bidx * 8));
00190 uint g = 0xffu & (src >> 8);
00191 uint r = 0xffu & (src >> ((bidx ^ 2) * 8));
00192 uint a = 0xffu & (src >> 24);
00193 return (ushort)((b >> 3) | ((g & ~7) << 2) | ((r & ~7) << 7) | (a * 0x8000));
00194 }
00195 };
00196
00197 template<int scn, int bidx, int green_bits> struct RGB2RGB5x5;
00198
00199 template<int bidx, int green_bits> struct RGB2RGB5x5<3, bidx,green_bits> : unary_function<uchar3, ushort>
00200 {
00201 __device__ __forceinline__ ushort operator()(const uchar3& src) const
00202 {
00203 return RGB2RGB5x5Converter<green_bits, bidx>::cvt(src);
00204 }
00205
00206 __device__ __forceinline__ RGB2RGB5x5():unary_function<uchar3, ushort>(){}
00207 __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5& other_):unary_function<uchar3, ushort>(){}
00208 };
00209
00210 template<int bidx, int green_bits> struct RGB2RGB5x5<4, bidx,green_bits> : unary_function<uint, ushort>
00211 {
00212 __device__ __forceinline__ ushort operator()(uint src) const
00213 {
00214 return RGB2RGB5x5Converter<green_bits, bidx>::cvt(src);
00215 }
00216
00217 __device__ __forceinline__ RGB2RGB5x5():unary_function<uint, ushort>(){}
00218 __device__ __forceinline__ RGB2RGB5x5(const RGB2RGB5x5& other_):unary_function<uint, ushort>(){}
00219 };
00220 }
00221
00222 #define OPENCV_GPU_IMPLEMENT_RGB2RGB5x5_TRAITS(name, scn, bidx, green_bits) \
00223 struct name ## _traits \
00224 { \
00225 typedef ::cv::gpu::device::color_detail::RGB2RGB5x5<scn, bidx, green_bits> functor_type; \
00226 static __host__ __device__ __forceinline__ functor_type create_functor() \
00227 { \
00228 return functor_type(); \
00229 } \
00230 };
00231
00232 namespace color_detail
00233 {
00234 template <int green_bits, int bidx> struct RGB5x52RGBConverter;
00235
00236 template <int bidx> struct RGB5x52RGBConverter<5, bidx>
00237 {
00238 static __device__ __forceinline__ void cvt(uint src, uchar3& dst)
00239 {
00240 (&dst.x)[bidx] = src << 3;
00241 dst.y = (src >> 2) & ~7;
00242 (&dst.x)[bidx ^ 2] = (src >> 7) & ~7;
00243 }
00244
00245 static __device__ __forceinline__ void cvt(uint src, uint& dst)
00246 {
00247 dst = 0;
00248
00249 dst |= (0xffu & (src << 3)) << (bidx * 8);
00250 dst |= (0xffu & ((src >> 2) & ~7)) << 8;
00251 dst |= (0xffu & ((src >> 7) & ~7)) << ((bidx ^ 2) * 8);
00252 dst |= ((src & 0x8000) * 0xffu) << 24;
00253 }
00254 };
00255
00256 template <int bidx> struct RGB5x52RGBConverter<6, bidx>
00257 {
00258 static __device__ __forceinline__ void cvt(uint src, uchar3& dst)
00259 {
00260 (&dst.x)[bidx] = src << 3;
00261 dst.y = (src >> 3) & ~3;
00262 (&dst.x)[bidx ^ 2] = (src >> 8) & ~7;
00263 }
00264
00265 static __device__ __forceinline__ void cvt(uint src, uint& dst)
00266 {
00267 dst = 0xffu << 24;
00268
00269 dst |= (0xffu & (src << 3)) << (bidx * 8);
00270 dst |= (0xffu &((src >> 3) & ~3)) << 8;
00271 dst |= (0xffu & ((src >> 8) & ~7)) << ((bidx ^ 2) * 8);
00272 }
00273 };
00274
00275 template <int dcn, int bidx, int green_bits> struct RGB5x52RGB;
00276
00277 template <int bidx, int green_bits> struct RGB5x52RGB<3, bidx, green_bits> : unary_function<ushort, uchar3>
00278 {
00279 __device__ __forceinline__ uchar3 operator()(ushort src) const
00280 {
00281 uchar3 dst;
00282 RGB5x52RGBConverter<green_bits, bidx>::cvt(src, dst);
00283 return dst;
00284 }
00285 __device__ __forceinline__ RGB5x52RGB():unary_function<ushort, uchar3>(){}
00286 __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB& other_):unary_function<ushort, uchar3>(){}
00287
00288 };
00289
00290 template <int bidx, int green_bits> struct RGB5x52RGB<4, bidx, green_bits> : unary_function<ushort, uint>
00291 {
00292 __device__ __forceinline__ uint operator()(ushort src) const
00293 {
00294 uint dst;
00295 RGB5x52RGBConverter<green_bits, bidx>::cvt(src, dst);
00296 return dst;
00297 }
00298 __device__ __forceinline__ RGB5x52RGB():unary_function<ushort, uint>(){}
00299 __device__ __forceinline__ RGB5x52RGB(const RGB5x52RGB& other_):unary_function<ushort, uint>(){}
00300 };
00301 }
00302
00303 #define OPENCV_GPU_IMPLEMENT_RGB5x52RGB_TRAITS(name, dcn, bidx, green_bits) \
00304 struct name ## _traits \
00305 { \
00306 typedef ::cv::gpu::device::color_detail::RGB5x52RGB<dcn, bidx, green_bits> functor_type; \
00307 static __host__ __device__ __forceinline__ functor_type create_functor() \
00308 { \
00309 return functor_type(); \
00310 } \
00311 };
00312
00314
00315 namespace color_detail
00316 {
00317 template <typename T, int dcn> struct Gray2RGB : unary_function<T, typename TypeVec<T, dcn>::vec_type>
00318 {
00319 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(T src) const
00320 {
00321 typename TypeVec<T, dcn>::vec_type dst;
00322
00323 dst.z = dst.y = dst.x = src;
00324 setAlpha(dst, ColorChannel<T>::max());
00325
00326 return dst;
00327 }
00328 __device__ __forceinline__ Gray2RGB():unary_function<T, typename TypeVec<T, dcn>::vec_type>(){}
00329 __device__ __forceinline__ Gray2RGB(const Gray2RGB& other_)
00330 : unary_function<T, typename TypeVec<T, dcn>::vec_type>(){}
00331 };
00332
00333 template <> struct Gray2RGB<uchar, 4> : unary_function<uchar, uint>
00334 {
00335 __device__ __forceinline__ uint operator()(uint src) const
00336 {
00337 uint dst = 0xffu << 24;
00338
00339 dst |= src;
00340 dst |= src << 8;
00341 dst |= src << 16;
00342
00343 return dst;
00344 }
00345 __device__ __forceinline__ Gray2RGB():unary_function<uchar, uint>(){}
00346 __device__ __forceinline__ Gray2RGB(const Gray2RGB& other_):unary_function<uchar, uint>(){}
00347 };
00348 }
00349
00350 #define OPENCV_GPU_IMPLEMENT_GRAY2RGB_TRAITS(name, dcn) \
00351 template <typename T> struct name ## _traits \
00352 { \
00353 typedef ::cv::gpu::device::color_detail::Gray2RGB<T, dcn> functor_type; \
00354 static __host__ __device__ __forceinline__ functor_type create_functor() \
00355 { \
00356 return functor_type(); \
00357 } \
00358 };
00359
00360 namespace color_detail
00361 {
00362 template <int green_bits> struct Gray2RGB5x5Converter;
00363 template<> struct Gray2RGB5x5Converter<6>
00364 {
00365 static __device__ __forceinline__ ushort cvt(uint t)
00366 {
00367 return (ushort)((t >> 3) | ((t & ~3) << 3) | ((t & ~7) << 8));
00368 }
00369 };
00370
00371 template<> struct Gray2RGB5x5Converter<5>
00372 {
00373 static __device__ __forceinline__ ushort cvt(uint t)
00374 {
00375 t >>= 3;
00376 return (ushort)(t | (t << 5) | (t << 10));
00377 }
00378 };
00379
00380 template<int green_bits> struct Gray2RGB5x5 : unary_function<uchar, ushort>
00381 {
00382 __device__ __forceinline__ ushort operator()(uint src) const
00383 {
00384 return Gray2RGB5x5Converter<green_bits>::cvt(src);
00385 }
00386
00387 __device__ __forceinline__ Gray2RGB5x5():unary_function<uchar, ushort>(){}
00388 __device__ __forceinline__ Gray2RGB5x5(const Gray2RGB5x5& other_):unary_function<uchar, ushort>(){}
00389 };
00390 }
00391
00392 #define OPENCV_GPU_IMPLEMENT_GRAY2RGB5x5_TRAITS(name, green_bits) \
00393 struct name ## _traits \
00394 { \
00395 typedef ::cv::gpu::device::color_detail::Gray2RGB5x5<green_bits> functor_type; \
00396 static __host__ __device__ __forceinline__ functor_type create_functor() \
00397 { \
00398 return functor_type(); \
00399 } \
00400 };
00401
00403
00404 namespace color_detail
00405 {
00406 template <int green_bits> struct RGB5x52GrayConverter;
00407 template <> struct RGB5x52GrayConverter<6>
00408 {
00409 static __device__ __forceinline__ uchar cvt(uint t)
00410 {
00411 return (uchar)CV_DESCALE(((t << 3) & 0xf8) * B2Y + ((t >> 3) & 0xfc) * G2Y + ((t >> 8) & 0xf8) * R2Y, yuv_shift);
00412 }
00413 };
00414
00415 template <> struct RGB5x52GrayConverter<5>
00416 {
00417 static __device__ __forceinline__ uchar cvt(uint t)
00418 {
00419 return (uchar)CV_DESCALE(((t << 3) & 0xf8) * B2Y + ((t >> 2) & 0xf8) * G2Y + ((t >> 7) & 0xf8) * R2Y, yuv_shift);
00420 }
00421 };
00422
00423 template<int green_bits> struct RGB5x52Gray : unary_function<ushort, uchar>
00424 {
00425 __device__ __forceinline__ uchar operator()(uint src) const
00426 {
00427 return RGB5x52GrayConverter<green_bits>::cvt(src);
00428 }
00429 __device__ __forceinline__ RGB5x52Gray() : unary_function<ushort, uchar>(){}
00430 __device__ __forceinline__ RGB5x52Gray(const RGB5x52Gray& other_) : unary_function<ushort, uchar>(){}
00431 };
00432 }
00433
00434 #define OPENCV_GPU_IMPLEMENT_RGB5x52GRAY_TRAITS(name, green_bits) \
00435 struct name ## _traits \
00436 { \
00437 typedef ::cv::gpu::device::color_detail::RGB5x52Gray<green_bits> functor_type; \
00438 static __host__ __device__ __forceinline__ functor_type create_functor() \
00439 { \
00440 return functor_type(); \
00441 } \
00442 };
00443
00444 namespace color_detail
00445 {
00446 template <int bidx, typename T> static __device__ __forceinline__ T RGB2GrayConvert(const T* src)
00447 {
00448 return (T)CV_DESCALE((unsigned)(src[bidx] * B2Y + src[1] * G2Y + src[bidx^2] * R2Y), yuv_shift);
00449 }
00450
00451 template <int bidx> static __device__ __forceinline__ uchar RGB2GrayConvert(uint src)
00452 {
00453 uint b = 0xffu & (src >> (bidx * 8));
00454 uint g = 0xffu & (src >> 8);
00455 uint r = 0xffu & (src >> ((bidx ^ 2) * 8));
00456 return CV_DESCALE((uint)(b * B2Y + g * G2Y + r * R2Y), yuv_shift);
00457 }
00458
00459 template <int bidx> static __device__ __forceinline__ float RGB2GrayConvert(const float* src)
00460 {
00461 return src[bidx] * 0.114f + src[1] * 0.587f + src[bidx^2] * 0.299f;
00462 }
00463
00464 template <typename T, int scn, int bidx> struct RGB2Gray : unary_function<typename TypeVec<T, scn>::vec_type, T>
00465 {
00466 __device__ __forceinline__ T operator()(const typename TypeVec<T, scn>::vec_type& src) const
00467 {
00468 return RGB2GrayConvert<bidx>(&src.x);
00469 }
00470 __device__ __forceinline__ RGB2Gray() : unary_function<typename TypeVec<T, scn>::vec_type, T>(){}
00471 __device__ __forceinline__ RGB2Gray(const RGB2Gray& other_)
00472 : unary_function<typename TypeVec<T, scn>::vec_type, T>(){}
00473 };
00474
00475 template <int bidx> struct RGB2Gray<uchar, 4, bidx> : unary_function<uint, uchar>
00476 {
00477 __device__ __forceinline__ uchar operator()(uint src) const
00478 {
00479 return RGB2GrayConvert<bidx>(src);
00480 }
00481 __device__ __forceinline__ RGB2Gray() : unary_function<uint, uchar>(){}
00482 __device__ __forceinline__ RGB2Gray(const RGB2Gray& other_) : unary_function<uint, uchar>(){}
00483 };
00484 }
00485
00486 #define OPENCV_GPU_IMPLEMENT_RGB2GRAY_TRAITS(name, scn, bidx) \
00487 template <typename T> struct name ## _traits \
00488 { \
00489 typedef ::cv::gpu::device::color_detail::RGB2Gray<T, scn, bidx> functor_type; \
00490 static __host__ __device__ __forceinline__ functor_type create_functor() \
00491 { \
00492 return functor_type(); \
00493 } \
00494 };
00495
00497
00498 namespace color_detail
00499 {
00500 __constant__ float c_RGB2YUVCoeffs_f[5] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f };
00501 __constant__ int c_RGB2YUVCoeffs_i[5] = { B2Y, G2Y, R2Y, 8061, 14369 };
00502
00503 template <int bidx, typename T, typename D> static __device__ void RGB2YUVConvert(const T* src, D& dst)
00504 {
00505 const int delta = ColorChannel<T>::half() * (1 << yuv_shift);
00506
00507 const int Y = CV_DESCALE(src[0] * c_RGB2YUVCoeffs_i[bidx^2] + src[1] * c_RGB2YUVCoeffs_i[1] + src[2] * c_RGB2YUVCoeffs_i[bidx], yuv_shift);
00508 const int Cr = CV_DESCALE((src[bidx^2] - Y) * c_RGB2YUVCoeffs_i[3] + delta, yuv_shift);
00509 const int Cb = CV_DESCALE((src[bidx] - Y) * c_RGB2YUVCoeffs_i[4] + delta, yuv_shift);
00510
00511 dst.x = saturate_cast<T>(Y);
00512 dst.y = saturate_cast<T>(Cr);
00513 dst.z = saturate_cast<T>(Cb);
00514 }
00515
00516 template <int bidx, typename D> static __device__ __forceinline__ void RGB2YUVConvert(const float* src, D& dst)
00517 {
00518 dst.x = src[0] * c_RGB2YUVCoeffs_f[bidx^2] + src[1] * c_RGB2YUVCoeffs_f[1] + src[2] * c_RGB2YUVCoeffs_f[bidx];
00519 dst.y = (src[bidx^2] - dst.x) * c_RGB2YUVCoeffs_f[3] + ColorChannel<float>::half();
00520 dst.z = (src[bidx] - dst.x) * c_RGB2YUVCoeffs_f[4] + ColorChannel<float>::half();
00521 }
00522
00523 template <typename T, int scn, int dcn, int bidx> struct RGB2YUV
00524 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00525 {
00526 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator ()(const typename TypeVec<T, scn>::vec_type& src) const
00527 {
00528 typename TypeVec<T, dcn>::vec_type dst;
00529 RGB2YUVConvert<bidx>(&src.x, dst);
00530 return dst;
00531 }
00532 __device__ __forceinline__ RGB2YUV()
00533 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00534 __device__ __forceinline__ RGB2YUV(const RGB2YUV& other_)
00535 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00536 };
00537 }
00538
00539 #define OPENCV_GPU_IMPLEMENT_RGB2YUV_TRAITS(name, scn, dcn, bidx) \
00540 template <typename T> struct name ## _traits \
00541 { \
00542 typedef ::cv::gpu::device::color_detail::RGB2YUV<T, scn, dcn, bidx> functor_type; \
00543 static __host__ __device__ __forceinline__ functor_type create_functor() \
00544 { \
00545 return functor_type(); \
00546 } \
00547 };
00548
00549 namespace color_detail
00550 {
00551 __constant__ float c_YUV2RGBCoeffs_f[5] = { 2.032f, -0.395f, -0.581f, 1.140f };
00552 __constant__ int c_YUV2RGBCoeffs_i[5] = { 33292, -6472, -9519, 18678 };
00553
00554 template <int bidx, typename T, typename D> static __device__ void YUV2RGBConvert(const T& src, D* dst)
00555 {
00556 const int b = src.x + CV_DESCALE((src.z - ColorChannel<D>::half()) * c_YUV2RGBCoeffs_i[3], yuv_shift);
00557
00558 const int g = src.x + CV_DESCALE((src.z - ColorChannel<D>::half()) * c_YUV2RGBCoeffs_i[2]
00559 + (src.y - ColorChannel<D>::half()) * c_YUV2RGBCoeffs_i[1], yuv_shift);
00560
00561 const int r = src.x + CV_DESCALE((src.y - ColorChannel<D>::half()) * c_YUV2RGBCoeffs_i[0], yuv_shift);
00562
00563 dst[bidx] = saturate_cast<D>(b);
00564 dst[1] = saturate_cast<D>(g);
00565 dst[bidx^2] = saturate_cast<D>(r);
00566 }
00567
00568 template <int bidx> static __device__ uint YUV2RGBConvert(uint src)
00569 {
00570 const int x = 0xff & (src);
00571 const int y = 0xff & (src >> 8);
00572 const int z = 0xff & (src >> 16);
00573
00574 const int b = x + CV_DESCALE((z - ColorChannel<uchar>::half()) * c_YUV2RGBCoeffs_i[3], yuv_shift);
00575
00576 const int g = x + CV_DESCALE((z - ColorChannel<uchar>::half()) * c_YUV2RGBCoeffs_i[2]
00577 + (y - ColorChannel<uchar>::half()) * c_YUV2RGBCoeffs_i[1], yuv_shift);
00578
00579 const int r = x + CV_DESCALE((y - ColorChannel<uchar>::half()) * c_YUV2RGBCoeffs_i[0], yuv_shift);
00580
00581 uint dst = 0xffu << 24;
00582
00583 dst |= saturate_cast<uchar>(b) << (bidx * 8);
00584 dst |= saturate_cast<uchar>(g) << 8;
00585 dst |= saturate_cast<uchar>(r) << ((bidx ^ 2) * 8);
00586
00587 return dst;
00588 }
00589
00590 template <int bidx, typename T> static __device__ __forceinline__ void YUV2RGBConvert(const T& src, float* dst)
00591 {
00592 dst[bidx] = src.x + (src.z - ColorChannel<float>::half()) * c_YUV2RGBCoeffs_f[3];
00593
00594 dst[1] = src.x + (src.z - ColorChannel<float>::half()) * c_YUV2RGBCoeffs_f[2]
00595 + (src.y - ColorChannel<float>::half()) * c_YUV2RGBCoeffs_f[1];
00596
00597 dst[bidx^2] = src.x + (src.y - ColorChannel<float>::half()) * c_YUV2RGBCoeffs_f[0];
00598 }
00599
00600 template <typename T, int scn, int dcn, int bidx> struct YUV2RGB
00601 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00602 {
00603 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator ()(const typename TypeVec<T, scn>::vec_type& src) const
00604 {
00605 typename TypeVec<T, dcn>::vec_type dst;
00606
00607 YUV2RGBConvert<bidx>(src, &dst.x);
00608 setAlpha(dst, ColorChannel<T>::max());
00609
00610 return dst;
00611 }
00612 __device__ __forceinline__ YUV2RGB()
00613 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00614 __device__ __forceinline__ YUV2RGB(const YUV2RGB& other_)
00615 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00616 };
00617
00618 template <int bidx> struct YUV2RGB<uchar, 4, 4, bidx> : unary_function<uint, uint>
00619 {
00620 __device__ __forceinline__ uint operator ()(uint src) const
00621 {
00622 return YUV2RGBConvert<bidx>(src);
00623 }
00624 __device__ __forceinline__ YUV2RGB() : unary_function<uint, uint>(){}
00625 __device__ __forceinline__ YUV2RGB(const YUV2RGB& other_) : unary_function<uint, uint>(){}
00626 };
00627 }
00628
00629 #define OPENCV_GPU_IMPLEMENT_YUV2RGB_TRAITS(name, scn, dcn, bidx) \
00630 template <typename T> struct name ## _traits \
00631 { \
00632 typedef ::cv::gpu::device::color_detail::YUV2RGB<T, scn, dcn, bidx> functor_type; \
00633 static __host__ __device__ __forceinline__ functor_type create_functor() \
00634 { \
00635 return functor_type(); \
00636 } \
00637 };
00638
00640
00641 namespace color_detail
00642 {
00643 __constant__ float c_RGB2YCrCbCoeffs_f[5] = {0.299f, 0.587f, 0.114f, 0.713f, 0.564f};
00644 __constant__ int c_RGB2YCrCbCoeffs_i[5] = {R2Y, G2Y, B2Y, 11682, 9241};
00645
00646 template <int bidx, typename T, typename D> static __device__ void RGB2YCrCbConvert(const T* src, D& dst)
00647 {
00648 const int delta = ColorChannel<T>::half() * (1 << yuv_shift);
00649
00650 const int Y = CV_DESCALE(src[0] * c_RGB2YCrCbCoeffs_i[bidx^2] + src[1] * c_RGB2YCrCbCoeffs_i[1] + src[2] * c_RGB2YCrCbCoeffs_i[bidx], yuv_shift);
00651 const int Cr = CV_DESCALE((src[bidx^2] - Y) * c_RGB2YCrCbCoeffs_i[3] + delta, yuv_shift);
00652 const int Cb = CV_DESCALE((src[bidx] - Y) * c_RGB2YCrCbCoeffs_i[4] + delta, yuv_shift);
00653
00654 dst.x = saturate_cast<T>(Y);
00655 dst.y = saturate_cast<T>(Cr);
00656 dst.z = saturate_cast<T>(Cb);
00657 }
00658
00659 template <int bidx> static __device__ uint RGB2YCrCbConvert(uint src)
00660 {
00661 const int delta = ColorChannel<uchar>::half() * (1 << yuv_shift);
00662
00663 const int Y = CV_DESCALE((0xffu & src) * c_RGB2YCrCbCoeffs_i[bidx^2] + (0xffu & (src >> 8)) * c_RGB2YCrCbCoeffs_i[1] + (0xffu & (src >> 16)) * c_RGB2YCrCbCoeffs_i[bidx], yuv_shift);
00664 const int Cr = CV_DESCALE(((0xffu & (src >> ((bidx ^ 2) * 8))) - Y) * c_RGB2YCrCbCoeffs_i[3] + delta, yuv_shift);
00665 const int Cb = CV_DESCALE(((0xffu & (src >> (bidx * 8))) - Y) * c_RGB2YCrCbCoeffs_i[4] + delta, yuv_shift);
00666
00667 uint dst = 0;
00668
00669 dst |= saturate_cast<uchar>(Y);
00670 dst |= saturate_cast<uchar>(Cr) << 8;
00671 dst |= saturate_cast<uchar>(Cb) << 16;
00672
00673 return dst;
00674 }
00675
00676 template <int bidx, typename D> static __device__ __forceinline__ void RGB2YCrCbConvert(const float* src, D& dst)
00677 {
00678 dst.x = src[0] * c_RGB2YCrCbCoeffs_f[bidx^2] + src[1] * c_RGB2YCrCbCoeffs_f[1] + src[2] * c_RGB2YCrCbCoeffs_f[bidx];
00679 dst.y = (src[bidx^2] - dst.x) * c_RGB2YCrCbCoeffs_f[3] + ColorChannel<float>::half();
00680 dst.z = (src[bidx] - dst.x) * c_RGB2YCrCbCoeffs_f[4] + ColorChannel<float>::half();
00681 }
00682
00683 template <typename T, int scn, int dcn, int bidx> struct RGB2YCrCb
00684 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00685 {
00686 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator ()(const typename TypeVec<T, scn>::vec_type& src) const
00687 {
00688 typename TypeVec<T, dcn>::vec_type dst;
00689 RGB2YCrCbConvert<bidx>(&src.x, dst);
00690 return dst;
00691 }
00692 __device__ __forceinline__ RGB2YCrCb()
00693 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00694 __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb& other_)
00695 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00696 };
00697
00698 template <int bidx> struct RGB2YCrCb<uchar, 4, 4, bidx> : unary_function<uint, uint>
00699 {
00700 __device__ __forceinline__ uint operator ()(uint src) const
00701 {
00702 return RGB2YCrCbConvert<bidx>(src);
00703 }
00704
00705 __device__ __forceinline__ RGB2YCrCb() : unary_function<uint, uint>(){}
00706 __device__ __forceinline__ RGB2YCrCb(const RGB2YCrCb& other_) : unary_function<uint, uint>(){}
00707 };
00708 }
00709
00710 #define OPENCV_GPU_IMPLEMENT_RGB2YCrCb_TRAITS(name, scn, dcn, bidx) \
00711 template <typename T> struct name ## _traits \
00712 { \
00713 typedef ::cv::gpu::device::color_detail::RGB2YCrCb<T, scn, dcn, bidx> functor_type; \
00714 static __host__ __device__ __forceinline__ functor_type create_functor() \
00715 { \
00716 return functor_type(); \
00717 } \
00718 };
00719
00720 namespace color_detail
00721 {
00722 __constant__ float c_YCrCb2RGBCoeffs_f[5] = {1.403f, -0.714f, -0.344f, 1.773f};
00723 __constant__ int c_YCrCb2RGBCoeffs_i[5] = {22987, -11698, -5636, 29049};
00724
00725 template <int bidx, typename T, typename D> static __device__ void YCrCb2RGBConvert(const T& src, D* dst)
00726 {
00727 const int b = src.x + CV_DESCALE((src.z - ColorChannel<D>::half()) * c_YCrCb2RGBCoeffs_i[3], yuv_shift);
00728 const int g = src.x + CV_DESCALE((src.z - ColorChannel<D>::half()) * c_YCrCb2RGBCoeffs_i[2] + (src.y - ColorChannel<D>::half()) * c_YCrCb2RGBCoeffs_i[1], yuv_shift);
00729 const int r = src.x + CV_DESCALE((src.y - ColorChannel<D>::half()) * c_YCrCb2RGBCoeffs_i[0], yuv_shift);
00730
00731 dst[bidx] = saturate_cast<D>(b);
00732 dst[1] = saturate_cast<D>(g);
00733 dst[bidx^2] = saturate_cast<D>(r);
00734 }
00735
00736 template <int bidx> static __device__ uint YCrCb2RGBConvert(uint src)
00737 {
00738 const int x = 0xff & (src);
00739 const int y = 0xff & (src >> 8);
00740 const int z = 0xff & (src >> 16);
00741
00742 const int b = x + CV_DESCALE((z - ColorChannel<uchar>::half()) * c_YCrCb2RGBCoeffs_i[3], yuv_shift);
00743 const int g = x + CV_DESCALE((z - ColorChannel<uchar>::half()) * c_YCrCb2RGBCoeffs_i[2] + (y - ColorChannel<uchar>::half()) * c_YCrCb2RGBCoeffs_i[1], yuv_shift);
00744 const int r = x + CV_DESCALE((y - ColorChannel<uchar>::half()) * c_YCrCb2RGBCoeffs_i[0], yuv_shift);
00745
00746 uint dst = 0xffu << 24;
00747
00748 dst |= saturate_cast<uchar>(b) << (bidx * 8);
00749 dst |= saturate_cast<uchar>(g) << 8;
00750 dst |= saturate_cast<uchar>(r) << ((bidx ^ 2) * 8);
00751
00752 return dst;
00753 }
00754
00755 template <int bidx, typename T> __device__ __forceinline__ void YCrCb2RGBConvert(const T& src, float* dst)
00756 {
00757 dst[bidx] = src.x + (src.z - ColorChannel<float>::half()) * c_YCrCb2RGBCoeffs_f[3];
00758 dst[1] = src.x + (src.z - ColorChannel<float>::half()) * c_YCrCb2RGBCoeffs_f[2] + (src.y - ColorChannel<float>::half()) * c_YCrCb2RGBCoeffs_f[1];
00759 dst[bidx^2] = src.x + (src.y - ColorChannel<float>::half()) * c_YCrCb2RGBCoeffs_f[0];
00760 }
00761
00762 template <typename T, int scn, int dcn, int bidx> struct YCrCb2RGB
00763 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00764 {
00765 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator ()(const typename TypeVec<T, scn>::vec_type& src) const
00766 {
00767 typename TypeVec<T, dcn>::vec_type dst;
00768
00769 YCrCb2RGBConvert<bidx>(src, &dst.x);
00770 setAlpha(dst, ColorChannel<T>::max());
00771
00772 return dst;
00773 }
00774 __device__ __forceinline__ YCrCb2RGB()
00775 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00776 __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB& other_)
00777 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00778 };
00779
00780 template <int bidx> struct YCrCb2RGB<uchar, 4, 4, bidx> : unary_function<uint, uint>
00781 {
00782 __device__ __forceinline__ uint operator ()(uint src) const
00783 {
00784 return YCrCb2RGBConvert<bidx>(src);
00785 }
00786 __device__ __forceinline__ YCrCb2RGB() : unary_function<uint, uint>(){}
00787 __device__ __forceinline__ YCrCb2RGB(const YCrCb2RGB& other_) : unary_function<uint, uint>(){}
00788 };
00789 }
00790
00791 #define OPENCV_GPU_IMPLEMENT_YCrCb2RGB_TRAITS(name, scn, dcn, bidx) \
00792 template <typename T> struct name ## _traits \
00793 { \
00794 typedef ::cv::gpu::device::color_detail::YCrCb2RGB<T, scn, dcn, bidx> functor_type; \
00795 static __host__ __device__ __forceinline__ functor_type create_functor() \
00796 { \
00797 return functor_type(); \
00798 } \
00799 };
00800
00802
00803 namespace color_detail
00804 {
00805 __constant__ float c_RGB2XYZ_D65f[9] = { 0.412453f, 0.357580f, 0.180423f, 0.212671f, 0.715160f, 0.072169f, 0.019334f, 0.119193f, 0.950227f };
00806 __constant__ int c_RGB2XYZ_D65i[9] = { 1689, 1465, 739, 871, 2929, 296, 79, 488, 3892 };
00807
00808 template <int bidx, typename T, typename D> static __device__ __forceinline__ void RGB2XYZConvert(const T* src, D& dst)
00809 {
00810 dst.x = saturate_cast<T>(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[0] + src[1] * c_RGB2XYZ_D65i[1] + src[bidx] * c_RGB2XYZ_D65i[2], xyz_shift));
00811 dst.y = saturate_cast<T>(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[3] + src[1] * c_RGB2XYZ_D65i[4] + src[bidx] * c_RGB2XYZ_D65i[5], xyz_shift));
00812 dst.z = saturate_cast<T>(CV_DESCALE(src[bidx^2] * c_RGB2XYZ_D65i[6] + src[1] * c_RGB2XYZ_D65i[7] + src[bidx] * c_RGB2XYZ_D65i[8], xyz_shift));
00813 }
00814
00815 template <int bidx> static __device__ __forceinline__ uint RGB2XYZConvert(uint src)
00816 {
00817 const uint b = 0xffu & (src >> (bidx * 8));
00818 const uint g = 0xffu & (src >> 8);
00819 const uint r = 0xffu & (src >> ((bidx ^ 2) * 8));
00820
00821 const uint x = saturate_cast<uchar>(CV_DESCALE(r * c_RGB2XYZ_D65i[0] + g * c_RGB2XYZ_D65i[1] + b * c_RGB2XYZ_D65i[2], xyz_shift));
00822 const uint y = saturate_cast<uchar>(CV_DESCALE(r * c_RGB2XYZ_D65i[3] + g * c_RGB2XYZ_D65i[4] + b * c_RGB2XYZ_D65i[5], xyz_shift));
00823 const uint z = saturate_cast<uchar>(CV_DESCALE(r * c_RGB2XYZ_D65i[6] + g * c_RGB2XYZ_D65i[7] + b * c_RGB2XYZ_D65i[8], xyz_shift));
00824
00825 uint dst = 0;
00826
00827 dst |= x;
00828 dst |= y << 8;
00829 dst |= z << 16;
00830
00831 return dst;
00832 }
00833
00834 template <int bidx, typename D> static __device__ __forceinline__ void RGB2XYZConvert(const float* src, D& dst)
00835 {
00836 dst.x = src[bidx^2] * c_RGB2XYZ_D65f[0] + src[1] * c_RGB2XYZ_D65f[1] + src[bidx] * c_RGB2XYZ_D65f[2];
00837 dst.y = src[bidx^2] * c_RGB2XYZ_D65f[3] + src[1] * c_RGB2XYZ_D65f[4] + src[bidx] * c_RGB2XYZ_D65f[5];
00838 dst.z = src[bidx^2] * c_RGB2XYZ_D65f[6] + src[1] * c_RGB2XYZ_D65f[7] + src[bidx] * c_RGB2XYZ_D65f[8];
00839 }
00840
00841 template <typename T, int scn, int dcn, int bidx> struct RGB2XYZ
00842 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00843 {
00844 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
00845 {
00846 typename TypeVec<T, dcn>::vec_type dst;
00847
00848 RGB2XYZConvert<bidx>(&src.x, dst);
00849
00850 return dst;
00851 }
00852 __device__ __forceinline__ RGB2XYZ()
00853 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00854 __device__ __forceinline__ RGB2XYZ(const RGB2XYZ& other_)
00855 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00856 };
00857
00858 template <int bidx> struct RGB2XYZ<uchar, 4, 4, bidx> : unary_function<uint, uint>
00859 {
00860 __device__ __forceinline__ uint operator()(uint src) const
00861 {
00862 return RGB2XYZConvert<bidx>(src);
00863 }
00864 __device__ __forceinline__ RGB2XYZ() : unary_function<uint, uint>(){}
00865 __device__ __forceinline__ RGB2XYZ(const RGB2XYZ& other_) : unary_function<uint, uint>(){}
00866 };
00867 }
00868
00869 #define OPENCV_GPU_IMPLEMENT_RGB2XYZ_TRAITS(name, scn, dcn, bidx) \
00870 template <typename T> struct name ## _traits \
00871 { \
00872 typedef ::cv::gpu::device::color_detail::RGB2XYZ<T, scn, dcn, bidx> functor_type; \
00873 static __host__ __device__ __forceinline__ functor_type create_functor() \
00874 { \
00875 return functor_type(); \
00876 } \
00877 };
00878
00879 namespace color_detail
00880 {
00881 __constant__ float c_XYZ2sRGB_D65f[9] = { 3.240479f, -1.53715f, -0.498535f, -0.969256f, 1.875991f, 0.041556f, 0.055648f, -0.204043f, 1.057311f };
00882 __constant__ int c_XYZ2sRGB_D65i[9] = { 13273, -6296, -2042, -3970, 7684, 170, 228, -836, 4331 };
00883
00884 template <int bidx, typename T, typename D> static __device__ __forceinline__ void XYZ2RGBConvert(const T& src, D* dst)
00885 {
00886 dst[bidx^2] = saturate_cast<D>(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[0] + src.y * c_XYZ2sRGB_D65i[1] + src.z * c_XYZ2sRGB_D65i[2], xyz_shift));
00887 dst[1] = saturate_cast<D>(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[3] + src.y * c_XYZ2sRGB_D65i[4] + src.z * c_XYZ2sRGB_D65i[5], xyz_shift));
00888 dst[bidx] = saturate_cast<D>(CV_DESCALE(src.x * c_XYZ2sRGB_D65i[6] + src.y * c_XYZ2sRGB_D65i[7] + src.z * c_XYZ2sRGB_D65i[8], xyz_shift));
00889 }
00890
00891 template <int bidx> static __device__ __forceinline__ uint XYZ2RGBConvert(uint src)
00892 {
00893 const int x = 0xff & src;
00894 const int y = 0xff & (src >> 8);
00895 const int z = 0xff & (src >> 16);
00896
00897 const uint r = saturate_cast<uchar>(CV_DESCALE(x * c_XYZ2sRGB_D65i[0] + y * c_XYZ2sRGB_D65i[1] + z * c_XYZ2sRGB_D65i[2], xyz_shift));
00898 const uint g = saturate_cast<uchar>(CV_DESCALE(x * c_XYZ2sRGB_D65i[3] + y * c_XYZ2sRGB_D65i[4] + z * c_XYZ2sRGB_D65i[5], xyz_shift));
00899 const uint b = saturate_cast<uchar>(CV_DESCALE(x * c_XYZ2sRGB_D65i[6] + y * c_XYZ2sRGB_D65i[7] + z * c_XYZ2sRGB_D65i[8], xyz_shift));
00900
00901 uint dst = 0xffu << 24;
00902
00903 dst |= b << (bidx * 8);
00904 dst |= g << 8;
00905 dst |= r << ((bidx ^ 2) * 8);
00906
00907 return dst;
00908 }
00909
00910 template <int bidx, typename T> static __device__ __forceinline__ void XYZ2RGBConvert(const T& src, float* dst)
00911 {
00912 dst[bidx^2] = src.x * c_XYZ2sRGB_D65f[0] + src.y * c_XYZ2sRGB_D65f[1] + src.z * c_XYZ2sRGB_D65f[2];
00913 dst[1] = src.x * c_XYZ2sRGB_D65f[3] + src.y * c_XYZ2sRGB_D65f[4] + src.z * c_XYZ2sRGB_D65f[5];
00914 dst[bidx] = src.x * c_XYZ2sRGB_D65f[6] + src.y * c_XYZ2sRGB_D65f[7] + src.z * c_XYZ2sRGB_D65f[8];
00915 }
00916
00917 template <typename T, int scn, int dcn, int bidx> struct XYZ2RGB
00918 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
00919 {
00920 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
00921 {
00922 typename TypeVec<T, dcn>::vec_type dst;
00923
00924 XYZ2RGBConvert<bidx>(src, &dst.x);
00925 setAlpha(dst, ColorChannel<T>::max());
00926
00927 return dst;
00928 }
00929 __device__ __forceinline__ XYZ2RGB()
00930 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00931 __device__ __forceinline__ XYZ2RGB(const XYZ2RGB& other_)
00932 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
00933 };
00934
00935 template <int bidx> struct XYZ2RGB<uchar, 4, 4, bidx> : unary_function<uint, uint>
00936 {
00937 __device__ __forceinline__ uint operator()(uint src) const
00938 {
00939 return XYZ2RGBConvert<bidx>(src);
00940 }
00941 __device__ __forceinline__ XYZ2RGB() : unary_function<uint, uint>(){}
00942 __device__ __forceinline__ XYZ2RGB(const XYZ2RGB& other_) : unary_function<uint, uint>(){}
00943 };
00944 }
00945
00946 #define OPENCV_GPU_IMPLEMENT_XYZ2RGB_TRAITS(name, scn, dcn, bidx) \
00947 template <typename T> struct name ## _traits \
00948 { \
00949 typedef ::cv::gpu::device::color_detail::XYZ2RGB<T, scn, dcn, bidx> functor_type; \
00950 static __host__ __device__ __forceinline__ functor_type create_functor() \
00951 { \
00952 return functor_type(); \
00953 } \
00954 };
00955
00957
00958 namespace color_detail
00959 {
00960 __constant__ int c_HsvDivTable [256] = {0, 1044480, 522240, 348160, 261120, 208896, 174080, 149211, 130560, 116053, 104448, 94953, 87040, 80345, 74606, 69632, 65280, 61440, 58027, 54973, 52224, 49737, 47476, 45412, 43520, 41779, 40172, 38684, 37303, 36017, 34816, 33693, 32640, 31651, 30720, 29842, 29013, 28229, 27486, 26782, 26112, 25475, 24869, 24290, 23738, 23211, 22706, 22223, 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};
00961 __constant__ int c_HsvDivTable180[256] = {0, 122880, 61440, 40960, 30720, 24576, 20480, 17554, 15360, 13653, 12288, 11171, 10240, 9452, 8777, 8192, 7680, 7228, 6827, 6467, 6144, 5851, 5585, 5343, 5120, 4915, 4726, 4551, 4389, 4237, 4096, 3964, 3840, 3724, 3614, 3511, 3413, 3321, 3234, 3151, 3072, 2997, 2926, 2858, 2793, 2731, 2671, 2614, 2560, 2508, 2458, 2409, 2363, 2318, 2276, 2234, 2194, 2156, 2119, 2083, 2048, 2014, 1982, 1950, 1920, 1890, 1862, 1834, 1807, 1781, 1755, 1731, 1707, 1683, 1661, 1638, 1617, 1596, 1575, 1555, 1536, 1517, 1499, 1480, 1463, 1446, 1429, 1412, 1396, 1381, 1365, 1350, 1336, 1321, 1307, 1293, 1280, 1267, 1254, 1241, 1229, 1217, 1205, 1193, 1182, 1170, 1159, 1148, 1138, 1127, 1117, 1107, 1097, 1087, 1078, 1069, 1059, 1050, 1041, 1033, 1024, 1016, 1007, 999, 991, 983, 975, 968, 960, 953, 945, 938, 931, 924, 917, 910, 904, 897, 890, 884, 878, 871, 865, 859, 853, 847, 842, 836, 830, 825, 819, 814, 808, 803, 798, 793, 788, 783, 778, 773, 768, 763, 759, 754, 749, 745, 740, 736, 731, 727, 723, 719, 714, 710, 706, 702, 698, 694, 690, 686, 683, 679, 675, 671, 668, 664, 661, 657, 654, 650, 647, 643, 640, 637, 633, 630, 627, 624, 621, 617, 614, 611, 608, 605, 602, 599, 597, 594, 591, 588, 585, 582, 580, 577, 574, 572, 569, 566, 564, 561, 559, 556, 554, 551, 549, 546, 544, 541, 539, 537, 534, 532, 530, 527, 525, 523, 521, 518, 516, 514, 512, 510, 508, 506, 504, 502, 500, 497, 495, 493, 492, 490, 488, 486, 484, 482};
00962 __constant__ int c_HsvDivTable256[256] = {0, 174763, 87381, 58254, 43691, 34953, 29127, 24966, 21845, 19418, 17476, 15888, 14564, 13443, 12483, 11651, 10923, 10280, 9709, 9198, 8738, 8322, 7944, 7598, 7282, 6991, 6722, 6473, 6242, 6026, 5825, 5638, 5461, 5296, 5140, 4993, 4855, 4723, 4599, 4481, 4369, 4263, 4161, 4064, 3972, 3884, 3799, 3718, 3641, 3567, 3495, 3427, 3361, 3297, 3236, 3178, 3121, 3066, 3013, 2962, 2913, 2865, 2819, 2774, 2731, 2689, 2648, 2608, 2570, 2533, 2497, 2461, 2427, 2394, 2362, 2330, 2300, 2270, 2241, 2212, 2185, 2158, 2131, 2106, 2081, 2056, 2032, 2009, 1986, 1964, 1942, 1920, 1900, 1879, 1859, 1840, 1820, 1802, 1783, 1765, 1748, 1730, 1713, 1697, 1680, 1664, 1649, 1633, 1618, 1603, 1589, 1574, 1560, 1547, 1533, 1520, 1507, 1494, 1481, 1469, 1456, 1444, 1432, 1421, 1409, 1398, 1387, 1376, 1365, 1355, 1344, 1334, 1324, 1314, 1304, 1295, 1285, 1276, 1266, 1257, 1248, 1239, 1231, 1222, 1214, 1205, 1197, 1189, 1181, 1173, 1165, 1157, 1150, 1142, 1135, 1128, 1120, 1113, 1106, 1099, 1092, 1085, 1079, 1072, 1066, 1059, 1053, 1046, 1040, 1034, 1028, 1022, 1016, 1010, 1004, 999, 993, 987, 982, 976, 971, 966, 960, 955, 950, 945, 940, 935, 930, 925, 920, 915, 910, 906, 901, 896, 892, 887, 883, 878, 874, 869, 865, 861, 857, 853, 848, 844, 840, 836, 832, 828, 824, 820, 817, 813, 809, 805, 802, 798, 794, 791, 787, 784, 780, 777, 773, 770, 767, 763, 760, 757, 753, 750, 747, 744, 741, 737, 734, 731, 728, 725, 722, 719, 716, 713, 710, 708, 705, 702, 699, 696, 694, 691, 688, 685};
00963
00964 template <int bidx, int hr, typename D> static __device__ void RGB2HSVConvert(const uchar* src, D& dst)
00965 {
00966 const int hsv_shift = 12;
00967 const int* hdiv_table = hr == 180 ? c_HsvDivTable180 : c_HsvDivTable256;
00968
00969 int b = src[bidx], g = src[1], r = src[bidx^2];
00970 int h, s, v = b;
00971 int vmin = b, diff;
00972 int vr, vg;
00973
00974 v = ::max(v, g);
00975 v = ::max(v, r);
00976 vmin = ::min(vmin, g);
00977 vmin = ::min(vmin, r);
00978
00979 diff = v - vmin;
00980 vr = (v == r) * -1;
00981 vg = (v == g) * -1;
00982
00983 s = (diff * c_HsvDivTable[v] + (1 << (hsv_shift-1))) >> hsv_shift;
00984 h = (vr & (g - b)) + (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
00985 h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
00986 h += (h < 0) * hr;
00987
00988 dst.x = saturate_cast<uchar>(h);
00989 dst.y = (uchar)s;
00990 dst.z = (uchar)v;
00991 }
00992
00993 template <int bidx, int hr> static __device__ uint RGB2HSVConvert(uint src)
00994 {
00995 const int hsv_shift = 12;
00996 const int* hdiv_table = hr == 180 ? c_HsvDivTable180 : c_HsvDivTable256;
00997
00998 const int b = 0xff & (src >> (bidx * 8));
00999 const int g = 0xff & (src >> 8);
01000 const int r = 0xff & (src >> ((bidx ^ 2) * 8));
01001
01002 int h, s, v = b;
01003 int vmin = b, diff;
01004 int vr, vg;
01005
01006 v = ::max(v, g);
01007 v = ::max(v, r);
01008 vmin = ::min(vmin, g);
01009 vmin = ::min(vmin, r);
01010
01011 diff = v - vmin;
01012 vr = (v == r) * -1;
01013 vg = (v == g) * -1;
01014
01015 s = (diff * c_HsvDivTable[v] + (1 << (hsv_shift-1))) >> hsv_shift;
01016 h = (vr & (g - b)) + (~vr & ((vg & (b - r + 2 * diff)) + ((~vg) & (r - g + 4 * diff))));
01017 h = (h * hdiv_table[diff] + (1 << (hsv_shift-1))) >> hsv_shift;
01018 h += (h < 0) * hr;
01019
01020 uint dst = 0;
01021
01022 dst |= saturate_cast<uchar>(h);
01023 dst |= (0xffu & s) << 8;
01024 dst |= (0xffu & v) << 16;
01025
01026 return dst;
01027 }
01028
01029 template <int bidx, int hr, typename D> static __device__ void RGB2HSVConvert(const float* src, D& dst)
01030 {
01031 const float hscale = hr * (1.f / 360.f);
01032
01033 float b = src[bidx], g = src[1], r = src[bidx^2];
01034 float h, s, v;
01035
01036 float vmin, diff;
01037
01038 v = vmin = r;
01039 v = fmax(v, g);
01040 v = fmax(v, b);
01041 vmin = fmin(vmin, g);
01042 vmin = fmin(vmin, b);
01043
01044 diff = v - vmin;
01045 s = diff / (float)(::fabs(v) + numeric_limits<float>::epsilon());
01046 diff = (float)(60. / (diff + numeric_limits<float>::epsilon()));
01047
01048 h = (v == r) * (g - b) * diff;
01049 h += (v != r && v == g) * ((b - r) * diff + 120.f);
01050 h += (v != r && v != g) * ((r - g) * diff + 240.f);
01051 h += (h < 0) * 360.f;
01052
01053 dst.x = h * hscale;
01054 dst.y = s;
01055 dst.z = v;
01056 }
01057
01058 template <typename T, int scn, int dcn, int bidx, int hr> struct RGB2HSV
01059 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
01060 {
01061 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
01062 {
01063 typename TypeVec<T, dcn>::vec_type dst;
01064
01065 RGB2HSVConvert<bidx, hr>(&src.x, dst);
01066
01067 return dst;
01068 }
01069 __device__ __forceinline__ RGB2HSV()
01070 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01071 __device__ __forceinline__ RGB2HSV(const RGB2HSV& other_)
01072 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01073 };
01074
01075 template <int bidx, int hr> struct RGB2HSV<uchar, 4, 4, bidx, hr> : unary_function<uint, uint>
01076 {
01077 __device__ __forceinline__ uint operator()(uint src) const
01078 {
01079 return RGB2HSVConvert<bidx, hr>(src);
01080 }
01081 __device__ __forceinline__ RGB2HSV():unary_function<uint, uint>(){}
01082 __device__ __forceinline__ RGB2HSV(const RGB2HSV& other_):unary_function<uint, uint>(){}
01083 };
01084 }
01085
01086 #define OPENCV_GPU_IMPLEMENT_RGB2HSV_TRAITS(name, scn, dcn, bidx) \
01087 template <typename T> struct name ## _traits \
01088 { \
01089 typedef ::cv::gpu::device::color_detail::RGB2HSV<T, scn, dcn, bidx, 180> functor_type; \
01090 static __host__ __device__ __forceinline__ functor_type create_functor() \
01091 { \
01092 return functor_type(); \
01093 } \
01094 }; \
01095 template <typename T> struct name ## _full_traits \
01096 { \
01097 typedef ::cv::gpu::device::color_detail::RGB2HSV<T, scn, dcn, bidx, 256> functor_type; \
01098 static __host__ __device__ __forceinline__ functor_type create_functor() \
01099 { \
01100 return functor_type(); \
01101 } \
01102 }; \
01103 template <> struct name ## _traits<float> \
01104 { \
01105 typedef ::cv::gpu::device::color_detail::RGB2HSV<float, scn, dcn, bidx, 360> functor_type; \
01106 static __host__ __device__ __forceinline__ functor_type create_functor() \
01107 { \
01108 return functor_type(); \
01109 } \
01110 }; \
01111 template <> struct name ## _full_traits<float> \
01112 { \
01113 typedef ::cv::gpu::device::color_detail::RGB2HSV<float, scn, dcn, bidx, 360> functor_type; \
01114 static __host__ __device__ __forceinline__ functor_type create_functor() \
01115 { \
01116 return functor_type(); \
01117 } \
01118 };
01119
01120 namespace color_detail
01121 {
01122 __constant__ int c_HsvSectorData[6][3] = { {1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0} };
01123
01124 template <int bidx, int hr, typename T> static __device__ void HSV2RGBConvert(const T& src, float* dst)
01125 {
01126 const float hscale = 6.f / hr;
01127
01128 float h = src.x, s = src.y, v = src.z;
01129 float b = v, g = v, r = v;
01130
01131 if (s != 0)
01132 {
01133 h *= hscale;
01134
01135 if( h < 0 )
01136 do h += 6; while( h < 0 );
01137 else if( h >= 6 )
01138 do h -= 6; while( h >= 6 );
01139
01140 int sector = __float2int_rd(h);
01141 h -= sector;
01142
01143 if ( (unsigned)sector >= 6u )
01144 {
01145 sector = 0;
01146 h = 0.f;
01147 }
01148
01149 float tab[4];
01150 tab[0] = v;
01151 tab[1] = v * (1.f - s);
01152 tab[2] = v * (1.f - s * h);
01153 tab[3] = v * (1.f - s * (1.f - h));
01154
01155 b = tab[c_HsvSectorData[sector][0]];
01156 g = tab[c_HsvSectorData[sector][1]];
01157 r = tab[c_HsvSectorData[sector][2]];
01158 }
01159
01160 dst[bidx] = b;
01161 dst[1] = g;
01162 dst[bidx^2] = r;
01163 }
01164
01165 template <int bidx, int HR, typename T> static __device__ void HSV2RGBConvert(const T& src, uchar* dst)
01166 {
01167 float3 buf;
01168
01169 buf.x = src.x;
01170 buf.y = src.y * (1.f / 255.f);
01171 buf.z = src.z * (1.f / 255.f);
01172
01173 HSV2RGBConvert<bidx, HR>(buf, &buf.x);
01174
01175 dst[0] = saturate_cast<uchar>(buf.x * 255.f);
01176 dst[1] = saturate_cast<uchar>(buf.y * 255.f);
01177 dst[2] = saturate_cast<uchar>(buf.z * 255.f);
01178 }
01179
01180 template <int bidx, int hr> static __device__ uint HSV2RGBConvert(uint src)
01181 {
01182 float3 buf;
01183
01184 buf.x = src & 0xff;
01185 buf.y = ((src >> 8) & 0xff) * (1.f/255.f);
01186 buf.z = ((src >> 16) & 0xff) * (1.f/255.f);
01187
01188 HSV2RGBConvert<bidx, hr>(buf, &buf.x);
01189
01190 uint dst = 0xffu << 24;
01191
01192 dst |= saturate_cast<uchar>(buf.x * 255.f);
01193 dst |= saturate_cast<uchar>(buf.y * 255.f) << 8;
01194 dst |= saturate_cast<uchar>(buf.z * 255.f) << 16;
01195
01196 return dst;
01197 }
01198
01199 template <typename T, int scn, int dcn, int bidx, int hr> struct HSV2RGB
01200 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
01201 {
01202 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
01203 {
01204 typename TypeVec<T, dcn>::vec_type dst;
01205
01206 HSV2RGBConvert<bidx, hr>(src, &dst.x);
01207 setAlpha(dst, ColorChannel<T>::max());
01208
01209 return dst;
01210 }
01211 __device__ __forceinline__ HSV2RGB()
01212 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01213 __device__ __forceinline__ HSV2RGB(const HSV2RGB& other_)
01214 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01215 };
01216
01217 template <int bidx, int hr> struct HSV2RGB<uchar, 4, 4, bidx, hr> : unary_function<uint, uint>
01218 {
01219 __device__ __forceinline__ uint operator()(uint src) const
01220 {
01221 return HSV2RGBConvert<bidx, hr>(src);
01222 }
01223 __device__ __forceinline__ HSV2RGB():unary_function<uint, uint>(){}
01224 __device__ __forceinline__ HSV2RGB(const HSV2RGB& other_):unary_function<uint, uint>(){}
01225 };
01226 }
01227
01228 #define OPENCV_GPU_IMPLEMENT_HSV2RGB_TRAITS(name, scn, dcn, bidx) \
01229 template <typename T> struct name ## _traits \
01230 { \
01231 typedef ::cv::gpu::device::color_detail::HSV2RGB<T, scn, dcn, bidx, 180> functor_type; \
01232 static __host__ __device__ __forceinline__ functor_type create_functor() \
01233 { \
01234 return functor_type(); \
01235 } \
01236 }; \
01237 template <typename T> struct name ## _full_traits \
01238 { \
01239 typedef ::cv::gpu::device::color_detail::HSV2RGB<T, scn, dcn, bidx, 255> functor_type; \
01240 static __host__ __device__ __forceinline__ functor_type create_functor() \
01241 { \
01242 return functor_type(); \
01243 } \
01244 }; \
01245 template <> struct name ## _traits<float> \
01246 { \
01247 typedef ::cv::gpu::device::color_detail::HSV2RGB<float, scn, dcn, bidx, 360> functor_type; \
01248 static __host__ __device__ __forceinline__ functor_type create_functor() \
01249 { \
01250 return functor_type(); \
01251 } \
01252 }; \
01253 template <> struct name ## _full_traits<float> \
01254 { \
01255 typedef ::cv::gpu::device::color_detail::HSV2RGB<float, scn, dcn, bidx, 360> functor_type; \
01256 static __host__ __device__ __forceinline__ functor_type create_functor() \
01257 { \
01258 return functor_type(); \
01259 } \
01260 };
01261
01263
01264 namespace color_detail
01265 {
01266 template <int bidx, int hr, typename D> static __device__ void RGB2HLSConvert(const float* src, D& dst)
01267 {
01268 const float hscale = hr * (1.f / 360.f);
01269
01270 float b = src[bidx], g = src[1], r = src[bidx^2];
01271 float h = 0.f, s = 0.f, l;
01272 float vmin, vmax, diff;
01273
01274 vmax = vmin = r;
01275 vmax = fmax(vmax, g);
01276 vmax = fmax(vmax, b);
01277 vmin = fmin(vmin, g);
01278 vmin = fmin(vmin, b);
01279
01280 diff = vmax - vmin;
01281 l = (vmax + vmin) * 0.5f;
01282
01283 if (diff > numeric_limits<float>::epsilon())
01284 {
01285 s = (l < 0.5f) * diff / (vmax + vmin);
01286 s += (l >= 0.5f) * diff / (2.0f - vmax - vmin);
01287
01288 diff = 60.f / diff;
01289
01290 h = (vmax == r) * (g - b) * diff;
01291 h += (vmax != r && vmax == g) * ((b - r) * diff + 120.f);
01292 h += (vmax != r && vmax != g) * ((r - g) * diff + 240.f);
01293 h += (h < 0.f) * 360.f;
01294 }
01295
01296 dst.x = h * hscale;
01297 dst.y = l;
01298 dst.z = s;
01299 }
01300
01301 template <int bidx, int hr, typename D> static __device__ void RGB2HLSConvert(const uchar* src, D& dst)
01302 {
01303 float3 buf;
01304
01305 buf.x = src[0] * (1.f / 255.f);
01306 buf.y = src[1] * (1.f / 255.f);
01307 buf.z = src[2] * (1.f / 255.f);
01308
01309 RGB2HLSConvert<bidx, hr>(&buf.x, buf);
01310
01311 dst.x = saturate_cast<uchar>(buf.x);
01312 dst.y = saturate_cast<uchar>(buf.y*255.f);
01313 dst.z = saturate_cast<uchar>(buf.z*255.f);
01314 }
01315
01316 template <int bidx, int hr> static __device__ uint RGB2HLSConvert(uint src)
01317 {
01318 float3 buf;
01319
01320 buf.x = (0xff & src) * (1.f / 255.f);
01321 buf.y = (0xff & (src >> 8)) * (1.f / 255.f);
01322 buf.z = (0xff & (src >> 16)) * (1.f / 255.f);
01323
01324 RGB2HLSConvert<bidx, hr>(&buf.x, buf);
01325
01326 uint dst = 0xffu << 24;
01327
01328 dst |= saturate_cast<uchar>(buf.x);
01329 dst |= saturate_cast<uchar>(buf.y * 255.f) << 8;
01330 dst |= saturate_cast<uchar>(buf.z * 255.f) << 16;
01331
01332 return dst;
01333 }
01334
01335 template <typename T, int scn, int dcn, int bidx, int hr> struct RGB2HLS
01336 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
01337 {
01338 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
01339 {
01340 typename TypeVec<T, dcn>::vec_type dst;
01341
01342 RGB2HLSConvert<bidx, hr>(&src.x, dst);
01343
01344 return dst;
01345 }
01346 __device__ __forceinline__ RGB2HLS()
01347 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01348 __device__ __forceinline__ RGB2HLS(const RGB2HLS& other_)
01349 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01350 };
01351
01352 template <int bidx, int hr> struct RGB2HLS<uchar, 4, 4, bidx, hr> : unary_function<uint, uint>
01353 {
01354 __device__ __forceinline__ uint operator()(uint src) const
01355 {
01356 return RGB2HLSConvert<bidx, hr>(src);
01357 }
01358 __device__ __forceinline__ RGB2HLS() : unary_function<uint, uint>(){}
01359 __device__ __forceinline__ RGB2HLS(const RGB2HLS& other_) : unary_function<uint, uint>(){}
01360 };
01361 }
01362
01363 #define OPENCV_GPU_IMPLEMENT_RGB2HLS_TRAITS(name, scn, dcn, bidx) \
01364 template <typename T> struct name ## _traits \
01365 { \
01366 typedef ::cv::gpu::device::color_detail::RGB2HLS<T, scn, dcn, bidx, 180> functor_type; \
01367 static __host__ __device__ __forceinline__ functor_type create_functor() \
01368 { \
01369 return functor_type(); \
01370 } \
01371 }; \
01372 template <typename T> struct name ## _full_traits \
01373 { \
01374 typedef ::cv::gpu::device::color_detail::RGB2HLS<T, scn, dcn, bidx, 256> functor_type; \
01375 static __host__ __device__ __forceinline__ functor_type create_functor() \
01376 { \
01377 return functor_type(); \
01378 } \
01379 }; \
01380 template <> struct name ## _traits<float> \
01381 { \
01382 typedef ::cv::gpu::device::color_detail::RGB2HLS<float, scn, dcn, bidx, 360> functor_type; \
01383 static __host__ __device__ __forceinline__ functor_type create_functor() \
01384 { \
01385 return functor_type(); \
01386 } \
01387 }; \
01388 template <> struct name ## _full_traits<float> \
01389 { \
01390 typedef ::cv::gpu::device::color_detail::RGB2HLS<float, scn, dcn, bidx, 360> functor_type; \
01391 static __host__ __device__ __forceinline__ functor_type create_functor() \
01392 { \
01393 return functor_type(); \
01394 } \
01395 };
01396
01397 namespace color_detail
01398 {
01399 __constant__ int c_HlsSectorData[6][3] = { {1,3,0}, {1,0,2}, {3,0,1}, {0,2,1}, {0,1,3}, {2,1,0} };
01400
01401 template <int bidx, int hr, typename T> static __device__ void HLS2RGBConvert(const T& src, float* dst)
01402 {
01403 const float hscale = 6.0f / hr;
01404
01405 float h = src.x, l = src.y, s = src.z;
01406 float b = l, g = l, r = l;
01407
01408 if (s != 0)
01409 {
01410 float p2 = (l <= 0.5f) * l * (1 + s);
01411 p2 += (l > 0.5f) * (l + s - l * s);
01412 float p1 = 2 * l - p2;
01413
01414 h *= hscale;
01415
01416 if( h < 0 )
01417 do h += 6; while( h < 0 );
01418 else if( h >= 6 )
01419 do h -= 6; while( h >= 6 );
01420
01421 int sector;
01422 sector = __float2int_rd(h);
01423
01424 h -= sector;
01425
01426 float tab[4];
01427 tab[0] = p2;
01428 tab[1] = p1;
01429 tab[2] = p1 + (p2 - p1) * (1 - h);
01430 tab[3] = p1 + (p2 - p1) * h;
01431
01432 b = tab[c_HlsSectorData[sector][0]];
01433 g = tab[c_HlsSectorData[sector][1]];
01434 r = tab[c_HlsSectorData[sector][2]];
01435 }
01436
01437 dst[bidx] = b;
01438 dst[1] = g;
01439 dst[bidx^2] = r;
01440 }
01441
01442 template <int bidx, int hr, typename T> static __device__ void HLS2RGBConvert(const T& src, uchar* dst)
01443 {
01444 float3 buf;
01445
01446 buf.x = src.x;
01447 buf.y = src.y * (1.f / 255.f);
01448 buf.z = src.z * (1.f / 255.f);
01449
01450 HLS2RGBConvert<bidx, hr>(buf, &buf.x);
01451
01452 dst[0] = saturate_cast<uchar>(buf.x * 255.f);
01453 dst[1] = saturate_cast<uchar>(buf.y * 255.f);
01454 dst[2] = saturate_cast<uchar>(buf.z * 255.f);
01455 }
01456
01457 template <int bidx, int hr> static __device__ uint HLS2RGBConvert(uint src)
01458 {
01459 float3 buf;
01460
01461 buf.x = 0xff & src;
01462 buf.y = (0xff & (src >> 8)) * (1.f / 255.f);
01463 buf.z = (0xff & (src >> 16)) * (1.f / 255.f);
01464
01465 HLS2RGBConvert<bidx, hr>(buf, &buf.x);
01466
01467 uint dst = 0xffu << 24;
01468
01469 dst |= saturate_cast<uchar>(buf.x * 255.f);
01470 dst |= saturate_cast<uchar>(buf.y * 255.f) << 8;
01471 dst |= saturate_cast<uchar>(buf.z * 255.f) << 16;
01472
01473 return dst;
01474 }
01475
01476 template <typename T, int scn, int dcn, int bidx, int hr> struct HLS2RGB
01477 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>
01478 {
01479 __device__ __forceinline__ typename TypeVec<T, dcn>::vec_type operator()(const typename TypeVec<T, scn>::vec_type& src) const
01480 {
01481 typename TypeVec<T, dcn>::vec_type dst;
01482
01483 HLS2RGBConvert<bidx, hr>(src, &dst.x);
01484 setAlpha(dst, ColorChannel<T>::max());
01485
01486 return dst;
01487 }
01488 __device__ __forceinline__ HLS2RGB()
01489 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01490 __device__ __forceinline__ HLS2RGB(const HLS2RGB& other_)
01491 : unary_function<typename TypeVec<T, scn>::vec_type, typename TypeVec<T, dcn>::vec_type>(){}
01492 };
01493
01494 template <int bidx, int hr> struct HLS2RGB<uchar, 4, 4, bidx, hr> : unary_function<uint, uint>
01495 {
01496 __device__ __forceinline__ uint operator()(uint src) const
01497 {
01498 return HLS2RGBConvert<bidx, hr>(src);
01499 }
01500 __device__ __forceinline__ HLS2RGB() : unary_function<uint, uint>(){}
01501 __device__ __forceinline__ HLS2RGB(const HLS2RGB& other_) : unary_function<uint, uint>(){}
01502 };
01503 }
01504
01505 #define OPENCV_GPU_IMPLEMENT_HLS2RGB_TRAITS(name, scn, dcn, bidx) \
01506 template <typename T> struct name ## _traits \
01507 { \
01508 typedef ::cv::gpu::device::color_detail::HLS2RGB<T, scn, dcn, bidx, 180> functor_type; \
01509 static __host__ __device__ __forceinline__ functor_type create_functor() \
01510 { \
01511 return functor_type(); \
01512 } \
01513 }; \
01514 template <typename T> struct name ## _full_traits \
01515 { \
01516 typedef ::cv::gpu::device::color_detail::HLS2RGB<T, scn, dcn, bidx, 255> functor_type; \
01517 static __host__ __device__ __forceinline__ functor_type create_functor() \
01518 { \
01519 return functor_type(); \
01520 } \
01521 }; \
01522 template <> struct name ## _traits<float> \
01523 { \
01524 typedef ::cv::gpu::device::color_detail::HLS2RGB<float, scn, dcn, bidx, 360> functor_type; \
01525 static __host__ __device__ __forceinline__ functor_type create_functor() \
01526 { \
01527 return functor_type(); \
01528 } \
01529 }; \
01530 template <> struct name ## _full_traits<float> \
01531 { \
01532 typedef ::cv::gpu::device::color_detail::HLS2RGB<float, scn, dcn, bidx, 360> functor_type; \
01533 static __host__ __device__ __forceinline__ functor_type create_functor() \
01534 { \
01535 return functor_type(); \
01536 } \
01537 };
01538
01539 #undef CV_DESCALE
01540 }}}
01541
01542 #endif // __OPENCV_GPU_COLOR_DETAIL_HPP__