一、Bimtap转Mat
cv::Mat BitmapToCvMat(System::Drawing::Bitmap^ image)
{
cv::Mat dst;
if (image == nullptr)
{
return dst;
}
int imgH = image->Height;
int imgW = image->Width;
int channel = 3;
int imgtype = 0;
if (image->PixelFormat == System::Drawing::Imaging::PixelFormat::Format8bppIndexed)
{
channel = 1;
imgtype = CV_8UC1;
}
else if (image->PixelFormat == System::Drawing::Imaging::PixelFormat::Format24bppRgb)
{
channel = 3;
imgtype = CV_8UC3;
}
else if (image->PixelFormat == System::Drawing::Imaging::PixelFormat::Format32bppArgb)
{
channel = 4;
imgtype = CV_8UC4;
}
else
{
return dst;
}
System::Drawing::Imaging::BitmapData^ bitmapData = image->LockBits(System::Drawing::Rectangle(0, 0, imgW, imgH), System::Drawing::Imaging::ImageLockMode::ReadWrite, image->PixelFormat);
int actualwidth = imgW*channel;
int offset = bitmapData->Stride - actualwidth;
int posScan = 0, posReal = 0;
if (0 != offset)
{
int step = ((imgW * channel * 8 + 31) / 32) * 4;
dst = cv::Mat(imgH, imgW, imgtype, (void*)(bitmapData->Scan0), step);
}
else
{
dst = cv::Mat(imgH, imgW, imgtype, (void*)(bitmapData->Scan0));
}
image->UnlockBits(bitmapData);
return dst;
}
二、Mat转Bitmap
System::Drawing::Bitmap^ CvMatToBitmap(cv::Mat cvimg) { if (cvimg.empty()) return nullptr; if (cvimg.depth() != CV_8U) return nullptr; int imgW = cvimg.cols; int imgH = cvimg.rows; int step = cvimg.step; int channel = cvimg.channels(); System::Drawing::Imaging::PixelFormat pixelFormat; if (channel == 1) { pixelFormat = System::Drawing::Imaging::PixelFormat::Format8bppIndexed; } else if (channel == 3) { pixelFormat = System::Drawing::Imaging::PixelFormat::Format24bppRgb; } else if (channel == 4) { pixelFormat = System::Drawing::Imaging::PixelFormat::Format32bppArgb; } else { return nullptr; } System::Drawing::Bitmap^ resultimage = nullptr; resultimage = gcnew System::Drawing::Bitmap(imgW, imgH, pixelFormat); System::Drawing::Imaging::BitmapData^ resultimageData = resultimage->LockBits(System::Drawing::Rectangle(0, 0, imgW, imgH), System::Drawing::Imaging::ImageLockMode::ReadWrite, resultimage->PixelFormat); int actualWidth = imgW*channel; int offset = resultimageData->Stride - actualWidth; uchar* outputData_b = (uchar*)(void*)resultimageData->Scan0; uchar* img = cvimg.data; int posreal = 0, posscan = 0; for (int r = 0; r < imgH; r++) { for (int c = 0; c < actualWidth; c++) { /**outputData_b = *img; utputData_b++; img++;*/ outputData_b[posscan++] = img[posreal++]; } //outputData_b += offset; posscan += offset; } resultimage->UnlockBits(resultimageData); return resultimage; }
以上是通过深拷贝方式实现,实际上,当图片宽为4的倍数时,有更简单的方式:
if (imgW % 4 == 0)
{
if (cvimg.isContinuous())
{
resultimage = gcnew System::Drawing::Bitmap(imgW, imgH, step, pixelFormat, System::IntPtr(cvimg.data));
}
else
{
cv::Mat cvtemp = cvimg.clone();
resultimage = gcnew System::Drawing::Bitmap(imgW, imgH, step, pixelFormat, System::IntPtr(cvtemp.data));
}return resultimage;
}
但是传到C#中时,如果后续使用可能就会因被自动释放掉而报错。目前没有什么好的解决办法,我只能一律使用深拷贝方式,速度上肯定比这个慢,若是有好的主意,可以留言评论。
Original: https://www.cnblogs.com/Clark-Zhang/p/14442522.html
Author: 朔月の流光
Title: C++/CLR中Opencv的Mat与C#中的Bitmap互转
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/712707/
转载文章受原作者版权保护。转载请注明原作者出处!