C语言 从V4L2 API转换YUY2到RGB24



我试图使用V4L2 API来捕获图像并将图像放入opencv Mat中。问题是我的网络摄像头只在YUYV (YUY2)中捕获,所以我需要首先转换为RGB24。这里是完整的V4L2代码,我正在使用。

我能够让图片中的物体被识别出来,但它都是粉红色和绿色的,并且它是水平拉伸和扭曲的。我已经尝试了许多不同的转换公式,我有相同的基本粉红色/绿色失真图像。这张图的公式来自http://paulbourke.net/dataformats/yuv/。我正在使用linux上的shotwell照片查看器来查看.raw图像。我没法让瘸子打开。我不太了解如何保存图像格式,但我假设必须有某种标题,但shotwell照片查看器似乎工作。这可能是不正确的图像的原因吗?

我不确定V4l2是否返回由p指向的有符号或无符号字节图像。但如果这是问题,我的图像不会只是色差吗?但看起来几何形状也扭曲了。我相信我正确地处理了转换为浮点数和从浮点数转换的问题。

有人能帮我理解一下吗

  1. 如何找出包含在*void p变量
  2. 中的底层类型
  3. 从YUYV转换为RGB24的正确公式,包括使用哪种类型的解释
  4. 可以保存图像没有格式(头)和观看与Shotwell是问题吗?
  5. 是否有一种简单的方法来正确保存RGB24图像。
  6. 通用调试提示

感谢
static unsigned char   *bgr_image;
static void process_image(void *p, int size)
{
    frame_number++;
    char filename[15];
    sprintf(filename, "frame-%d.raw", frame_number);
    FILE *fp=fopen(filename,"wb");
    int i;
    float y1, y2, u, v;
    char * bgr_p = bgr_image;
    unsigned char * p_tmp = (unsigned char *) p;
    for (i=0; i < size; i+=4) {
      y1 = p_tmp[i];
      u = p_tmp[i+1];
      y2 = p_tmp[i+2];
      v = p_tmp[i+3];
      bgr_p[0] = (y1 + 1.371*(u - 128.0));
      bgr_p[1] = (y1 - 0.698*(u - 128.0) - 0.336*(v - 128.0));
      bgr_p[2] = (y1 + 1.732*(v - 128.0));
      bgr_p[3] = (y2 + 1.371*(v - 128.0));
      bgr_p[4] = (y2 - 0.698*(v - 128.0) - 0.336*(u - 128.0));
      bgr_p[5] = (y2 + 1.732*(u - 128.0));
      bgr_p+=6;
    }
    fwrite(bgr_image, size, 1, fp);                                       
    fflush(fp);
    fclose(fp);
}

首先,您必须了解使用什么类型的YUV422。

PIX_FMT_YUYV422,   ///< packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
PIX_FMT_UYVY422,   ///< packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1

尝试相应地替换y1, u, y2和v,但您可能根本没有处理YUV422,图片可能是平面的,而不是您期望的打包格式?

我认为你最好下载IrfanViewer,它有一个原始的yuv文件打开功能,并尝试选择正确的值有一个正确解码的图像,以找到你正在使用的数据类型。

不要尝试重新发明轮子。很多人都写过色彩空间转换器,而且很有可能你的实现(即使它有效)不是"最佳"的(例如比必要的慢)。

处理任何颜色空间的V4L2设备的规范方法是使用libv4l库,它将透明地将相机的本机颜色空间转换为BGR24, RGB24YUV420中的一次(如果你想要,我认为这是真的)。

至于保存图像,仍然使用已经存在的内容。就我个人而言,我会使用imagemagick将帧保存为任何imageviewer都可以读取的"适当"格式(png或tiff,如果质量重要)

最新更新