OpenCV中的cvtColor函数包括了很多颜色格式之间的转换,用起来很方便,这里对cvtColor函数的code进行了提取,经测试,和OpenCV3.1结果完全一致。
实现代码cvtColor.hpp:
// fbc_cv is free software and uses the same licence as OpenCV// Email: fengbingchun@163.com#ifndef FBC_CV_CVTCOLOR_HPP_#define FBC_CV_CVTCOLOR_HPP_// reference: include/opencv2/imgproc.hpp#include "core/mat.hpp"#include "core/saturate.hpp"#include "imgproc.hpp"#include "core/core.hpp"namespace fbc {
#define FBC_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n))template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2Gray(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_Gray2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2YCrCb(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs_f, const int* coeffs_i);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_YCrCb2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs_f, const int* coeffs_i);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2XYZ(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_XYZ2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2HSV(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2HLS(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_HSV2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_HLS2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, int hrange);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2Lab(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_RGB2Luv(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_Lab2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb);template<typename _Tp, int chs1, int chs2> static int CvtColorLoop_Luv2RGB(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int bidx, const float* coeffs, const float* whitept, bool srgb);// Converts an image from one color space to another// support type: uchar/ushort/floattemplate<typename _Tp, int chs1, int chs2>int cvtColor(const Mat_<_Tp, chs1>& src, Mat_<_Tp, chs2>& dst, int code){ FBC_Assert(src.cols > 0 && src.rows > 0 && dst.cols > 0 && dst.rows > 0); FBC_Assert(src.cols == dst.cols); FBC_Assert(src.data != NULL && dst.data != NULL); FBC_Assert((sizeof(_Tp) == 1) || sizeof(_Tp) == 2 || sizeof(_Tp) == 4); // uchar || ushort || float int scn = src.channels; int dcn = dst.channels; // number of channels in the destination image Size sz = src.size(); Size dz = dst.size(); int bidx; switch (code) { case CV_BGR2BGRA: case CV_RGB2BGRA: case CV_BGRA2BGR: case CV_RGBA2BGR: case CV_RGB2BGR: case CV_BGRA2RGBA: { FBC_Assert(scn == 3 || scn == 4); dcn = code == CV_BGR2BGRA || code == CV_RGB2BGRA || code == CV_BGRA2RGBA ? 4 : 3; FBC_Assert(dst.channels == dcn); bidx = code == CV_BGR2BGRA || code == CV_BGRA2BGR ? 0 : 2; CvtColorLoop_RGB2RGB(src, dst, bidx); // uchar/ushort/float break; } case CV_BGR2GRAY: case CV_BGRA2GRAY: case CV_RGB2GRAY: case CV_RGBA2GRAY: { FBC_Assert(scn == 3 || scn == 4); FBC_Assert(dst.channels == 1); bidx = code == CV_BGR2GRAY || code == CV_BGRA2GRAY ? 0 : 2; CvtColorLoop_RGB2Gray(src, dst, bidx); break; } case CV_GRAY2BGR: case CV_GRAY2BGRA: { FBC_Assert(scn == 1 && (dcn == 3 || dcn == 4)); CvtColorLoop_Gray2RGB(src, dst); break; } case CV_BGR2YCrCb: case CV_RGB2YCrCb: case CV_BGR2YUV: case CV_RGB2YUV: { FBC_Assert(scn == 3 || scn == 4); bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2; static const float yuv_f[] = { 0.114f, 0.587f, 0.299f, 0.492f, 0.877f }; static const int yuv_i[] = { B2Y, G2Y, R2Y, 8061, 14369 }; const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f; const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i; CvtColorLoop_RGB2YCrCb(src, dst, bidx, coeffs_f, coeffs_i); break; } case CV_YCrCb2BGR: case CV_YCrCb2RGB: case CV_YUV2BGR: case CV_YUV2RGB: { FBC_Assert(scn == 3 && (dcn == 3 || dcn == 4)); bidx = code == CV_YCrCb2BGR || code == CV_YUV2BGR ? 0 : 2; static const float yuv_f[] = { 2.032f, -0.395f, -0.581f, 1.140f }; static const int yuv_i[] = { 33292, -6472, -9519, 18678 }; const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f; const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i; CvtColorLoop_YCrCb2RGB(src, dst, bidx, coeffs_f, coeffs_i); break; } case CV_BGR2XYZ: case CV_RGB2XYZ: { FBC_Assert(scn == 3 || scn == 4); bidx = code == CV_BGR2XYZ ? 0 : 2; CvtColorLoop_RGB2XYZ(src, dst, bidx); break; } case CV_XYZ2BGR: case CV_XYZ2RGB: { FBC_Assert(scn == 3 && (dcn == 3 || dcn == 4)); bidx = code == CV_XYZ2BGR ? 0 : 2; CvtColorLoop_XYZ2RGB(src, dst, bidx); break; } case CV_BGR2HSV: case CV_RGB2HSV: case CV_BGR2HSV_FULL: case CV_RGB2HSV_FULL: case CV_BGR2HLS: case CV_RGB2HLS: case CV_BGR2HLS_FULL: case CV_RGB2HLS_FULL: { FBC_Assert(scn == 3 || scn == 4); FBC_Assert(sizeof(_Tp) == 1 || sizeof(_Tp) == 4); bidx = code == CV_BGR2HSV || code == CV_BGR2HLS || code == CV_BGR2HSV_FULL || code == CV_BGR2HLS_FULL ? 0 : 2; int hrange = sizeof(_Tp) == 4 ? 360 : code == CV_BGR2HSV || code == CV_RGB2HSV || code == CV_BGR2HLS || code == CV_RGB2HLS ? 180 : 256; if (code == CV_BGR2HSV || code == CV_RGB2HSV || code == CV_BGR2HSV_FULL || code == CV_RGB2HSV_FULL) { CvtColorLoop_RGB2HSV(src, dst, bidx, hrange); } else { CvtColorLoop_RGB2HLS(src, dst, bidx, hrange); } break; } case CV_HSV2BGR: case CV_HSV2RGB: case CV_HSV2BGR_FULL: case CV_HSV2RGB_FULL: case CV_H