关于YUV420转换成RGB565问题

gooogleman 2010-11-02 11:19:28
我的数据出来时YUV420,Y,U,V存在不同的数组当中

现在要转换成RGB565保存成BMP图像

现在发现图像很怪异,我觉得是我在转换的过程中出现了问题。
我觉得是我没有搞清楚如下东西:

1、YUV420 的Y,U,v三个长度是不一样的,按照道理Y=4*U=4*V 那么在转换的过程中,RGB应该如何应对?怎么样做到对应?
开始我采用相同的方式递增,现在发现不对啊。
请问各位,这个应该如何转换呢?
我的这个方法明显不符合道理啊。

for(i=0;i<width*height*2;i++) {
//*RData++=YCbCrtoR(*YData++,*CbData++,*CbData++);
//*GData++=YCbCrtoG(*YData++,*CbData++,*CbData++);
//*BData++=YCbCrtoB(*YData++,*CbData++,*CbData++);
RData[i]=YCbCrtoR(YData[i],CbData[i],CbData[i]);
GData[i]=YCbCrtoG(YData[i],CbData[i],CbData[i]);
BData[i]=YCbCrtoB(YData[i],CbData[i],CbData[i]);
//--------------------2010.10.26-------------------

if (RData[i]>255) RData[i]=255; if (RData[i]<0) RData[i]=0;
if (GData[i]>255) GData[i]=255; if (GData[i]<0) GData[i]=0;
if (BData[i]>255) BData[i]=255; if (BData[i]<0) BData[i]=0;
//RGB565
//DDBdata[i]=(RData[i]<<11)+(GData[i]<<5)+(BData[i]); // wrong
TempDDBdata[i]=((RData[i])<<11)|((GData[i])<<5)|(BData[i]);
//RETAILMSG(1,(_T("DDBdata[i] = 0x%x\r\n"), DDBdata[i]));
}
明显是不合理的,god!
各位,从未接触这些,请大家明示啊。呵呵
...全文
279 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
nbhx2010 2010-11-06
  • 打赏
  • 举报
回复
顶,这种有意义,我当时也问过
wdove 2010-11-05
  • 打赏
  • 举报
回复
很有研究头
gooogleman 2010-11-04
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 kacassi 的回复:]
貌似应该是这样:
for(i=0;i<UV_Size;i++) {
RData[i]=YCbCrtoR(YData[i],CbData[i],CbData[i]);
GData[i]=YCbCrtoG(YData[i],CbData[i],CbData[i]);
BData[i]=YCbCrtoB(YData[i],CbData[i],CbData[i]);

RDat……
[/Quote]

和这个描述的不一样,不对啊
b c d
e f g h
Ya = Y0, Ua = U0, Va = V0
Yb = Y1, Ub = U0, Vb = V0
Yc = Y2, Uc = U1, Vc = V1
Yd = Y3, Ud = U1, Vd = V1
Ye = Y4, Ue = U0, Ve = V0
Yf = Y5, Uf = U0, Vf = V0
Yg = Y6, Ug = U1, Vg = V1
Yh = Y7, Uh = U1, Vh = V1
gooogleman 2010-11-04
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 tufaqing 的回复:]
其他地方看不出什么问题,除了YUV都rgb的快速转换部分的算法,不太确定对不对。
[/Quote]
多谢!
我晕,其实已经完全正常的了!是摄像头问题,摄像头对着日光灯,效果会很糟糕!
现在我对着显示器拍照一切正常了
tufaqing 2010-11-04
  • 打赏
  • 举报
回复
其他地方看不出什么问题,除了YUV都rgb的快速转换部分的算法,不太确定对不对。
gooogleman 2010-11-04
  • 打赏
  • 举报
回复
现在换成如下算法,有点进展,不过图像偏黑了。不知道咋回事。
代码如下,各位看看有什么问题。

//
//---------------------------------2010.11.04-------------------------------------------
//


void yuv420_to_rgb565(int width, int height, unsigned char *src, unsigned short *dst)
{
int line, col, linewidth;
int y, u, v, yy, vr, ug, vg, ub;
int r, g, b;
const unsigned char *py, *pu, *pv;

linewidth = width >> 1;
py = src;
pu = py + (width * height);
pv = pu + (width * height) / 4;

y = *py++;
yy = y << 8;
u = *pu - 128;
ug = 88 * u;
ub = 454 * u;
v = *pv - 128;
vg = 183 * v;
vr = 359 * v;

for (line = 0; line < height; line++) {
for (col = 0; col < width; col++) {
r = (yy + vr) >> 8;
g = (yy - ug - vg) >> 8;
b = (yy + ub ) >> 8;

if (r < 0) r = 0;
if (r > 255) r = 255;
if (g < 0) g = 0;
if (g > 255) g = 255;
if (b < 0) b = 0;
if (b > 255) b = 255;
*dst++ = (((unsigned short)r>>3)<<11) | (((unsigned short)g>>2)<<5) | (((unsigned short)b>>3)<<0);

y = *py++;
yy = y << 8;
if (col & 1) {
pu++;
pv++;

u = *pu - 128;
ug = 88 * u;
ub = 454 * u;
v = *pv - 128;
vg = 183 * v;
vr = 359 * v;
}
}
if ((line & 1) == 0) {
pu -= linewidth;
pv -= linewidth;
}
}
}

SetKMode(TRUE);

//memcpy(DDBdata,(void *)image.rgb_address,width*height*2);
//2010.09.29
memcpy(bufferYUV,(void *)YUVData.y_address,width*height);
// just use Y
memcpy((bufferYUV+width*height),(void *)YUVData.cb_address,width*height/4);
memcpy((bufferYUV+width*height+width*height/4),(void *)
YUVData.cr_address,width*height/4);

SetKMode(FALSE);

// void yuv420_to_rgb565(int width, int height, unsigned char *src, unsigned short *dst)
yuv420_to_rgb565(width,height,bufferYUV, DDBdata);

图像也变成如下了,只是比较暗淡!


看看各位有什么意见,help me ,对这个玩意不太懂。呵呵。
fengbingchun 2010-11-03
  • 打赏
  • 举报
回复
up.....
gooogleman 2010-11-03
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 kacassi 的回复:]
貌似应该是这样:
for(i=0;i<UV_Size;i++) {
RData[i]=YCbCrtoR(YData[i],CbData[i],CbData[i]);
GData[i]=YCbCrtoG(YData[i],CbData[i],CbData[i]);
BData[i]=YCbCrtoB(YData[i],CbData[i],CbData[i]);

RDat……
[/Quote]

不错,今天我也尝试了一下,我看看是否合适。呵呵,谢谢了。
kacassi 2010-11-03
  • 打赏
  • 举报
回复
貌似应该是这样:
for(i=0;i<UV_Size;i++) {
RData[i]=YCbCrtoR(YData[i],CbData[i],CbData[i]);
GData[i]=YCbCrtoG(YData[i],CbData[i],CbData[i]);
BData[i]=YCbCrtoB(YData[i],CbData[i],CbData[i]);

RData[i*4+1]=YCbCrtoR(YData[i*4+1],CbData[i],CbData[i]);
GData[i*4+1]=YCbCrtoG(YData[i*4+1],CbData[i],CbData[i]);
BData[i*4+1]=YCbCrtoB(YData[i*4+1],CbData[i],CbData[i]);


RData[i*4+2]=YCbCrtoR(YData[i*4+2],CbData[i],CbData[i]);
GData[i*4+2]=YCbCrtoG(YData[i*4+2],CbData[i],CbData[i]);
BData[i*4+2]=YCbCrtoB(YData[i*4+2],CbData[i],CbData[i]);


RData[i*4+3]=YCbCrtoR(YData[i*4+3],CbData[i],CbData[i]);
GData[i*4+3]=YCbCrtoG(YData[i*4+3],CbData[i],CbData[i]);
BData[i*4+3]=YCbCrtoB(YData[i*4+3],CbData[i],CbData[i]);

//--------------------2010.10.26-------------------

if (RData[i]>255) RData[i]=255; if (RData[i]<0) RData[i]=0;
if (GData[i]>255) GData[i]=255; if (GData[i]<0) GData[i]=0;
if (BData[i]>255) BData[i]=255; if (BData[i]<0) BData[i]=0;
//RGB565
//DDBdata[i]=(RData[i]<<11)+(GData[i]<<5)+(BData[i]); // wrong
TempDDBdata[i]=((RData[i])<<11)|((GData[i])<<5)|(BData[i]);
TempDDBdata[i*4+1]=((RData[i*4+1])<<11)|((GData[i*4+1])<<5)|(BData[i*4+1]);
TempDDBdata[i*4+2]=((RData[i*4+2])<<11)|((GData[i*4+2])<<5)|(BData[i*4+2]);
TempDDBdata[i*4+3]=((RData[i*4+3])<<11)|((GData[i*4+3])<<5)|(BData[i*4+3]);

//RETAILMSG(1,(_T("DDBdata[i] = 0x%x\r\n"), DDBdata[i]));
}
gooogleman 2010-11-02
  • 打赏
  • 举报
回复
人呢?god help me
gooogleman 2010-11-02
  • 打赏
  • 举报
回复
下面是我糟糕的图像
tufaqing 2010-11-02
  • 打赏
  • 举报
回复
先了解YUV420的结构,大小Y=4*U=4*V,以4(2*2)个像素点为单位,每个像素点各一个Y,它们共用一个U和一个V,
比如如下4*4图像(abef, edgh各为一块):
a b c d
e f g h
Ya = Y0, Ua = U0, Va = V0
Yb = Y1, Ub = U0, Vb = V0
Yc = Y2, Uc = U1, Vc = V1
Yd = Y3, Ud = U1, Vd = V1
Ye = Y4, Ue = U0, Ve = V0
Yf = Y5, Uf = U0, Vf = V0
Yg = Y6, Ug = U1, Vg = V1
Yh = Y7, Uh = U1, Vh = V1
然后转换成RGB,R,G,B范围是0~255,可以保存为24位位图。
现在要保存为RGB565位图,就需要对RGB888数据进行相应的转换,这时要了解RGB565和RGB888的对应关系,位图数值表示的意思。5,6,8这些都是一个精度表示,并不是颜色(不是数值)一个范围的表示。8表示数值大小范围是0~255,0表示最低,255表示最高,可以控制256个精度。而5表示数值大小范围是0~31,0表示最低,31表示最高,可以控制32个精度。对于8中的255和5中的31都是表示最高的颜色值,他们是等价的,表示同一种亮度,他们的精度比例差就是表示的位数差,可以用移位转换比较方便,比如:
RGB888中3颜色值为R,G,B,转换成RGB565中3颜色值是r,g,b,则:
r = R >> (8 - 5);
g = G >> (8 - 6);
b = B >> (8 - 5);
一个像素点的RGB565两个字节以WORD为单位:
WORD c = (r << 11) | (g << 5) | b;
注意字节序,是以litter endian存储方式的(现在机器short int都是以这种方式),对应WORD两个字节,高字节在后面,直接写WORD对应的数据内存2字节就行了。
两字节分开写就是:
第一字节:BYTE c0 = ((g & 0x07) << 5) | b;
第二字节:BYTE c1 = (r << 3) | (g >> 3);

4,512

社区成员

发帖
与我相关
我的任务
社区描述
图形图像/机器视觉
社区管理员
  • 机器视觉
  • 迪菲赫尔曼
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧