YUYV转RGB-C-Cuda实现

介绍Cuda实现YUYV转RGB算法。

1.YUV介绍

  YUV是被欧洲电视系统所采用的一种颜色编码方法(属于PAL,Phase Alternation Line),是PAL和SECAM模拟彩色电视制式采用的颜色空间。其中的Y、U、V几个字母不是英文单词的组合词,Y代表亮度,其实Y就是图像的灰度值;UV代表色差,U和V是构成彩色的两个分量。

1.1 YUV转RGB公式

YUV到RGB的转换有如下公式:

1
2
3
R = 1.164*(Y-16) + 1.159*(V-128);
G = 1.164*(Y-16) - 0.380*(U-128)+ 0.813*(V-128);
B = 1.164*(Y-16) + 2.018*(U-128));

那么YUYV(Y0UY1V)的实现就是使用Y0UV转换出一个RGB像素,使用Y1UV转换出第二个像素,那么就实现了四个字节转换出6个字节(2个RGB像素)。

2.代码实现

C语言实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void CPU_YUYV2RGB(char* arrOut, char* arrIn)
{
unsigned char y0, y1, u, v;
int r, g, b;
int nIndex = 0;
for(nIndex = 0; nIndex < N/2; nIndex++)
{
y0 = *(arrIn + nIndex*4);
u = *(arrIn + nIndex*4 + 1);
y1 = *(arrIn + nIndex*4 + 2);
v = *(arrIn + nIndex*4 + 3);
r = 1.164*(y0-16) + 1.159*(v-128);
g = 1.164*(y0-16) - 0.380*(u-128) + 0.813*(v-128);
b = 1.164*(y0-16) + 2.018*(u-128);
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
*(arrOut + nIndex*6) = r;
*(arrOut + nIndex*6+1) = g;
*(arrOut + nIndex*6+2) = b;
r = 1.164*(y1-16) + 1.159*(v-128);
g = 1.164*(y1-16) - 0.380*(u-128) + 0.813*(v-128);
b = 1.164*(y1-16) + 2.018*(u-128);
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
*(arrOut + nIndex*6+3) = r;
*(arrOut + nIndex*6+4) = g;
*(arrOut + nIndex*6+5) = b;
}
}

Cuda代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
__global__ void YUYV2RGB(char *g_out, char *g_in, int N)
{
unsigned int i = 0, j = 0;
unsigned char y0, y1, u, v;
int r, g, b;
int nStart = blockIdx.x * 320 * 4 + threadIdx.x * 4 ;
int nOut = blockIdx.x * 320 * 6 + threadIdx.x * 6 ;
char *YUV = (char*)g_in + nStart;
char* RGB = (char*)g_out + nOut;
//for (i = 0, j = 0; i < (N << 1); i += 4, j += 6)
//{
y0 = (unsigned char)YUV[i + 0];
u = (unsigned char)YUV[i + 1];
y1 = (unsigned char)YUV[i + 2];
v = (unsigned char)YUV[i + 3];
r = 1.164*(y0-16) + 1.159*(v-128);
g = 1.164*(y0-16) - 0.380*(u-128) + 0.813*(v-128);
b = 1.164*(y0-16) + 2.018*(u-128);
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
//YUV2RGB(y0, u, v, &r, &g, &b);
RGB[j + 0] = r;
RGB[j + 1] = g;
RGB[j + 2] = b;
//YUV2RGB(y1, u, v, &r, &g, &b);
r = 1.164*(y1-16) + 1.159*(v-128);
g = 1.164*(y1-16) - 0.380*(u-128) + 0.813*(v-128);
b = 1.164*(y1-16) + 2.018*(u-128);
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
RGB[j + 3] = r;
RGB[j + 4] = g;
RGB[j + 5] = b;
//}
}
Dock wechat
欢迎您扫一扫上面的微信公众号,订阅我的公众号