,系数介绍,可参考http://baike.baidu.com/view/640197.htm?fr=aladdin
经过对源码的阅读,对源码做如下改写:
</pre><pre name="code" class="cpp">enum { R2Y = 4899, G2Y = 9617, B2Y = 1868, };
inline void RGB2YCrCb_i(int blueIdx, int coeffs[], const int* _coeffs) { static const int coeffs0[] = {R2Y, G2Y, B2Y, 11682, 9241};//CV_BGR2YUV对应的系数 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0])); if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);//对应的code 为CV_BRG2YCrCv时, 将CV_BGR2YUV对应的系数的R2y(4899)与B2y(1868)对应的值互换 }
inline void Operater_YCrCb_i(unsigned char* src,int srccn, int blueId, int coeffs[], unsigned char* dst, int n) { int scn = srccn, bidx = blueId; int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4]; ColorChannel cc; int delta = cc.half()*(1<<yuv_shift); n *= 3; for (int i=0; i<n; i += 3, src += scn) { int Y = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, yuv_shift); int Cr = CV_DESCALE((src[bidx^2] - Y)*C3 + delta, yuv_shift); int Cb = CV_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift); dst[i] = (unsigned char)(Y); dst[i+1] = (unsigned char)(Cr); dst[i+2] = (unsigned char)(Cb); } } void CvtColor_YCrCb_i(unsigned char* src, int sstep, unsigned char* dst, int dstep, int nWidth, int nHeight, int nChannel, int code, int dcn) { assert(nWidth >=0 && nHeight >= 0); int scn = nChannel, bidx; unsigned char* src_ptr = NULL; unsigned char* dst_ptr = NULL; switch(code) { case CV_BGR2YCrCb: case CV_RGB2YCrCb: case CV_BGR2YUV: case CV_RGB2YUV: assert(scn == 3 || scn == 4); bidx = code == CV_BGR2YCrCb || code == CV_RGB2YUV ? 0 : 2; static const int yuv_i[]= {B2Y, G2Y, R2Y, 8061, 14369}; const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i; for (int row = 0; row < nHeight; row++) { src_ptr = (unsigned char*)(src + row*sstep); dst_ptr = (unsigned char*)(dst + row*dstep); for (int col = 0; col < nWidth; col++) { int coeffs[5]; RGB2YCrCb_i(bidx, coeffs,coeffs_i ); Operater_YCrCb_i(src_ptr, scn, bidx, coeffs, dst_ptr, nWidth*nHeight/(double(1<<16))); src_ptr += 3; dst_ptr += 3; } } } }
维基百科中关于rgb->yuv 和rgb->ycbcr的具体介绍为:
详细内容可参考 http://zh.wikipedia.org/wiki/YUV
及http://blog.sina.com.cn/s/blog_4665b35b0100vf6r.html
附整个改写的代码部分:
#ifndef _RGB2YUV_H_ #define _RGB2YUV_H_ #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <math.h> #include <assert.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <limits.h> #include <float.h> using namespace std; using namespace cv; #undef R2Y #undef G2Y #undef B2Y #define CV_DESCALE(x,n) (((x) + (1 << ((n)-1))) >> (n)) enum { yuv_shift = 14, xyz_shift = 12, R2Y = 4899, G2Y = 9617, B2Y = 1868, BLOCK_SIZE = 256 }; struct ColorChannel { typedef float worktype_f; static uchar max() { return std::numeric_limits<uchar>::max(); } static uchar half() { return (uchar)(max()/2 + 1); } }; inline void RGB2YCrCb_i( int blueId, int coeffs[], const int* _coeffs); inline void Operater_YCrCb_i(unsigned char* src,int srccn, int blueId, int coeffs[], unsigned char* dst, int n); void CvtColor_YCrCb_i(unsigned char* src, int sstep, unsigned char* dst, int dstep, int nWidth, int nHeight, int nChannel, int code, int dcn = 0); #endif
#include "rgb2yuv.h" inline void RGB2YCrCb_i(int blueIdx, int coeffs[], const int* _coeffs) { static const int coeffs0[] = {R2Y, G2Y, B2Y, 11682, 9241};//CV_BGR2YUV对应的系数 memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0])); if(blueIdx==0) std::swap(coeffs[0], coeffs[2]);//对应的code 为CV_BRG2YCrCv时, 将CV_BGR2YUV对应的系数的R2y(4899)与B2y(1868)对应的值互换 } inline void Operater_YCrCb_i(unsigned char* src,int srccn, int blueId, int coeffs[], unsigned char* dst, int n) { int scn = srccn, bidx = blueId; int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4]; ColorChannel cc; int delta = cc.half()*(1<<yuv_shift); n *= 3; for (int i=0; i<n; i += 3, src += scn) { int Y = CV_DESCALE(src[0]*C0 + src[1]*C1 + src[2]*C2, yuv_shift); int Cr = CV_DESCALE((src[bidx^2] - Y)*C3 + delta, yuv_shift); int Cb = CV_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift); dst[i] = (unsigned char)(Y); dst[i+1] = (unsigned char)(Cr); dst[i+2] = (unsigned char)(Cb); } } void CvtColor_YCrCb_i(unsigned char* src, int sstep, unsigned char* dst, int dstep, int nWidth, int nHeight, int nChannel, int code, int dcn) { assert(nWidth >=0 && nHeight >= 0); int scn = nChannel, bidx; unsigned char* src_ptr = NULL; unsigned char* dst_ptr = NULL; switch(code) { case CV_BGR2YCrCb: case CV_RGB2YCrCb: case CV_BGR2YUV: case CV_RGB2YUV: assert(scn == 3 || scn == 4); bidx = code == CV_BGR2YCrCb || code == CV_RGB2YUV ? 0 : 2; static const int yuv_i[]= {B2Y, G2Y, R2Y, 8061, 14369}; const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i; for (int row = 0; row < nHeight; row++) { src_ptr = (unsigned char*)(src + row*sstep); dst_ptr = (unsigned char*)(dst + row*dstep); for (int col = 0; col < nWidth; col++) { int coeffs[5]; RGB2YCrCb_i(bidx, coeffs,coeffs_i ); Operater_YCrCb_i(src_ptr, scn, bidx, coeffs, dst_ptr, nWidth*nHeight/(double(1<<16))); src_ptr += 3; dst_ptr += 3; } } } }