将 GDIPlus::Bitmap 转换为 cv::Mat(OpenCV C++ 接口)
我正在尝试将 GDIPlus::Bitmap 转换为 openCV Mat 对象,但我遇到了访问冲突问题,这意味着我没有做正确的事情,但我一遍又一遍地查看代码,我认为它应该有效。
有人看到一个明显的问题吗?
cv::Mat ConvertToOpenCV(Gdiplus::Bitmap &image) {
cv::Mat *retval = new cv::Mat(
image.GetWidth(), image.GetHeight(), CV_8UC3
);
Gdiplus::BitmapData source;
Gdiplus::Rect rect( 0, 0, image.GetWidth(), image.GetHeight() );
Gdiplus::Status status =
image.LockBits( &rect, Gdiplus::ImageLockModeRead, PixelFormat24bppRGB, &source );
if ( status != Gdiplus::Ok ) {
// Some error condition
return retval; // No image copied
}
BYTE *destination = (BYTE *)retval->data;
for ( int y = 0; y != source.Height; ++y ) {
BYTE *src = (BYTE *) source.Scan0 + y * source.Stride;
BYTE *dst = (BYTE *)(destination + y * retval->step);
memcpy( dst, src, 3 * source.Width ); // Access Violation happens here
}
image.UnlockBits(&source);
return retval;
}
I'm trying to convert a GDIPlus::Bitmap into an openCV Mat object, but I'm running into problems with Access Violations, which means I'm not doing something right, but I've looked over the code over and over, and I think it should work.
Does anyone see an obvious problem?
cv::Mat ConvertToOpenCV(Gdiplus::Bitmap &image) {
cv::Mat *retval = new cv::Mat(
image.GetWidth(), image.GetHeight(), CV_8UC3
);
Gdiplus::BitmapData source;
Gdiplus::Rect rect( 0, 0, image.GetWidth(), image.GetHeight() );
Gdiplus::Status status =
image.LockBits( &rect, Gdiplus::ImageLockModeRead, PixelFormat24bppRGB, &source );
if ( status != Gdiplus::Ok ) {
// Some error condition
return retval; // No image copied
}
BYTE *destination = (BYTE *)retval->data;
for ( int y = 0; y != source.Height; ++y ) {
BYTE *src = (BYTE *) source.Scan0 + y * source.Stride;
BYTE *dst = (BYTE *)(destination + y * retval->step);
memcpy( dst, src, 3 * source.Width ); // Access Violation happens here
}
image.UnlockBits(&source);
return retval;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这里有一个问题:
Mat 构造函数的第一个参数是行,第二个参数是列。所以你应该这样做:
这可能会导致访问冲突。
编辑
另外,OpenCV 图像默认为 BGR,而不是 RGB。因此,如果您完成此操作,然后使用 imshow 显示图像,您的蓝色和红色值将向后。您可以通过在 return 语句之前调用
cv::cvtColor(retval, retval, CV_RGB2BGR)
来解决此问题。Here's one problem:
The Mat constructor's first argument is rows, second is columns. So you should be doing this:
That could cause an access violation.
Edit
Also, OpenCV images are by default BGR, not RGB. So if you get this working and then display the image with imshow, your blue and red values will be backward. You can fix this with the call
cv::cvtColor(retval, retval, CV_RGB2BGR)
before your return statement.您可以使用我的即用类 CGdiPlus 来自动从 cv::Mat 转换为 Gdiplus::Bitmap,反之亦然:
OpenCV / Tesseract:如何替换 libpng、libtiff 等GDI+ 位图(通过 GDI+ 加载到 cv::Mat)
You can use my ready to use class CGdiPlus that does automatic conversion from cv::Mat to Gdiplus::Bitmap and vice versa:
OpenCV / Tesseract: How to replace libpng, libtiff etc with GDI+ Bitmap (Load into cv::Mat via GDI+)
正如 SSteve 所指出的,Mat 构造函数先行后列,因此先使用高度,然后使用宽度。但是,您无需亲自进行实际复制。您可以使用 Mat 构造函数之一来包装现有数据而不进行复制,然后通过调用 clone 成员函数强制其进行复制。
唯一的麻烦是 Gdiplus::Bitmap 理论上支持像素布局的负载;然而,其中大多数都非常具有异国情调。您可以按如下方式处理简单的情况:
As SSteve notes the Mat constructors go rows then columns, so use height then width. However there is no need to do the actual copy yourself. You can use one of the Mat constructors that will wrap existing data without copying and then force it to copy by calling the clone member function.
The only other trouble is that Gdiplus::Bitmap in theory supports loads of pixel layouts; however, most of these are pretty exotic. You can handle the simple case as follows: