【问题标题】:RGB to Ycbcr conversionRGB 到 Ycbcr 的转换
【发布时间】:2013-07-11 23:58:19
【问题描述】:

我正在做图像处理,我有一个包含图像 rgb 值的 3D 数组,我正在尝试将这些值转换为 ycbcr(我制作了 rgb 数组的副本并将其命名为 ycbcr,并且

public static void rgb2ycbcr(System.Drawing.Bitmap bmp, ref byte[, ,] arrayrgb, ref byte[, ,] arrayycbcr)
    {

        byte Y;
        byte Cb;
        byte Cr;

        for (int i = 1; i < (bmp.Height + 1); i++)   //don't worry about bmp.height/width+2 its for my project
        {
            for (int j = 1; j < (bmp.Width + 1); j++)
            {
                byte R = arrayrgb[i, j, 0];
                byte G = arrayrgb[i, j, 1];
                byte B = arrayrgb[i, j, 2];

                Y = (byte)((0.257 * R) + (0.504 * G) + (0.098 * B) + 16);
                Cb = (byte)(-(0.148 * R) - (0.291 * G) + (0.439 * B) + 128);
                Cr = (byte)((0.439 * R) - (0.368 * G) - (0.071 * B) + 128);

                arrayycbcr[i, j, 0] = Y;
                arrayycbcr[i, j, 1] = Cb;
                arrayycbcr[i, j, 2] = Cr;

            }
        }

    }

问题是我得到的 ycbcr 值与使用 rgb2ycbcr 时在 matlab 中得到的值不同,我的代码中是否缺少某些内容?

【问题讨论】:

  • "得到的 ycbcr 值与我在 matlab 中得到的值不同" 举个例子怎么样?
  • 试过在命令窗口输入edit rgb2ycbcr 看看Matlab 的实现是做什么的?
  • 是的,一个带有 1x1 图像(x3 通道)的示例可以提供不同的结果。
  • 您可能永远不会像在 Matlab 中那样获得准确的值,因为您使用的是浮点计算。如果值非常接近,那没关系。

标签: c# matlab image-processing rgb


【解决方案1】:

更快、更准确的代码。 输出0到255之间的值(JPG公式)

            width = bmp.Width;
            height = bmp.Height;
            yData = new byte[width, height];                     //luma
            bData = new byte[width, height];                     //Cb
            rData = new byte[width, height];                     //Cr

            unsafe
            {
                BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, bmp.PixelFormat);
                int heightInPixels = bitmapData.Height;
                int widthInBytes = width * 3;
                byte* ptrFirstPixel = (byte*)bitmapData.Scan0;

                //Convert to YCbCr
                for (int y = 0; y < heightInPixels; y++)
                {
                    byte* currentLine = ptrFirstPixel + (y * bitmapData.Stride);
                    for (int x = 0; x < width; x++)
                    {
                        int xPor3 = x * 3;
                        float blue = currentLine[xPor3++];
                        float green = currentLine[xPor3++];
                        float red = currentLine[xPor3];

                        yData[x, y] = (byte)((0.299 * red) + (0.587 * green) + (0.114 * blue));
                        bData[x, y] = (byte)(128 - (0.168736 * red) + (0.331264 * green) + (0.5 * blue));
                        rData[x, y] = (byte)(128 + (0.5 * red) + (0.418688 * green) + (0.081312 * blue));
                    }
                }
                bmp.UnlockBits(bitmapData);
            }

【讨论】:

    【解决方案2】:

    在赋值之前将 R/G/B 转换为 uint。

    uint R =ConvertToUint(arrayrgb[i, j, 0]);

    uint G =ConvertToUint(arrayrgb[i, j, 1]);

    uint B =ConvertToUint(arrayrgb[i, j, 2]);

    【讨论】:

    • 可能还需要一些饱和逻辑。