如何将 C# 中的图像数组转换为一维向量?
How to convert an array of images in C# to a one dimension vector?
我有一个包含 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
。我想现在很清楚,如何实现这一点?
为什么不是这样的:
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
}
首先,我不确定你说的“矢量”是什么意思。您可以谈论 C# 的 Vector<T>
(documentation here),或者您可以谈论一维数组中的向量。如果是后者,C# array
就可以解决问题,我的大部分回答仍然有用。
我假设您想要 Vector<T>
,因为它更难选择并且对并行化很有用,您可能会在神经网络训练中利用它。
要将所有像素放入 Vector<T>
,您的第一直觉可能是使用 Vector<System.Drawing.Color>
。这是一种非常合理的方法,但它行不通,因为 Vector<T>
仅适用于 C# 的内置数字(byte、int、float 等)。所以我们必须想出一个解决方法。
值得庆幸的是,颜色只有 4 个我们关心的分量,每个分量都可以表示为一个字节:alpha、红色、蓝色和绿色。这意味着我们可以将 Color 的信息存储在任何 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
}
我有一个包含 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
。我想现在很清楚,如何实现这一点?
为什么不是这样的:
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
}
首先,我不确定你说的“矢量”是什么意思。您可以谈论 C# 的 Vector<T>
(documentation here),或者您可以谈论一维数组中的向量。如果是后者,C# array
就可以解决问题,我的大部分回答仍然有用。
我假设您想要 Vector<T>
,因为它更难选择并且对并行化很有用,您可能会在神经网络训练中利用它。
要将所有像素放入 Vector<T>
,您的第一直觉可能是使用 Vector<System.Drawing.Color>
。这是一种非常合理的方法,但它行不通,因为 Vector<T>
仅适用于 C# 的内置数字(byte、int、float 等)。所以我们必须想出一个解决方法。
值得庆幸的是,颜色只有 4 个我们关心的分量,每个分量都可以表示为一个字节:alpha、红色、蓝色和绿色。这意味着我们可以将 Color 的信息存储在任何 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
}