1. 程式人生 > >在C#中使用OpenCV(使用GOCW)

在C#中使用OpenCV(使用GOCW)

在C#中使用OpenCV(使用GOCW)

1、什麼是GOCW

      為了解決在Csharp下編寫OpenCV程式的問題,我做過比較深入的研究,並且實現了高效可用的方法GreenOpenCsharpWrapper(GOCW)。通過這種方法,能夠分離介面和演算法業務,高效率完成演算法呼叫,而且非常方便進行演算法維護。應該說是我在多年專案實踐中不斷總結提煉出來的一點東西。        GOCW的釋出地址為:https://gitee.com/jsxyhelu2020/gocw

2、GOCW有什麼特點

 

  • 分離介面和演算法業務
  • 影象資料直接通過記憶體傳值,高效率完成演算法呼叫
  • 直接編寫C++語法程式,方便維護改進
  • 在C#中可以通過CLR方式引用,提供函式級別介面
  • 開放原始碼

3、GOCW在VS中的環境配置

下載gocw_master,解壓後獲得兩個目錄檔案。

其中,GOCW是類庫檔案,而WINFORM_DEMO是引用範例。

使用VS2017或者更高版本開啟WINFORM_DEMO.sln(或新建winform程式),在“引用”處新增GOCW的引用。

  特別需要注意,正確編譯GOCW需要OpenCV的正確配置,所以需要正確設定include和lib,並且保證對應版本的dll檔案能夠被正確訪問。
  特別需要注意1:保證dll和csharp程式的.net目標框架是一致的       特別需要注意2:保證dll和csharp程式的.net目標框架是一致的 配置管理器中,所有專案版本全部使用64位   4、測試程式碼 可以直接參考 WINFROM_DEMO 新增GOCW的標頭檔案 using GOCW;   編寫GOCW呼叫程式碼,你也可以根據需要吧Client的定義放在Form中。你實際使用過程中需要修改lena的地址。    private void button1_Click(object sender, EventArgs e)
        {
            Bitmap bmp = (Bitmap)Bitmap.FromFile("e:/template/lena.jpg");
            GOCWClass client = new GOCWClass();
            //呼叫影象處理演算法
            MemoryStream ms = new MemoryStream();
            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            byte[] bytes = ms.GetBuffer();
            Bitmap bitmap = client.testMethod(bytes);
            pictureBox1.Image = bitmap;
        }   可以看到,實現了“灰度”變化。 5、原理簡介

 

GOCW是通過CLR的方式進行呼叫,關於CLR的原理這裡不展開。重點將一下你在哪裡新增影象處理演算法,開啟 GOCW.h檔案

#pragma once
#include "opencv.hpp"
#using <system.drawing.dll>
using namespace System;
using namespace System::Data;
using namespace System::IO;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
using namespace std;
namespace GOCW {
    public ref class GOCWClass
    {
    public:
        /////例子函式//////
        //1.傳遞影象
      /*  MemoryStream ms = new MemoryStream();
        b.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
        byte[] bytes = ms.GetBuffer();
        Bitmap bitmap = client.testMethod(bytes);*/
        Bitmap^  GOCWClass::testMethod(cli::array<unsigned char>^ pCBuf1);
        //2.引用傳遞int
        /*unsafe
        {
        int* value = stackalloc int[1];
        value[0] = 0;
        int iret = client.allTest(2, 3, value);
        }*/
        int GOCWClass::allTest(int a, int b, int* c);
        
        //3.引用傳遞字串
        System::String^ GOCWClass::allTestStr(System::String^ inputStr);
        /////業務函式//////
        /*unsafe
        {
            int* value = stackalloc int[1];//返回程式碼
            value[0] = 0;
            bitmap = client.fetchresult(bytes, value);//呼叫來自GOClrClasslibrary影象處理演算法
            if (value[0] == 0)//0真1假
            {
                res = true;
            }
            else
            {
                res = false;
            }
        }*/
        Bitmap^  GOCWClass::fetchresult(cli::array<unsigned char>^ pCBuf1, int* errorCode);
    
    };
}   這裡以“三明治”的方法將各種實現的方法進行了申明,具體的實現在GOCW.cpp中,比如我們舉一個例子。 //1.傳遞影象
Bitmap^  GOCWClass::testMethod(cli::array<unsigned char>^ pCBuf1)
{
    ////////////////////////////////將輸入cli::array<unsigned char>轉換為cv::Mat/////////////////////////
    pin_ptr<System::Byte> p1 = &pCBuf1[0];
    unsigned char* pby1 = p1;
    cv::Mat img_data1(pCBuf1->Length, 1, CV_8U, pby1);
    cv::Mat img_object = cv::imdecode(img_data1, cv::IMREAD_UNCHANGED);
    if (!img_object.data)
        return nullptr;
    ////////////////////////////////////////////OpenCV的演算法處理過程////////////////////////////////////
    Mat draw = img_object.clone();
    cvtColor(draw, draw, COLOR_BGR2GRAY);
    cvtColor(draw, draw, COLOR_GRAY2BGR);
    /////////////////////////將cv::Mat轉換為Bitmap(只能傳輸cv_8u3格式資料)///////////////////////////////
    if (!draw.data)
        return nullptr;
    Bitmap^ bitmap = MatToBitmap(draw);
    return bitmap;
}   在這段程式碼中 Mat draw = img_object.clone();
cvtColor(draw, draw, COLOR_BGR2GRAY);
cvtColor(draw, draw, COLOR_GRAY2BGR);   是具體業務函式,可以根據實際演算法要求進行修改。關於引數的傳入傳出,在其他幾個函式中都有說明。

 

6、初步小結

 

      雖然GOCW相比較OpenCVSharp複雜一點,但是它能夠和現有系統更緊密結合,優勢也非常明顯。如果你首先是影象處理開發者,需要為演算法尋找一個可以執行的平臺,那麼GOCW基於CLR的封裝形式,肯定更適合你!

         感謝閱讀至此,希望有所幫助!

&n