C++:灰度位图标题和实时绘画+opencv图像处理
C++: Grayscale bitmap header and live painting + opencv image processing
我正在尝试显示来自黑白相机(Adimec N5A/CXP,使用GenIcam标准)的实时图像。
从供应商的示例(但在RGB 24中),我或多或少能够显示图像,但显色性非常奇怪(颜色和阴影而不是灰度)。我想我在位图标头声明中做错了什么:
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;
}
*/
我在BITMAPINFO结构的bmiColors字段中发现"biClrUsed"应该设置为256。然后我不知道我是否需要写一个块来描述"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。从文档中:
如果此值为零,则位图使用与
biBitCount
成员的值对应的最大颜色数...
接下来,设置调色板(这基本上是注释掉的代码部分)。
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
。
现在位图标头已准备就绪。在您的情况下,对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);
- 从数据库实时显示QT c++中的数据
- 在 Windows 8/10 技术中完全实时的屏幕捕获,没有延迟
- 有没有办法使用 c++ 实时阅读文本?
- 在本地网络中通过OpenCV(C++)实时流式传输图像
- 将相机数据从服务器实时流式传输到客户端
- 将实时(非静态)放在qt(c ++)上
- 线程之间的实时数据共享
- 如何在实时应用程序中锁定线程
- 如何检测是否在缓冲绘画动画中绘制最后一帧?
- OpenCV - 来自相机的实时馈送不流畅
- 如何提高 OpenCV 实时检测器应用程序的帧率?
- 使用 Opencv 将姿势值实时写入文本文件
- Firebase C++ Windows 上的实时数据库连接丢失
- 我在 IDA 或 dbg 或 olly 上看到的内存是否与我在 RAM 上实时加载的内存相同?
- 媒体基金会:WavSink以比实时消耗率更快的速度处理音频-是否可以实时限制后台处理
- 如何实时捕获相机的视频?
- ROOT中的实时更新
- C# 的垃圾回收会给实时音频应用程序带来问题吗?
- 如何编写日志文件,以便可以使用记事本实时读取它以进行C++
- C++:灰度位图标题和实时绘画+opencv图像处理