,系数介绍,可参考http://baike.baidu.com/view/640197.htm?fr=aladdin
经过对源码的阅读,对源码做如下改写:
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<=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
#include
#include
#include
#include
#include
#include
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::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<=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;
}
}
}
}