【问题标题】:How to convert an array of images in C# to a one dimension vector?如何将 C# 中的图像数组转换为一维向量?
【发布时间】:2021-12-22 22:11:19
【问题描述】:

我有一个包含 200 张图片的文件夹。我将所有这些图像加载到名为training 的图像类型数组列表中。我在将其转换为一维向量时遇到问题。我需要帮助,正在编写基于 PCA 的人脸识别解决方案,谢谢。

 List<Image> training = new List<Image>();
        //the path to the images
        static string path = "C:/Users/User/Documents/visual studio 2015/Projects/PCA/PCA/training";
        public Form1()
        {
            InitializeComponent();
        }
        //the method below starts the training process
        private void button1_Click(object sender, EventArgs e)
        {
            /*read all the images in the training folder into an array
            in this case the images are already in gray scale so we do not need to convert
            */
            var files = Directory.GetFiles(path);
            foreach(string r in files)
            {
                if(Regex.IsMatch(r, @"\.jpg$|\.png$|\.gif$"))
                {
                    training.Add(Image.FromFile(r));
                }
            }
            //convert the list of images to a one dimension vector
           
           
        }

更新

我有一个名为matrix data 的变量,它已初始化为大小[200,92*112],然后我进行了此列表训练,我需要遍历列表中的所有图像并访问pixel 并将其分配给matrix_data。我想现在很清楚,如何实现这一目标?

【问题讨论】:

  • 您可以查看这个答案,该答案显示了访问单个图像像素的方法stackoverflow.com/a/190395/234087
  • @Fede,谢谢,我当然需要一个数据类型变量来加载像素,因为我正在循环遍历每个图像,我需要一些帮助
  • 图像通常作为带有一些元数据的字节数组进行管理,例如 with/height/stride/pixelformat。或者作为 16 位灰度数据的 ushort 数组。
  • 这能回答你的问题吗? stackoverflow.com/questions/3801275/…
  • @JonasH,我很难做到这一点,因为期望一维数组需要单列和多行,而图像有 width 列和 height

标签: c# arraylist vector


【解决方案1】:

首先,我不确定您所说的“矢量”是什么意思。您可能正在谈论 C# 的 Vector&lt;T&gt; (documentation here),或者您可能正在谈论一维数组中的向量。如果是后者,那么 C# array 就可以了,我的大部分回答仍然会有所帮助。

我假设你想要一个Vector&lt;T&gt;,因为它是一个更难的选择并且对并行化很有用,你可能会在神经网络训练中利用它。

要将所有像素放入Vector&lt;T&gt;,您的第一反应可能是使用Vector&lt;System.Drawing.Color&gt;。这是一个完全合理的方法,但它不起作用,因为Vector&lt;T&gt; 仅适用于 C# 的内置数字(字节、整数、浮点数等)。所以我们必须想出一个解决方法。

幸运的是,颜色只有 4 个我们关心的分量,每个分量都可以表示为一个字节:alpha、red、blue 和 green。这意味着我们可以将颜色的信息存储在任何 4 字节数字中。我选择使用uint

private static uint ToUint(Color color)
{
    var bytes = new[] { color.A,color.R,color.G,color.B};
    return BitConverter.ToUInt32(bytes);
}

转换回颜色同样简单:

private static Color ToColor(uint integer)
{
    var bytes = BitConverter.GetBytes(integer);
    return Color.FromArgb(bytes[0], bytes[1], bytes[2], bytes[3]);
}

现在我们要做的就是遍历像素,将它们转换为uints,将它们存储在一个数组中,然后从数组中创建一个向量:

private static Vector<uint> ConvertImagesToColorVector(IEnumerable<Bitmap> images)
{
    var pixelCount = images.Sum(image => image.Width * image.Height);
    var pixels = new uint[pixelCount];
    var index = 0;
    foreach (var image in images)
    {
        foreach (var pixel in GetPixels(image))
        {
            pixels[index++] = ToUint(pixel);
        }
    }
    return new Vector<uint>(pixels);
}

private static IEnumerable<Color> GetPixels(Bitmap bitmap)
{
    for (var row = 0; row < bitmap.Height; row++)
    {
        for (var column = 0; column < bitmap.Width; column++)
        {
            yield return bitmap.GetPixel(column, row);
        }
    }
}

您的代码如下所示:

private void button1_Click(object sender, EventArgs e)
{
    /*read all the images in the training folder into an array
    in this case the images are already in gray scale so we do not need to convert
    */
    var files = Directory.GetFiles(path);
    var imageFiles = new List<string>();
    foreach (string r in files)
    {
        if (Regex.IsMatch(r, @"\.jpg$|\.png$|\.gif$"))
        {
            training.Add(Image.FromFile(r));
        }
    }

    var vector = ConvertImagesToColorVector(training.Select(i=>new Bitmap(i)));

    //do whatever you want with the vector here. If you need to convert back to a color use ToColor
}

【讨论】:

  • 好的,感谢您的帮助。我可以从我们上面计算的那个向量中得到平均向量,然后从数组中的每个图像中减去平均值吗?
  • 我不确定你的意思。也许打开一个新问题?另外,如果您认为我的回答满足您的问题,请将其标记为正确答案
  • 尚未在visual studio中实现,建议耐心等待
  • 赏金将在 15 小时后到期
【解决方案2】:

为什么不这样:

public static IEnumerable<System.Drawing.Color> ColorEnumerable(System.Drawing.Image picture)
{
    System.Drawing.Bitmap btmp = new Bitmap(picture);
    //TODO maybe LockBits first
    for(int i = 0; i < btmp.Height; i++) 
    {
        for(int j = 0; j < btmp.Width; j++)
        {
            yield return btmp.GetPixel(i,j);            
        }
    }
}

您可以根据需要在代码中分配给矩阵:

foreach(Image image in training)
{
    if(Regex.IsMatch(r, @"\.jpg$|\.png$|\.gif$"))
    {
        training.Add(Image.FromFile(r));
        // you could even populate your matrix here
    }
}
//convert the list of images to a one dimension vector
System.Numeric.Vector<Color> colorVector;
for(int i = 0; i < training.Count(); i++)
{
    colorVector = new Vector(ColorEnumerable(training[i]).ToArray());
    // TODO add colorVector to your matrix or whatever
}

【讨论】:

  • 尚未实施
  • 我能用这个矩阵计算平均向量吗?
  • 我不知道,你呢?我不知道公式,我只能帮你编程。也就是说,我想你已经知道你需要什么样的矩阵了。最坏的情况你需要编写自己的 calculateMeanVector(Matrix matrix) 方法。
  • stackoverflow.com/questions/32256998/… 这里他们在谈论一些数学库,也许你可以在那里得到一些想法
  • 我以为您想要为每张图片创建一个单独的矢量实例?取决于您打算使用向量的确切用途(也许它适用于某些内置矩阵?也许您甚至不需要向量,并且数组就足够了?也许只需将值直接添加到您的“矩阵”或其他什么?)我只是试图展示如何将位图转换为 1D - .toArray() 为您提供 1D 数组, Vector() 构造函数从该数组创建 Vector,请随意详细说明您的问题,我仍然需要猜测很多你真正想知道的是什么
猜你喜欢
  • 2021-05-11
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 2019-07-21
  • 1970-01-01
  • 1970-01-01
  • 2016-12-21
  • 1970-01-01
相关资源
最近更新 更多