在本例中,Shape_Predictor 的二维灰度数组。
这是我正在尝试的方法,但没有取得太大成功。
using DlibDotNet;
using Rectangle = System.Drawing.Rectangle;
using System.Runtime.InteropServices;
public static class Extension
{
public static Array2D<byte> ToArray2D(this Bitmap bitmap)
{
var bits = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
var length = bits.Stride * bits.Height;
var data = new byte[length];
Marshal.Copy(bits.Scan0, data, 0, length);
bitmap.UnlockBits(bits);
var array = new Array2D<byte>(bitmap.Width, bitmap.Height);
for (var x = 0; x < bitmap.Width; x++)
for (var y = 0; y < bitmap.Height; y++)
{
var offset = x * 4 + y * bitmap.Width * 4;
array[x][y] = data[offset];
}
return array;
}
我已经搜索过,但还没有找到明确的答案。
最佳答案
如前所述,您首先需要将图像转换为灰度图像。 StackOverflow 上有很多答案可以帮助您解决这个问题。我建议在这个答案中使用 ColorMatrix
方法:
A: Convert an image to grayscale
我将在下面的代码中使用该答案中显示的 MakeGrayscale3(Bitmap original)
方法。
通常,图像是逐行循环处理的,因此为了清楚起见,您应该将 Y 循环作为外循环。它还使数据偏移量的计算更加高效。
对于实际数据,如果图像是灰度图,R、G、B字节应该都是一样的。 32 位像素数据中的顺序“ARGB”指的是一个 UInt32
值,但它们是小端字节序的,这意味着字节的实际顺序是 [B, G, R, A]。这意味着在每次循环迭代中,我们可以只取四个字节中的第一个,它将成为蓝色分量。
public static Array2D<Byte> ToArray2D(this Bitmap bitmap)
{
Int32 stride;
Byte[] data;
// Removes unnecessary getter calls.
Int32 width = bitmap.Width;
Int32 height = bitmap.Height;
// 'using' block to properly dispose temp image.
using (Bitmap grayImage = MakeGrayscale(bitmap))
{
BitmapData bits = grayImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppPArgb);
stride = bits.Stride;
Int32 length = stride*height;
data = new Byte[length];
Marshal.Copy(bits.Scan0, data, 0, length);
grayImage.UnlockBits(bits);
}
// Constructor is (rows, columns), so (height, width)
Array2D<Byte> array = new Array2D<Byte>(height, width);
Int32 offset = 0;
for (Int32 y = 0; y < height; y++)
{
// Offset variable for processing one line
Int32 curOffset = offset;
// Get row in advance
Array2D<Byte>.Row<Byte> curRow = array[y];
for (Int32 x = 0; x < width; x++)
{
curRow[x] = data[curOffset]; // Should be the Blue component.
curOffset += 4;
}
// Stride is the actual data length of one line. No need to calculate that;
// not only is it already given by the BitmapData object, but in some situations
// it may differ from the actual data length. This also saves processing time
// by avoiding multiplications inside each loop.
offset += stride;
}
return array;
}
关于c# - 将 System.Drawing 位图转换为 Dlib Array2D,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49910060/