图像数据处理库:从图像到数组的高效转换

图像处理领域,图像数据和算法之间存在着一道鸿沟。实验室中的数学家和算法工程师通常擅长矩阵处理。对于他们来说,图像不过是矩阵的一种形式。因此,他们不需要理解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); // ...对矩阵进行一些操作

方法细节

有三个方法:

  1. 从文件加载图像矩阵
    • C# T[][][] LoadFromFile(string fileName)
    • C# T[][,] LoadFromFile2DArray(string fileName)
    定义了PixelFormat.Format24bppRgb,所以总是得到图像的RGB波段,即使图像文件是8位灰度图像。如果加载单色图像文件,三个波段的值是相同的。
  2. 将T[][] /T[,]/ T[][,] /T[][][]数据保存到图像文件
    • C# void SaveToBmpLinear(T[][,] image, string fileName)
    • C# void SaveToBmpLinear(T[][][] image, string fileName)
    • C# void SaveToBmpLinear(T[,] image, string fileName)
    • C# void SaveToBmpLinear(T[][] image, string fileName)
    • C# SaveToBmpNoLinear(T[,] image, string fileName)
    • C# SaveToBmpNoLinear(T[][] image, string fileName)
    • C# SaveToBmpNoLinear(T[][,] image, string fileName)
    • C# SaveToBmpNoLinear(T[][][] image, string fileName)
    将T[][,]/T[][][]图像保存为RGB彩色24位bmp类型图像文件。在保存之前,它将数据拉伸到0-255。它可以提高图像的对比度。
  3. 将图像转换为T[][,]/T[][]
    • T[][][] LoadFromImage(Image img)
    • T[][,] LoadFromFile2DArray(Image img)
    将图像数据加载到T[R/G/B][Width][Height]。

关键方法

发现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]; } } });
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485