如何在c#中使用opencv函數(shù)庫(kù)
這個(gè)demo用c#實(shí)現(xiàn)圖片裁剪和半透明融合的功能演示程序。功能挺簡(jiǎn)單的,就是把一張固定大小的圖片先做邊緣羽化,然后貼到一個(gè)圓形泡泡形狀的底圖上,最后把結(jié)果半透明融合到一張背景圖上。
C#實(shí)現(xiàn)圖像的羽化、將圖片裁剪復(fù)制到一個(gè)圓形圖片這些都挺簡(jiǎn)單的,最后一步融合到背景圖上需要用到opencv的seamlessClone方法。網(wǎng)上搜索c#使用opencv的方法有很多,一種是直接使用opencv的C#版本,一種是先把opencv的方法封裝到一個(gè)dll然后用c#調(diào)用這個(gè)dll導(dǎo)出的方法。對(duì)于我這個(gè)需求,后一種方法最合算了。我只用到了一個(gè)方法而已。vc中怎么使用opencv就不說(shuō)了,直接開(kāi)始吧。
用VC創(chuàng)建一個(gè)win32項(xiàng)目,選擇生成dll動(dòng)態(tài)鏈接庫(kù)。
添加一個(gè)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,所以還需要一個(gè)def文件,否則導(dǎo)出函數(shù)名字前面有個(gè)下劃線,_Blend
加一個(gè)def文件:
LIBRARY "opencvImage" EXPORTS Blend @1 PoissonBlend @2
C#調(diào)用方法:
1. 在cs文件開(kāi)頭添加
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;
最后說(shuō)明一下
1.VC編譯的dll需要放到C#可執(zhí)行程序的目錄下,也就是bin目錄下的debug或release目錄下,否則會(huì)提示一些錯(cuò)誤。dll的依賴庫(kù)也需要放進(jìn)來(lái),比如我用到了opencv_core331.dll opencv_imgproc331.dll opencv_photo331.dll三個(gè)庫(kù)。
2.如果C#程序不需要用到opencv的對(duì)象,可以直接傳遞指針給dll,這樣使用起來(lái)很方便。就像下面這樣:
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.很多人說(shuō)c#調(diào)用opencv封裝的dll會(huì)遇到內(nèi)存泄漏方面的問(wèn)題,我覺(jué)得如果不用opencv的對(duì)象,內(nèi)存申請(qǐng)和釋放都在c#中完成,只是傳遞指針給opencv做處理,應(yīng)該沒(méi)問(wèn)題。
以上就是如何在c#中使用opencv的詳細(xì)內(nèi)容,更多關(guān)于c#中使用opencv的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C#用表達(dá)式樹(shù)構(gòu)建動(dòng)態(tài)查詢的方法
這篇文章主要介紹了C#用表達(dá)式樹(shù)構(gòu)建動(dòng)態(tài)查詢的方法,幫助大家更好的理解和學(xué)習(xí)c#,感興趣的朋友可以了解下2020-12-12
使用C#創(chuàng)建Windows服務(wù)的實(shí)例代碼
這篇文章主要介紹了使用C#創(chuàng)建Windows服務(wù)的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07
C# 實(shí)現(xiàn)ADSL自動(dòng)斷網(wǎng)和撥號(hào)的方法(適用于撥號(hào)用戶)
下面小編就為大家?guī)?lái)一篇C# 實(shí)現(xiàn)ADSL自動(dòng)斷網(wǎng)和撥號(hào)的方法(適用于撥號(hào)用戶)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
C# Dynamic關(guān)鍵字之:解析dynamic就是Object
本篇文章是對(duì)C#中dynamic關(guān)鍵字就是Object進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C#基礎(chǔ)之Lambda表達(dá)式用法實(shí)例教程
這篇文章主要介紹了C#中Lambda表達(dá)式用法,并與之前所述的匿名方法做一比較,詳細(xì)的講述了Lambda表達(dá)式的定義及具體用法,需要的朋友可以參考下2014-09-09
c#下注冊(cè)表操作的一個(gè)小細(xì)節(jié)
c#下注冊(cè)表操作的一個(gè)小細(xì)節(jié)...2007-11-11
Unity?百度AI實(shí)現(xiàn)Logo商標(biāo)識(shí)別
本文主要介紹了Unity實(shí)現(xiàn)檢測(cè)和識(shí)別圖片中的品牌LOGO信息。即對(duì)于輸入的一張圖片(可正常解碼,且長(zhǎng)寬比適宜),輸出圖片中LOGO的名稱、位置和置信度。需要的可以參考一下2022-01-01
Unity游戲開(kāi)發(fā)實(shí)現(xiàn)場(chǎng)景切換示例
這篇文章主要為大家介紹了Unity游戲開(kāi)發(fā)實(shí)現(xiàn)場(chǎng)景切換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08

