c# - 将 System.Drawing 位图转换为 Dlib Array2D

标签 c# .net dlib

在本例中,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/

相关文章:

python - Python 的面部和头发检测

opencv - 使用 DLIB 进行面部对齐检查

c++ - 如何在 C++ 中找到两个 vector 之间的最小(优化)距离

c# - 查找单个类的所有依赖项

c# - GitHub 提交错误 : Permission denied fatal: Unable to process path ~/App_Data/aspnet-MyProject. mdf

c# - 使用 C# 创建位图字体

c# - 已经有一个打开的 DataReader ...即使它不是

.net - 在 Mono 和 Visual Studio 之间共享源代码

c# - 如何在客户端拦截器方法AsyncUnaryCall中进行异步调用

c# - 自定义控件上的单击事件未触发(从包含表单分配的事件)