代码之家  ›  专栏  ›  技术社区  ›  user366312

如何将位图RGB颜色正确转换为二维双数组?

  •  0
  • user366312  · 技术社区  · 6 年前

    我需要转换一个 Bitmap 图像到二维 double 数组。
    我希望每个像素都有一个任意的数字,表示在0-1之间缩放的rbg颜色。 我想将位图图像转换为二维双数组,以便对该位图图像应用卷积操作。 所以,我写了以下代码:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
    
            Bitmap image = (Bitmap)Bitmap.FromFile("lena.jpg");
    
            pictureBox1.Image = image;
            dataGridView1.DataSource = ToDataTable(ToDouble2d(image));
        }        
    
        public static double[,] ToDouble2d(Bitmap input)
        {
            int width = input.Width;
            int height = input.Height;
    
            double[,] array2d = new double[width, height];
    
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Color clr = input.GetPixel(x, y);
    
                    double iClr = (double)clr.ToArgb();
    
                    array2d[x, y] = iClr / 255.0;
                }
            }
    
            return array2d;
        }
    
        public static DataTable ToDataTable(double[,] numbers)
        {
            DataTable dt = new DataTable();
            for (int i = 0; i < numbers.GetLength(1); i++)
            {
                dt.Columns.Add("Column" + (i + 1));
            }
    
            for (var i = 0; i < numbers.GetLength(0); ++i)
            {
                DataRow row = dt.NewRow();
                for (var j = 0; j < numbers.GetLength(1); ++j)
                {
                    row[j] = numbers[i, j];
                }
                dt.Rows.Add(row);
            }
            return dt;
        }
    }
    

    enter image description here

    我注意到的第一个问题是:所有的值都是负的。
    所以,我试着在 0 1 是的。

    private static void Rescale(double[,] convolve)
    {
        int imageWidth = convolve.GetLength(0);
        int imageHeight = convolve.GetLength(1);
    
        double maxAmp = 0.0;
    
        for (int j = 0; j < imageHeight; j++)
        {
            for (int i = 0; i < imageWidth; i++)
            {
                maxAmp = Math.Max(maxAmp, convolve[i, j]);
            }
        }
    
        double scale = 1 / maxAmp;
    
        for (int j = 0; j < imageHeight; j++)
        {
            for (int i = 0; i < imageWidth; i++)
            {
                double d = convolve[i, j] * scale;
                convolve[i, j] = d;
            }
        }
    }  
    

    现在,所有的强度 -Infinity 是的。

    enter image description here

    那么,处理这种情况的正确方法是什么?

    注意。 此时性能不是问题(例如位图锁定等)。我只想知道为什么我的代码不工作,以及如何正确地做到这一点。

    2 回复  |  直到 6 年前
        1
  •  0
  •   TheGeneral    6 年前

    我不知道你想做什么,也不知道为什么。但是,如果您只需要一个表示从0到1的RBG值的任意数字你也许能做这样的事

    public static Uint RGBtoUInt(int r, int g, int b)
    {
        return (uint)(( r << 0 ) | ( g << 8 ) | ( b << 16 ));
    }
    
    ...
    
    var myArbitaryValue = RGBtoInt(r,g,b) / (double)16581375; // maximum 24bit color value 
    

    注意 :完全未经测试

        2
  •  0
  •   user366312    6 年前

    好的,我已经解决了这个问题 this link .

        public static double[,] ToDouble2d(Bitmap input)
        {
            int width = input.Width;
            int height = input.Height;
    
            double[,] array2d = new double[width, height];
    
            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    Color cl = input.GetPixel(x, y);
    
                    // A 2d double data is always Grayscale.
                    // So, three elements are averaged.
                    double gray = ((cl.R * 0.3) + (cl.G * 0.59) + (cl.B * 0.11));
    
                    array2d[x, y] = gray/255.0;
                }
            }
    
            return array2d;
        }