gpt4 book ai didi

C++:灰度位图头和活绘+opencv图像处理

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:14:31 30 4
gpt4 key购买 nike

我正在尝试显示来自单色相机(Adimec N5A/CXP,符合 GenIcam 标准)的实时图像。

从供应商提供的示例(但在 RGB 24 中),我或多或少能够显示图像,但显色性非常奇怪(颜色和阴影而不是灰度)。我想我在位图 header 声明中做错了什么:

    bitmapInfo = (LPBITMAPINFO)malloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD));
bitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo->bmiHeader.biPlanes = 1;
bitmapInfo->bmiHeader.biBitCount = 8; // 24
bitmapInfo->bmiHeader.biCompression = BI_RGB;
bitmapInfo->bmiHeader.biSizeImage = 0;
bitmapInfo->bmiHeader.biXPelsPerMeter = 0;
bitmapInfo->bmiHeader.biYPelsPerMeter = 0;
bitmapInfo->bmiHeader.biClrUsed = 256;
bitmapInfo->bmiHeader.biClrImportant = 0;
bitmapInfo->bmiHeader.biWidth = (LONG)width;
bitmapInfo->bmiHeader.biHeight = -(LONG)height;
/*
RGBQUAD* bmiColors = (RGBQUAD*)(bitmapInfo->bmiColors);
for (size_t index = 0; index < 256; ++index)
{
bmiColors[index].rgbBlue = (BYTE)index;
bmiColors[index].rgbGreen = (BYTE)index;
bmiColors[index].rgbRed = (BYTE)index;
bmiColors[index].rgbReserved = 0;
}
*/

我在 bmiColors field of BITMAPINFO structure 中找到'biClrUsed' 应该设置为 256。然后我不知道是否需要编写一个 block 来描述 'bmiColors'。我想每个像素只使用一个字节而不是 r、g 和 b 组件。

然后在程序中(在函数“OnPaint”中),它使用函数“SetDIBitsToDevice”在先前创建的窗口中显示。首先检索图像指针:

unsigned char *imagePtr = liveState.currentBuffer->getInfo<unsigned char *>(liveState.grabber, gc::BUFFER_INFO_BASE);

然后显示图像:

::SetDIBitsToDevice(dc, 0, 0, (DWORD)liveState.width, (DWORD)liveState.height, 0, 0, 0, (UINT)liveState.height, imagePtr, liveState.bitmapInfo, DIB_RGB_COLORS);

我不知道用什么代替 DIB_RGB_COLORS 作为最后一个参数。我只发现此参数的另一个值是 DIB_PAL_COLORS。我想应该有一个灰度选项?

这是我程序的第一步...如果您对如何将图像指针插入 opencv 容器有任何建议,我也会非常高兴 :-)。

提前致谢!

最佳答案

看来你们很亲密。显示灰度图像的方法是使用调色板。这只是代表黑色和白色之间所有阴影的 256 个 RGB 条目:

std::vector<RGBQUAD> pal(256);
for (int32_t i(0); i < 256; ++i) {
pal[i].rgbRed = pal[i].rgbGreen = pal[i].rgbBlue = i;
pal[i].rgbReserved = 0;
}

首先,您需要分配足够的内存来容纳 BITMAPINFOHEADER 以及定义要使用的调色板的 256 个 RGBQUAD 条目。

int32_t const bmi_size(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);

分配结构。我使用 _alloca 把它放在堆栈上,所以我不需要担心清理问题。

BITMAPINFO* bmi(static_cast<BITMAPINFO*>(alloca(bmi_size)));

需要设置BITMAPINFOHEADER的以下成员,其余可以留零。

bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi->bmiHeader.biWidth = static_cast<LONG>(width);
bmi->bmiHeader.biHeight = static_cast<LONG>(-height);
bmi->bmiHeader.biPlanes = 1;
bmi->bmiHeader.biBitCount = 8;
bmi->bmiHeader.biCompression = BI_RGB;

注意:因为我们有一个完整的 256 条目调色板,biClrUsed 可以保留设置为 0。来自 docs :

If this value is zero, the bitmap uses the maximum number of colors corresponding to the value of the biBitCount member...

接下来,设置调色板(这基本上是您的代码中被注释掉的部分)。

for (uint32_t i(0); i < 256; ++i) {
if (pal.size() > i) {
bmi->bmiColors[i] = pal[i];
} else {
bmi->bmiColors[i].rgbRed
= bmi->bmiColors[i].rgbGreen
= bmi->bmiColors[i].rgbBlue
= bmi->bmiColors[i].rgbReserved = 0;
}
}

注意:以上代码来自通用的调色板图像渲染函数。对于较小的调色板,它用黑色填充未使用的颜色。我想这可以重构为使用更少的条目以及将 biClrUsed 设置为适当的值。

现在位图 header 已准备就绪。在您的情况下,调用 SetDIBitsToDevice仍会使用 DIB_RGB_COLORS,因为“颜色表包含文字 RGB 值。”

我使用 CreateDIBitmap创建一个 DDB,稍后我可以使用 BitBlt 渲染它.

HBITMAP bitmap = ::CreateDIBitmap(dc
, &bmi->bmiHeader
, CBM_INIT
, data // Pointer to raw pixel data
, bmi
, DIB_RGB_COLORS);

关于C++:灰度位图头和活绘+opencv图像处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49798722/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com