Sử dụng OpenCV function với C#.Net
C#
18
#OpenCV
3
Male avatar

vankhangfet viết ngày 08/10/2015

Sử dụng OpenCV function với C#.Net

Nếu bạn đã từng làm một số project có liên quan đến xử lý ảnh thì chắc hẳn sẽ biết thư viện OpenCV. Hiện tại đã có phiên bản OpenCV cho .Net là EmgCV, tuy nhiên với ứng dụng thương mại bạn sẽ phải trả tiền. Để tăng tốc độ xử lý cũng như dễ dàng hơn thì theo mình bạn nên sử dụng OpenCV trước sau đó mới đến EmguCV.

Với những ai chưa nghe đến OpenCV hoặc EmguCV bao giờ thì bạn có thể tham khảo ở link sau:

OpenCV
EmguCV

OpenCV được viết bằng C++, nên sẽ có chút khó khăn khi bạn muốn sử dụng các function của OpenCV trên C#.Net.

Tình huống mình gặp phải đó là trên app của mình có hiển thị ảnh ,với Winform app thì việc hiển thị ảnh hay dùng đối tượng Bitmap. Nhưng OpenCV xử lý ảnh dưới dạng ma trận là kiểu Cv::Mat. Mình mất thời gian để tìm hiểu convert giữa 2 kiểu dữ liệu này và cách làm như sau:

  1. Để dùng OpenCV trên project.Net bạn cần phải xây dựng một class warpper, class này sẽ làm nhiệm vụ giao tiếp giữa C++ và C# như trong project của mình. Việc viết một class wrapper như thế nào mình sẽ viết chi tiết vào một topic khác ^^.

alt text

  1. Khi có lớp wrapper này rồi thì công việc còn lại chỉ là convert kiểu dữ liệu để xử dụng. Các bạn sử dụng các method sau:
  • Convert Bitpmap to Mat

    Mat BitmapToMat(System::Drawing::Bitmap^ bitmap)`
    {
    IplImage* tmp;
    
    System::Drawing::Imaging::BitmapData^ bmData = bitmap->LockBits(System::Drawing::Rectangle(0, 0, bitmap->Width, bitmap-`>Height), System::Drawing::Imaging::ImageLockMode::ReadWrite, bitmap->PixelFormat);`
    if (bitmap->PixelFormat == System::Drawing::Imaging::PixelFormat::Format8bppIndexed)
    {
        tmp = cvCreateImage(cvSize(bitmap->Width, bitmap->Height), IPL_DEPTH_8U, 1);
        tmp->imageData = (char*)bmData->Scan0.ToPointer();
    }
    
    else if (bitmap->PixelFormat == System::Drawing::Imaging::PixelFormat::Format24bppRgb)
    {
        tmp = cvCreateImage(cvSize(bitmap->Width, bitmap->Height), IPL_DEPTH_8U, 3);
        tmp->imageData = (char*)bmData->Scan0.ToPointer();
    }
    
    bitmap->UnlockBits(bmData);
    
    return Mat(tmp);
    }
    
  • Convert Mat to Bitmap

    System::Drawing::Bitmap^ MatToBitmap(Mat srcImg){
    int stride = srcImg.size().width * srcImg.channels();//calc the srtide
    int hDataCount = srcImg.size().height;
    
    System::Drawing::Bitmap^ retImg;
    
    System::IntPtr ptr(srcImg.data);
    
    //create a pointer with Stride
    if (stride % 4 != 0){//is not stride a multiple of 4?
        //make it a multiple of 4 by fiiling an offset to the end of each row
    
        //to hold processed data
        uchar *dataPro = new uchar[((srcImg.size().width * srcImg.channels() + 3) & -4) * hDataCount];
    
        uchar *data = srcImg.ptr();
    
        //current position on the data array
        int curPosition = 0;
        //current offset
        int curOffset = 0;
    
        int offsetCounter = 0;
    
        //itterate through all the bytes on the structure
        for (int r = 0; r < hDataCount; r++){
            //fill the data
            for (int c = 0; c < stride; c++){
                curPosition = (r * stride) + c;
    
                dataPro[curPosition + curOffset] = data[curPosition];
            }
    
            //reset offset counter
            offsetCounter = stride;
    
            //fill the offset
            do{
                curOffset += 1;
                dataPro[curPosition + curOffset] = 0;
    
                offsetCounter += 1;
            } while (offsetCounter % 4 != 0);
        }
    
        ptr = (System::IntPtr)dataPro;//set the data pointer to new/modified data array
    
        //calc the stride to nearest number which is a multiply of 4
        stride = (srcImg.size().width * srcImg.channels() + 3) & -4;
    
        retImg = gcnew System::Drawing::Bitmap(srcImg.size().width, srcImg.size().height,
            stride,
            System::Drawing::Imaging::PixelFormat::Format24bppRgb,
            ptr);
    }
    else{
    
        //no need to add a padding or recalculate the stride
        retImg = gcnew System::Drawing::Bitmap(srcImg.size().width, srcImg.size().height,
            stride,
            System::Drawing::Imaging::PixelFormat::Format24bppRgb,
            ptr);
    }
    
    array^ imageData;
    System::Drawing::Bitmap^ output;
    
    // Create the byte array.
    {
        System::IO::MemoryStream^ ms = gcnew System::IO::MemoryStream();
        retImg->Save(ms, System::Drawing::Imaging::ImageFormat::Png);
        imageData = ms->ToArray();
        delete ms;
    }
    
    // Convert back to bitmap
    {
        System::IO::MemoryStream^ ms = gcnew System::IO::MemoryStream(imageData);
        output = (System::Drawing::Bitmap^)System::Drawing::Bitmap::FromStream(ms);
    }
    
    return output;
    }
    

    Bài viết trên mình có tham khảo tại:
    http://milindapro.blogspot.jp/2015/04/call-opencv-functions-from-cnet-bitmap.html

Hy vọng là những ghi chép này sẽ giúp bạn đỡ mất công khi gặp những tình huống như vậy

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

Male avatar

vankhangfet

2 bài viết.
16 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
Male avatar
27 10
UML Class Diagram Nếu như muốn biểu diễn mối quan hệ giữa các class như : Aggregation, Composition, Inheritance thì mình nghĩ UML Class Diagram th...
vankhangfet viết gần 3 năm trước
27 10
Bài viết liên quan
White
24 4
Tạo dummy data với Faker và Mockaroo – Xa rồi những ngày nhập tay nhàm chán Cuộc đời một thằng developer có rất nhiều việc rất chán nhưng phải làm...
Huy Hoàng Phạm viết hơn 2 năm trước
24 4
White
18 0
Nhân tiện vừa đọc bài viết liên quan tới OpenCV trên Kipalog, nên em xin giới thiệu về giải thuật sinh ảnh mosaic từ một ảnh gốc. Không hiểu sinh ả...
Cùi Bắp viết hơn 2 năm trước
18 0
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


Male avatar
{{userFollowed ? 'Following' : 'Follow'}}
2 bài viết.
16 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!