0
我試圖寫一個YUV422到RGB24轉換器,但轉換後的數據的結果似乎很奇怪。 結果是一個紫色觸摸灰度圖片與一些淺綠色的點... 有沒有人有想法?轉換YUV422到RGB24
inline void convert_yuv442_2_rgb24(const unsigned char* source, unsigned char* destination, unsigned long width, unsigned long height)
{
unsigned char data[3];
for(unsigned long i = 0, c = 0; i < width * height * 2; i += 2, c += 3)
{
// 16Bit YUV422 -> 24Bit YUV
data[0] = source[i+0];
data[1] = (source[i+1] & 0xF0) >> 4;
data[2] = (source[i+1] & 0X0F);
// YUV-> RGB24
//destination[c + 0] = (float) (1.164f*(data[0] - 16) + 1.596f*(data[2] - 128));
//destination[c + 1] = (float) (1.164f*(data[0] - 16) - 0.813f*(data[2] - 128) - 0.391f*(data[1] - 128));
//destination[c + 2] = (float) (1.164f*(data[0] - 16) + 2.018f*(data[1] - 128));
destination[c + 0] = (float) data[0] + (float) data[2]/0.877F;
destination[c + 2] = (float) data[0] + (float) data[1]/0.493f;
destination[c + 1] = (float) 1.7f * (float) data[0] - 0.509f * destination[c + 0] - 0.194f*(float)destination[c + 2];
}
}
我試着用給定的提示成功oneone。 轉換器代碼來自這裏:http://paulbourke.net/dataformats/yuv/
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <libv4l1.h>
#include <libv4l2.h>
#include <linux/videodev.h>
int init_webcam(int *fd, struct video_window *web_win, long *length);
struct RGB
{
unsigned char r, g, b;
};
RGB convert(int y, int u, int v)
{
RGB rgb;
u -= 128;
v -= 128;
rgb.r = y + 1.370705 * v;
rgb.g = y - 0.698001 * v - 0.337633 * u;
rgb.b = y + 1.732446 * u;
if (rgb.r < 0) rgb.r = 0;
if (rgb.g < 0) rgb.g = 0;
if (rgb.b < 0) rgb.b = 0;
if (rgb.r > 255) rgb.r = 255;
if (rgb.g > 255) rgb.g = 255;
if (rgb.b > 255) rgb.b = 255;
return rgb;
}
void YUV422_2_RGB24(unsigned char* yuv, RGB* p1, RGB* p2)
{
// int u = yuv[0];
// int y1 = yuv[1];
// int v = yuv[2];
// int y2 = yuv[3];
int y1 = yuv[0];
int u = yuv[1];
int y2 = yuv[2];
int v = yuv[3];
*p1 = convert(y1, u, v);
*p2 = convert(y2, u, v);
}
int main()
{
struct video_window web_win;
int fd;
long length;
if(!init_webcam(&fd, &web_win, &length))
return 1;
// Bild aufnehmen
unsigned char* picture = new unsigned char[web_win.width * web_win.height * 2];
unsigned char* image = new unsigned char[web_win.width * web_win.height * 3];
if(v4l1_read(fd, picture, web_win.width * web_win.height * 2) == -1)
{
printf("Error while reading webcam\n");
return 0;
}
// Bild speichern
FILE *imagefile;
if((imagefile = fopen("bild.ppm", "w+b")) == NULL)
{
printf("Couldn't open file for writing\n");
return 0;
}
RGB p1, p2;
for(unsigned long i = 0, c = 0; i < web_win.width * web_win.height * 2; i += 4, c += 6)
{
YUV422_2_RGB24(&picture[i], &p1, &p2);
image[c + 0] = p1.r;
image[c + 1] = p1.g;
image[c + 2] = p1.b;
image[c + 3] = p2.r;
image[c + 4] = p2.g;
image[c + 5] = p2.b;
}
fprintf(imagefile, "P6\n%d %d\n255\n", web_win.width, web_win.height);
for(unsigned long i = 0; i < web_win.width * web_win.height; ++ i)
{
fwrite((unsigned char*) &image[i * 3], 1, 3, imagefile);
}
fclose(imagefile);
delete[] picture;
delete[] image;
v4l1_close(fd);
return 0;
}
int init_webcam(int *fd, struct video_window *web_win, long *length)
{
struct video_capability web_cap;
struct video_picture web_pict;
if((*fd = v4l1_open("/dev/video0", O_RDONLY)) == -1)/*Open webcam device*/
{
printf("Unable to open webcam devide\n");
return 0;
}
if(v4l1_ioctl(*fd, VIDIOCGPICT, &web_pict) == -1)/*This function call isn't necessary but otherwise you won't get a proper picture*/
{
printf("Unable to get picture information\n");
return 0;
}
if (ioctl (*fd, VIDIOCGPICT, &web_pict) != -1)
{ // successfully retrieved the default image properties
// the following values are for requesting 8bit grayscale
//web_pict.depth = 16;
web_pict.palette = VIDEO_PALETTE_YUV422;
if (ioctl (*fd, VIDIOCSPICT, &web_pict) == -1)
{
printf("failed to set the image properties\n");
//return 0;
}
}
if(ioctl(*fd, VIDIOCGCAP, &web_cap) == -1)/*Get video capabilities*/
{
printf("Unable to get capabilities\n");
return 0;
}
if(v4l1_ioctl(*fd, VIDIOCGWIN, web_win) == -1)/*Get video information*/
{
printf("Unable to get video information\n");
return 0;
}
web_win->width = web_cap.maxwidth;/*Try to write max solution*/
web_win->height = web_cap.maxheight;
if(v4l1_ioctl(*fd, VIDIOCSWIN, web_win) == -1)/*Write new(?!) video information*/
{
printf("Unable to write video information\n");
return -1;
}
if(v4l1_ioctl(*fd, VIDIOCGWIN, web_win) == -1)/*Read new(?!) video information*/
{
printf("Unable to get video information\n");
return 0;
}
*length = web_win->width * web_win->height * (web_pict.depth/8);
printf("bits per pixel: %d\n", web_pict.depth);
printf("palette: %d\n", web_pict.palette);
return 1;
}
422意味着8位正確嗎?你的代碼看起來像是試圖處理844個數據。此外,Y通道通常是有偏見的。你看過[維基百科](http://en.wikipedia.org/wiki/YUV#Y.27UV422)條目嗎? – user786653
Y422使用宏像素來壓縮U和V,看起來並不像你正在處理的那樣。 –