如何从 OpenCV 图像中获取 BITMAPINFOHEADER?

How to get BITMAPINFOHEADER from OpenCV image?

我必须使用第 3 方本机 API,它将指向 BITMAPINFOHEADER 结构的指针和指向位图数据的指针作为参数。

static Image load ( IntPtr bi, IntPtr img, string name )

constructs a image representation from the specified bitmap image in memory. The bi pointer points to a BITMAPINFOHEARER followed by an optional color table. The existence of a colortable depends on the image type. The Byte pointer has to point to bitmap data as described by the bitmap information.

如何在 C# 中获取指向表示具有指定大小的未压缩 24 位 RGB 位图的结构的指针?

我已经从这里下载了 BITMAPINFOHEADER 结构 C# 声明:http://www.pinvoke.net/default.aspx/Structures/BITMAPINFOHEADER.html

我实际上正在使用 EmguCV 图像 class,我试图从 Image<Rgb, byte>.

中获取描述图像的 BITMAPINFOHEARER
var image = new Image<Rgb, byte>(@"myImage.bmp");

//1. create BITMAPINFOHEADER instance
var bitmapInfoHeader = new BITMAPINFOHEADER
{
    biSize = (uint)Marshal.SizeOf(typeof(BITMAPINFOHEADER)), //40
    biWidth = image.Width, //4096
    biHeight = image.Height, //4096
    biPlanes = 1,
    biBitCount =24,
    biCompression = BitmapCompressionMode.BI_RGB,
    biSizeImage = (uint)image.Bytes.Length,
};

//2. get pointer to the data
IntPtr ptrData;
fixed (byte* pData = image.Data)
    ptrData = (IntPtr)pData;

//3. get pointer to the BitmapInfoHeader:
int iSizeOfBih = Marshal.SizeOf(typeof(BITMAPINFOHEADER));
IntPtr ptrBih = Marshal.AllocHGlobal(iSizeOfBih);
Marshal.StructureToPtr(bih, ptrBih, false);

fixed (byte* pData = image.Bytes)
{
   var frImage = Bmp.load(pBitmapInfoHeader, (IntPtr)pData, "Frame");
   var faces = faceTracker.processFrame(frImage);
}

虽然编译和运行没有异常,但它没有正确加载图像(我无法处理稍后使用 facetracker.When 我使用另一种方法从 facetracker 工作的文件加载图像)

我做错了什么?

评论回顾

关于如何填写 BITMAPINFOHEADER 的大部分信息都可以在 msdn documentation 上找到。

需要更正的几点:
biSize 应该填写 BITMAPINFOHEADER 的大小。这个字段在这里是因为结构可以是更完整的版本,如BITMAPV5HEADER,所以如果设置不正确,它可能会起作用,但显然不推荐。
biCompression 应设置为 BI_RGBBI_BITFIELDS 未记录为对 24 位模式有效。
biHeight 如果图像是自上而下的,则应设置为负数,这很可能是内存表示的情况,就像您的情况一样。否则,图片可能会上下颠倒加载。
biSizeImage貌似设置正确,但由于在BI_RGB模式下是允许填0的,这样可以防止出错。
此外,固定指针(使用 fixed)的所有使用都应在 fixed 范围内完成。如果在外面使用,不能保证数组不会被移动到别处。

关于尺寸,Image class 似乎使用了行填充,即,如果行的宽度不是 4 字节的倍数,则用额外的字节填充行。 BITMAPINFOHEADER 描述的位图也应该有这个 属性,所以 load 可能适用于所有维度,但如果 load 实际上不支持行填充,它可能需要将图像复制到具有精确尺寸的数组。另一种解决方案是在任何地方都使用 32 位模式(并且它也可能会提高性能)。