在图像处理领域,图像数据和算法之间存在着一道鸿沟。实验室中的数学家和算法工程师通常擅长矩阵处理。对于他们来说,图像不过是矩阵的一种形式。因此,他们不需要理解Bitmap类的细节。此外,像MathNet.Numerics这样的数学工具,设计之初就是为了处理double[]或T[]这样的数据类型。例如,GDI+可以轻松地放大图像,但如果想使用一些高级的插值方法来计算插值像素值,GDI+就显得无能为力了。因此,支持这个库将Image转换为float[][][]/float[][,]/T[][][]/T[][,]类型。这样,算法工程师就可以专注于算法本身,而不需要关心“如何正确加载图像”。
同时,有时发现实验室中的代码效率不高,例如GetPixel()和SetPixel()。因此,认为需要提供一个解决方案来连接矩阵和图像。
这个类库做了两件事:1. 将图像转换为数组。2. 将数组转换为图像。通常,图像可以分为两种类型:a) 单色图像;b) 彩色图像。单色图像可以用2D矩阵定义:float[Width][Height]/float[Width,Height]或T[Width][Height]/T[Width,Height]。彩色图像可以用3D矩阵定义:float[R/G/B][Width][Height]/[R/G/B]float[Width,Height]或T[R/G/B][Width][Height]/T[R/G/B][Width,Height]。
这里支持这4种数据类型。
构建单个cs文件(DoubleToImageMethod.cs)后,将得到一个DLL文件。为这个DLL添加一个引用。
C# string fileName = "test.bmp";
float[][][] image;
// 这里得到了图像矩阵
image = DoubleToImageMethods.LoadFromFile(fileName);
// ...对矩阵进行一些操作,例如模式识别
// 现在有三个来自test.bmp的波段。
image[0]是红色波段,image[1]是绿色通道,image[2]是蓝色波段。也许可以用图像做一些事情。完成工作后,应该保存数据:
C#
// 然后将矩阵保存为Bmp图像文件
DoubleToImageMethods.SaveToBmpLinear(image, "test.bmp");
然后就得到了结果。
有时,需要其他数据类型,例如需要比float更精确的值,如double。可以使用这种方式加载图像:
C# string fileName = "test.bmp";
double[][][] image;
// 这里得到了图像矩阵,并且这里请求了double[][][]数据类型
image = DoubleToImageMethods.LoadFromFile(fileName);
// ...对矩阵进行一些操作
有三个方法:
发现Marshal.Copy()是一个解决这个问题的好类。当使用bmp或jpg文件加载或保存数据时,需要BitmapData,而Marshal.Copy()支持快速且安全地加载或保存数据。
C# Parallel.For(0, imgHeight, (int i) => {
for (int j = 0; j < imgExtentWidth; j += 3) {
if (j < imgWidth * 3) {
linlizeImg[i * imgExtentWidth + j] = arrayData[2][j / 3][i];
linlizeImg[i * imgExtentWidth + j + 1] = arrayData[1][j / 3][i];
linlizeImg[i * imgExtentWidth + j + 2] = arrayData[0][j / 3][i];
} else {
linlizeImg[i * imgExtentWidth + j] = linlizeImg[i * imgExtentWidth + j - 1];
}
}
});