如何在c#中使用opencv函數(shù)庫
這個demo用c#實現(xiàn)圖片裁剪和半透明融合的功能演示程序。功能挺簡單的,就是把一張固定大小的圖片先做邊緣羽化,然后貼到一個圓形泡泡形狀的底圖上,最后把結(jié)果半透明融合到一張背景圖上。
C#實現(xiàn)圖像的羽化、將圖片裁剪復(fù)制到一個圓形圖片這些都挺簡單的,最后一步融合到背景圖上需要用到opencv的seamlessClone方法。網(wǎng)上搜索c#使用opencv的方法有很多,一種是直接使用opencv的C#版本,一種是先把opencv的方法封裝到一個dll然后用c#調(diào)用這個dll導(dǎo)出的方法。對于我這個需求,后一種方法最合算了。我只用到了一個方法而已。vc中怎么使用opencv就不說了,直接開始吧。
用VC創(chuàng)建一個win32項目,選擇生成dll動態(tài)鏈接庫。
添加一個cpp文件:
// opencvImage.cpp : Defines the exported functions for the DLL application. // #include "stdafx.h" #include <opencv2/core/core.hpp> #include "opencv2/photo.hpp" #ifdef _DEBUG #pragma comment(lib,"opencv_core331d.lib") #pragma comment(lib,"opencv_imgproc331d.lib") #pragma comment(lib,"opencv_photo331d.lib") #else #pragma comment(lib,"opencv_core331.lib") #pragma comment(lib,"opencv_imgproc331.lib") #pragma comment(lib,"opencv_photo331.lib") #endif #define Export_API extern "C" _declspec(dllexport) using namespace cv; Export_API void _stdcall Blend(unsigned char * src, int width, int height, int stride, int bitcount, unsigned char *dst, int alpha) { double beta,alpha1 = alpha / 255.0 ; Mat src1(width, height, CV_8UC3, src, stride); Mat src2(width, height, CV_8UC3, dst, stride); Mat dst1(width, height, CV_8UC3, dst, stride); beta = (1.0 - alpha1); addWeighted(src1, alpha1, src2, beta, 0.0, dst1); } Export_API void _stdcall PoissonBlend(unsigned char * src, int width, int height, int stride, int bitcount, unsigned char *dst, int flags) { int cx = width >> 1; int cy = height >> 1; int numpts = 5; Point point(cx, cy); Point pts[] = { { 80, 40 }, { 30, height - 80 }, { cx, height - 20 }, { width - 30, height - 80 }, { width - 80, 40 } }; Mat img0(width, height, CV_8UC3, src, stride); Mat dst0(width, height, CV_8UC3, dst, stride); Mat final = Mat::zeros(img0.size(), CV_8UC3); Mat mask = Mat::zeros(img0.size(), CV_8UC1); const Point* pts4[1] = { &pts[0] }; fillPoly(mask, pts4, &numpts, 1, Scalar(255, 255, 255), 8, 0); // circle(mask, point, cx - 30, Scalar(255, 255, 255),-1); bitwise_and(img0, img0, final, mask); seamlessClone(img0, dst0, mask, point, dst0, flags); }
由于使用了_stdcall,所以還需要一個def文件,否則導(dǎo)出函數(shù)名字前面有個下劃線,_Blend
加一個def文件:
LIBRARY "opencvImage" EXPORTS Blend @1 PoissonBlend @2
C#調(diào)用方法:
1. 在cs文件開頭添加
using System.Runtime.InteropServices;
2.在用到的地方添加
[DllImport("opencvImage.dll")] unsafe public static extern void Blend(byte* src, int width, int height, int stride, int bitcount, byte* dst, int alpha);
3.調(diào)用dll方法
Bitmap bp = new Bitmap(srcImage); System.Drawing.Rectangle rect = new System.Drawing.Rectangle(x, y, width, height); BitmapData src = bp.LockBits(rect, ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); Bitmap dp = new Bitmap(destImage); System.Drawing.Rectangle dstRect = new System.Drawing.Rectangle(dx, dy, width, height); BitmapData dst = dp.LockBits(dstRect, ImageLockMode.ReadWrite,PixelFormat.Format24bppRgb); int nPitch = src.Stride; int bitCount = 3; byte* lpsrc = (byte*)src.Scan0; byte* lpdst = (byte*)dst.Scan0; byte alpha = 128; Blend(lpsrc, width, height, nPitch, bitCount ,lpdst, alpha); bp.UnlockBits(src); dp.UnlockBits(dst); return dp;
最后說明一下
1.VC編譯的dll需要放到C#可執(zhí)行程序的目錄下,也就是bin目錄下的debug或release目錄下,否則會提示一些錯誤。dll的依賴庫也需要放進來,比如我用到了opencv_core331.dll opencv_imgproc331.dll opencv_photo331.dll三個庫。
2.如果C#程序不需要用到opencv的對象,可以直接傳遞指針給dll,這樣使用起來很方便。就像下面這樣:
Export_API void _stdcall Blend(unsigned char * src, int width, int height, int stride, int bitcount, unsigned char *dst, int alpha) { double beta,alpha1 = alpha / 255.0 ; Mat src1(width, height, CV_8UC3, src, stride); Mat src2(width, height, CV_8UC3, dst, stride); Mat dst1(width, height, CV_8UC3, dst, stride); beta = (1.0 - alpha1); addWeighted(src1, alpha1, src2, beta, 0.0, dst1); }
3.很多人說c#調(diào)用opencv封裝的dll會遇到內(nèi)存泄漏方面的問題,我覺得如果不用opencv的對象,內(nèi)存申請和釋放都在c#中完成,只是傳遞指針給opencv做處理,應(yīng)該沒問題。
以上就是如何在c#中使用opencv的詳細內(nèi)容,更多關(guān)于c#中使用opencv的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用C#創(chuàng)建Windows服務(wù)的實例代碼
這篇文章主要介紹了使用C#創(chuàng)建Windows服務(wù)的實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07C# 實現(xiàn)ADSL自動斷網(wǎng)和撥號的方法(適用于撥號用戶)
下面小編就為大家?guī)硪黄狢# 實現(xiàn)ADSL自動斷網(wǎng)和撥號的方法(適用于撥號用戶)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12C# Dynamic關(guān)鍵字之:解析dynamic就是Object
本篇文章是對C#中dynamic關(guān)鍵字就是Object進行了詳細的分析介紹,需要的朋友參考下2013-05-05Unity?百度AI實現(xiàn)Logo商標(biāo)識別
本文主要介紹了Unity實現(xiàn)檢測和識別圖片中的品牌LOGO信息。即對于輸入的一張圖片(可正常解碼,且長寬比適宜),輸出圖片中LOGO的名稱、位置和置信度。需要的可以參考一下2022-01-01