可是這裏我想更進一步:但願可以用Csharp編寫界面,由於它更好用;可是又不想引入EmguCV相似的庫,由於裏面不少東西不是我須要的。那麼最直接的方法就是使用Csharp調用基於Opencv編寫的類庫文件(Dll)的,我取名叫作
GreenOpenCsharpWarper(GOCW)
通過比較長時間的探索研究,目前的GOCW已經能夠直接以函數的形式在內存中傳遞bitmap和Mat對象,達到了函數級別的應用。由於這裏涉及到託管代碼編寫,也就是CLR程序編寫,因此有比較複雜的地方;爲了展示GOCW的優良特性,我編寫實現GOGPY項目,也就是一個"Csharp編寫界面,OpenCV實現算法的實時視頻處理程序」,相關細節都包含其中。之因此叫「GPY」,是採集硬件這塊,我採用了
成像質量較好的
高拍儀設備(GaoPaiYi)。
這裏簡單將最核心內容進行講解。
GOCW的核心問題,
無非就是基於CLR之上的兩個方向的數據流轉換。核心函數爲
Bitmap
^ GOClrClass
:
:testMethod(cli
:
:array
<
unsigned
char
>
^ pCBuf1)
{
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,IMREAD_UNCHANGED);
//得到數據到img_object中去
//////////////////////////////////處理過程///////////////////////////////////////
cvtColor(img_object,img_object,
40);
/////////////////////////////////////////////////////////////////////////////////
Bitmap
^ bb
= MatToBitmap(img_object);
if (
!img_object.data)
return nullptr;
std
:
:vector
<uchar
> buf;
cv
:
:imencode(
".jpg", img_object, buf);
return bb;
}
以及
System
:
:Drawing
:
:Bitmap
^ MatToBitmap(
const cv
:
:Mat
& img)
{
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
PixelFormat fmt(PixelFormat
:
:Format24bppRgb);
Bitmap
^bmpimg
= gcnew Bitmap(img.cols, img.rows, fmt);
BitmapData
^data
= bmpimg
-
>LockBits(System
:
:Drawing
:
:Rectangle(
0,
0, img.cols, img.rows), ImageLockMode
:
:WriteOnly, fmt);
//byte *dstData = reinterpret_cast<byte*>(data->Scan0.ToPointer());
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);
return bmpimg;
}
而在chsarp中,直接
Bitmap b
=
new Bitmap(cam.Width, cam.Height, cam.Stride, PixelFormat.Format24bppRgb, m_ip);
// If the image is upsidedown
b.RotateFlip(RotateFlipType.RotateNoneFlipY);
srcImage
= b;
if (picPreview.Image
!= null)
picPreview.Image.Dispose();
//調用clr+opencv圖像處理模塊
MemoryStream ms
=
new MemoryStream();
b.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes
= ms.GetBuffer();
Bitmap bitmap
= client.testMethod(bytes);
就能夠調用,而且得到結果。
如下內容爲2017年更新的內容,適當參考:
1、CLR編寫的DLL部分
一、按照正常方法引入Opencv;
二、提供接口函數,進行圖像處理(這裏只是實現了cvtColor,實際過程當中能夠用本身編寫的複雜函數)
String
^ Class1
:
:Method(cli
:
:array
<
unsigned
char
>
^ pCBuf1)
{
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,IMREAD_UNCHANGED);
//////////////////////////////////處理過程/////////
cvtColor(img_object,img_object,
40);
/////////////////////////////////////////////////////////////////////////////////
if (
!img_object.data)
return nullptr;
//得到目錄,保存文件
cv
:
:imwrite(
"c:/Method.jpg",img_object);
return
"c:/Method.jpg";
}
String
^ Class1
:
:Method2(cli
:
:array
<
unsigned
char
>
^ pCBuf1)
{
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,IMREAD_UNCHANGED);
//////////////////////////////////處理過程///////////////////////
cvtColor(img_object,img_object,
6);
/////////////////////////////////////////////////////////////////////////////////
if (
!img_object.data)
return nullptr;
//得到目錄,保存文件
cv
:
:imwrite(
"c:/Method2.jpg",img_object);
return
"c:/Method2.jpg";
}
2、Winform調用接口部分(TIP:不只能夠用Winform調用,asp.net/webservice都是能夠調用的)
一、直接引用clr dll
二、編寫helper文件(應該也能夠叫作 warpper),經過外部IO的方法獲取clr dll的文件
class GOCsharpHelper
{
Class1 client
=
new Class1();
string strResult1
= null;
string strResult2
= null;
//輸入參數是string或bitmap
public Bitmap ImageProcess(string ImagePath){
Image ImageTemp
= Bitmap.FromFile(ImagePath);
return ImageProcess(ImageTemp);
}
//輸出結果是bitmap
public Bitmap ImageProcess(Image image)
{
MemoryStream ms
=
new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes
= ms.GetBuffer();
strResult1
= client.Method(bytes);
Image ImageResult
= Bitmap.FromFile(strResult1);
return (Bitmap)ImageResult;
}
public Bitmap ImageProcess2(string ImagePath)
{
Image ImageTemp
= Bitmap.FromFile(ImagePath);
return ImageProcess2(ImageTemp);
}
//輸出結果是bitmap
public Bitmap ImageProcess2(Image image)
{
MemoryStream ms
=
new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] bytes
= ms.GetBuffer();
strResult2
= client.Method2(bytes);
Image ImageResult
= Bitmap.FromFile(strResult2);
return (Bitmap)ImageResult;
}
public
void Clear()
{
if (File.Exists(strResult1))
File.Delete(strResult1);
if (File.Exists(strResult2))
File.Delete(strResult2);
}
}
三、使用例子(注意控件的dispose):
private
void button2_Click(object sender, EventArgs e)
{
if (pictureBox1.Image
!= null)
pictureBox1.Image.Dispose();
if (pictureBox2.Image
!= null)
pictureBox2.Image.Dispose();
Image image1
= gocsharphelper.ImageProcess(
" E:/sandbox/logo.jpg");
pictureBox1.Image
= image1;
Image image2
= gocsharphelper.ImageProcess2(
"E:/sandbox/lena.jpg");
pictureBox2.Image
= image2;
}
3、解釋說明
使用外部I/O不只僅是權宜之計,實際上Opencv的Decode使用的就是外部I/O。就目前研究的水平來講,這是最穩定的。
目前搭建成功的框架已經可以完成「csharp調用opencv的」目標,而且在調試、參數傳遞方面都很強。
若是是處理靜態圖片,已經夠用。
4、殺手程序
GOImageResearch:
使用這種方法編寫的圖像處理預分析程序。
五
、程序調試
「
clr怎麼調試啊,在clr工程中相關的數據全是無效的,怎麼看呢,不能保證寫的圖像算法徹底正確啊……
」
那麼clr確定是能夠調試,出現這個問題的緣由是沒有掌握相關調試技巧。這裏是相關解決方法:
2019年8月30日22:50:18 更新
主要是添加了OpenCVDNN模塊,將代碼升級到2017版本,並解決細節問題,如今應該說處理靜態圖片,那是至關好的了。
d
附件列表