一、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#中時,如果后續使用可能就會因被自動釋放掉而報錯。目前沒有什么好的解決辦法,我只能一律使用深拷貝方式,速度上肯定比這個慢,若是有好的主意,可以留言評論。