Tạo ứng Dụng OpenCV Bằng C# - THỊ GIÁC MÁY TÍNH
Có thể bạn quan tâm
Để tránh code rườm rà khó hiểu mình đưa toàn bộ code vào project mẫu. Các bạn down về chạy thử, nếu xuất ra hình ảnh là ok.
Tham khảo: Convert Bitmap sang Mat và ngược lại
C# sử dụng định dạng hình ảnh bitmap, còn OpenCV là Mat, do đó cần có hàm để convert Mat thành Bitmap
Show More Bitmap^ TGMTbridge::MatToBitmap(cv::Mat img) { if (img.data == nullptr) return nullptr; if (img.type() != CV_8UC3) { throw gcnew NotSupportedException("Only images of type CV_8UC3 are supported for conversion to Bitmap"); } //create the bitmap and get the pointer to the data Bitmap ^bmpimg = gcnew Bitmap(img.cols, img.rows, PixelFormat::Format24bppRgb); BitmapData ^data = bmpimg->LockBits(System::Drawing::Rectangle(0, 0, img.cols, img.rows), ImageLockMode::WriteOnly, PixelFormat::Format24bppRgb); byte *dstData = reinterpret_cast<byte*>(data->Scan0.ToPointer()); unsigned char *srcData = img.data; for (int row = 0; row < data->Height; ++row) { memcpy(reinterpret_cast<void*>(&dstData[row*data->Stride]), reinterpret_cast<void*>(&srcData[row*img.step]), img.cols*img.channels()); } bmpimg->UnlockBits(data); delete(data); img.release(); return bmpimg; }| 12345678910111213141516171819202122232425262728 | Bitmap^TGMTbridge::MatToBitmap(cv::Mat img){if(img.data==nullptr)returnnullptr;if(img.type()!=CV_8UC3){throwgcnew NotSupportedException("Only images of type CV_8UC3 are supported for conversion to Bitmap");} //create the bitmap and get the pointer to the dataBitmap^bmpimg=gcnew Bitmap(img.cols,img.rows,PixelFormat::Format24bppRgb); BitmapData^data=bmpimg->LockBits(System::Drawing::Rectangle(0,0,img.cols,img.rows),ImageLockMode::WriteOnly,PixelFormat::Format24bppRgb); byte*dstData=reinterpret_cast<byte*>(data->Scan0.ToPointer()); unsignedchar*srcData=img.data; for(introw=0;row<data->Height;++row){memcpy(reinterpret_cast<void*>(&dstData[row*data->Stride]), reinterpret_cast<void*>(&srcData[row*img.step]), img.cols*img.channels());} bmpimg->UnlockBits(data);delete(data);img.release();returnbmpimg;} |
Còn đây là hàm convert Bitmap thành Mat
Show More cv::Mat BitmapToMat(Bitmap^ bitmap) { Drawing::Rectangle rect = Drawing::Rectangle(0, 0, bitmap->Width, bitmap->Height); BitmapData^ bmpData = bitmap->LockBits(rect, ImageLockMode::ReadWrite, bitmap->PixelFormat); // data = scan0 is a pointer to our memory block. IntPtr data = bmpData->Scan0; // step = stride = amount of bytes for a single line of the image size_t step = bmpData->Stride; // So you can try to get you Mat instance like this: cv::Mat mat; if (bitmap->PixelFormat == PixelFormat::Format8bppIndexed) { mat = cv::Mat(bitmap->Height, bitmap->Width, CV_8UC1, data.ToPointer(), step); } else if (bitmap->PixelFormat == PixelFormat::Format24bppRgb) { mat = cv::Mat(bitmap->Height, bitmap->Width, CV_8UC3, data.ToPointer(), step); } else { TGMTbridgeUtil::ShowErrorBox("IPSS error", "Does not support input image because don't know format"); } // Unlock the bits. bitmap->UnlockBits(bmpData); delete(bmpData); return mat; }| 12345678910111213141516171819202122232425262728293031323334 | cv::Mat BitmapToMat(Bitmap^bitmap){Drawing::Rectangle rect=Drawing::Rectangle(0,0,bitmap->Width,bitmap->Height); BitmapData^bmpData=bitmap->LockBits(rect,ImageLockMode::ReadWrite,bitmap->PixelFormat); // data = scan0 is a pointer to our memory block.IntPtr data=bmpData->Scan0; // step = stride = amount of bytes for a single line of the imagesize_t step=bmpData->Stride;// So you can try to get you Mat instance like this:cv::Mat mat; if(bitmap->PixelFormat==PixelFormat::Format8bppIndexed){mat=cv::Mat(bitmap->Height,bitmap->Width,CV_8UC1,data.ToPointer(),step);}elseif(bitmap->PixelFormat==PixelFormat::Format24bppRgb){mat=cv::Mat(bitmap->Height,bitmap->Width,CV_8UC3,data.ToPointer(),step);}else{TGMTbridgeUtil::ShowErrorBox("IPSS error","Does not support input image because don't know format");} // Unlock the bits.bitmap->UnlockBits(bmpData);delete(bmpData);returnmat;} |
Download
Nếu các bước trên phức tạp đối với bạn hoặc gặp lỗi khó giải quyết thì sử dụng source có sẵn. Mình có viết 1 sample đơn giản để minh họa việc gọi C++ từ C#. Trong repo Github có nhiều project sample, các bạn chạy riêng CsCallCpp.sln để hiểu cách C# gọi C++;
Solution CsCallCpp.sln load 1 ảnh rồi làm mờ bằng thuật toán blur(). Nhớ là clone submodule mới build được chương trình.
Trong Solution có nhiều project:
- libjpeg-turbo: dùng để xử lý ảnh jpg
- libpng: dùng để xử lý ảnh png
- zlib: nén/giải nén data, dùng cho 2 project trên
- opencv_core: project chính của opencv xử lý các phép tính toán mat (matrix – ma trận)
- opencv_highgui: tạo form hiển thị Mat, các control như trackbar, button,…
- opencv_imgcodecs: load ảnh bằng cách gọi các lib libjpeg-turbo, >libpng
- opencv_imgproc: các phép biến đổi hình ảnh bằng phép tính toán ma trận
- Sample: project xử lý ảnh viết bằng C++ build ra file lib
- UI: project C# để làm giao diện
- TGMTbridge: cầu nối giữa UI và Sample
Lưu ý: khi Visual Studio 2017 hỏi có retarget các project không thì các bạn cứ chọn cancel 
https://github.com/thigiacmaytinh/TGMTcpp
Từ khóa » Sử Dụng Opencv Trong C#
-
Các Thư Viện C# Wrapper Cho OpenCV -.NET Cơ Bản
-
Sử Dụng Open CV Với C# - GitHub Pages
-
OpenCV Với C# Nhận Dạng Cử Chỉ Tay - Programming - Dạy Nhau Học
-
OpenCV Là Gì? Cách Sử Dụng OpenCV Như Thế Nào? - Teky
-
OpenCV Là Gì? Học Computer Vision Không Khó! | TopDev
-
Xử Lý ảnh #1 - Hướng Dẫn Nhúng Thư Viện EmguCV Vào C#.NET ...
-
Nhận Dạng Khuôn Mặt Người Sử Dụng OpenCV Trong CSharp - 123doc
-
Sử Dụng OpenCV để Tìm điểm Chính Giữa Của 1 Hình - Viblo
-
Opencv Là Gì? Thư Viện Mở Ra Thế Giới Cho “thị Giác Máy Tính”
-
Hướng Dẫn Lập Trình Nhận Dạng Hình ảnh Với Opencv - DVMS
-
[C#] Hướng Dẫn Detect Face And Crop Image Sử Dụng EmguCV ...
-
Đồ Án - Nhận Dạng Khuôn Mặt Người Sử Dụng OpenCV Trong ...