我正在尝试将GDIPlus :: Bitmap转换为openCV Mat对象,但我遇到了Access Violations的问题,这意味着我没有做正确的事情,但我已经查看了代码并且,我认为它应该工作。
有没有人看到明显的问题?
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;
}
答案 0 :(得分:2)
这是一个问题:
cv::Mat *retval = new cv::Mat(
image.GetWidth(), image.GetHeight(), CV_8UC3
);
Mat构造函数的第一个参数是行,第二个是列。所以你应该这样做:
cv::Mat *retval = new cv::Mat(
image.GetHeight(), image.GetWidth(), CV_8UC3
);
这可能会导致访问冲突。
修改强>
此外,OpenCV图像默认为BGR,而不是RGB。因此,如果您使用此工作,然后使用imshow显示图像,则您的蓝色和红色值将向后。您可以在返回声明之前使用cv::cvtColor(retval, retval, CV_RGB2BGR)
调用来解决此问题。
答案 1 :(得分:0)
您可以使用我准备使用的类CGdiPlus,它可以自动从cv :: Mat转换为Gdiplus :: Bitmap,反之亦然:
OpenCV / Tesseract: How to replace libpng, libtiff etc with GDI+ Bitmap (Load into cv::Mat via GDI+)
答案 2 :(得分:0)
由于SSteve注意到Mat构造函数会进行行然后是列,因此请使用height然后使用width。但是,您无需自己进行实际复制。您可以使用其中一个Mat构造函数来包装现有数据而不复制,然后通过调用克隆成员函数强制它进行复制。
唯一的另一个问题是理论上Gdiplus :: Bitmap支持大量的像素布局;然而,其中大部分都非常具有异国情调。您可以按如下方式处理简单的情况:
cv::Mat GdiPlusBitmapToOpenCvMat(Gdiplus::Bitmap* bmp)
{
auto format = bmp->GetPixelFormat();
if (format != PixelFormat24bppRGB)
return cv::Mat();
int wd = bmp->GetWidth();
int hgt = bmp->GetHeight();
Gdiplus::Rect rcLock(0, 0, wd, hgt);
Gdiplus::BitmapData bmpData;
if (!bmp->LockBits(&rcLock, Gdiplus::ImageLockModeRead, format, &bmpData) == Gdiplus::Ok)
return cv::Mat();
cv::Mat mat = cv::Mat(hgt, wd, CV_8UC3, static_cast<unsigned char*>(bmpData.Scan0), bmpData.Stride).clone();
bmp->UnlockBits(&bmpData);
return mat;
}