基于編寫圖像處理項目,除了算法以外,比較重要一個問題就是界面設計問題。對于c++語系的程序員來說,一般來說有QT/MFC兩種考慮。QT的確功能強大,特別是QML編寫界面很有一套(//p/.html),在樹莓派上進行設計也很方便(//p/.html);但是使用QT的一個現實問題就是和現有平臺的結合,比如客戶需要將結果導出到excel中,使用QT就比較別扭(當然不是說不可以)。所以現在我一般這樣來做:對于和PI,或者需要在Linux上運行的項目,使用QT編寫界面,調用函數;對于需要在上運行的項目,使用MFC編寫界面,直接就可以引用。
有人會吐槽MFC使用起來非常麻煩mfc基于對話框 狀態欄,這點我非常同意。但MFC經過這么多年的發展,今日仍有活力,并且短時間內不會消失。因為相比較其他一些所見即所得的語言和環境來說(QT/),mfc的消息映射機制和坐標體系等,的確有它的優勢,對于圖像處理程序來說尤其如此;加以積累,能夠快速做出很多專業的東西;近期出現的界面也為mfc加分不少(//p/.html)
選擇了MFC這個方向,思考圖像處理程序問題,一般來說分為“處理圖像”和"處理視頻"兩類:對于圖像處理來說,我提供的框架(//p/.html)能夠提供一個基本的靜態圖像處理框架;而(//p/.html)則適合用來處理視頻。這兩種都分別成功運用于多種視頻處理項目中。
但是這里我想更進一步:希望能夠用編寫界面,因為它更好用;但是又不想引入類似的庫,因為里面很多東西不是我需要的。那么最直接的方法就是使用調用基于編寫的類庫文件(Dll)的,我取名叫做r(GOCW)
經過比較長時間的探索研究,目前的GOCW已經可以直接以函數的形式在內存中傳遞和Mat對象,達到了函數級別的應用。因為這里涉及到托管代碼編寫mfc基于對話框 狀態欄,也就是CLR程序編寫,所以有比較復雜的地方;為了展現GOCW的優良特性,我編寫實現GOGPY項目,也就是一個"編寫界面,實現算法的實時視頻處理程序”,相關細節都包含其中。之所以叫“GPY”,是采集硬件這塊,我采用了成像質量較好的高拍儀設備()。
這里簡單將最核心內容進行講解。GOCW的核心問題,無非就是基于CLR之上的兩個方向的數據流轉換。核心函數為
^ ::(cli::array^ )
{
p1 = &[0];
char* pby1 = p1;
cv::Mat (->,1,CV_8U,pby1);
cv::Mat = cv::(,);//獲得數據到中去
//////////////////////////////////處理過程///////////////////////////////////////
(,,40);
/////////////////////////////////////////////////////////////////////////////////
^ bb = ();
if (!.data)
;
std:: buf;
cv::(".jpg", , buf);
bb;
}
以及
::::^ (const cv::Mat& img)
{
if (img.type() != )
{
throw gcnew n("Only of type are for to ");
}
// the and get the to the data
fmt(::);
^ = gcnew (img.cols, img.rows, fmt);
^data = ->(::::(0, 0, img.cols, img.rows), ::, fmt);
//byte * = (data->Scan0.());
Byte * = (data->Scan0.());
char * = img.data;
for (int row = 0; row < data->; ++row)
{
((&[row*data->]), (&[row*img.step]), img.cols*img.());
}
->(data);
;
}
而在中,直接
b = new (cam.Width, cam., cam., ., m_ip);
// If the image is
b.(.);
= b;
if (.Image != null)
.Image.();
//調用clr+圖像處理模塊
ms = new ();
b.Save(ms, ....Jpeg);
byte[] bytes = ms.();
= .(bytes);
就可以調用,并且獲得結果。
以下內容為2017年更新的內容,適當參考:
一、CLR編寫的DLL部分
1、按照正常方法引入;
2、提供接口函數,進行圖像處理(這里只是實現了,實際過程中可以用自己編寫的復雜函數)
^ ::(cli::array^ )
{
p1 = &[0];
char* pby1 = p1;
cv::Mat (->,1,CV_8U,pby1);
cv::Mat = cv::(,);
//////////////////////////////////處理過程/////////
(,,40);
/////////////////////////////////////////////////////////////////////////////////
if (!.data)
;
//獲得目錄,保存文件
cv::("c:/.jpg",);
"c:/.jpg";
}
^ ::(cli::array^ )
{
p1 = &[0];
char* pby1 = p1;
cv::Mat (->,1,CV_8U,pby1);
cv::Mat = cv::(,);
//////////////////////////////////處理過程///////////////////////
(,,6);
/////////////////////////////////////////////////////////////////////////////////
if (!.data)
;
//獲得目錄,保存文件
cv::("c:/.jpg",);
"c:/.jpg";
}
二、調用接口部分(TIP:不僅可以用調用,/都是可以調用的)
1、直接引用clr dll
2、編寫文件(應該也可以叫做 ),通過外部IO的方法獲取clr dll的文件
class
{
= new ();
= null;
= null;
//輸入參數是或
( ){
Image = .();
();
}
//輸出結果是
(Image image)
{
ms = new ();
image.Save(ms, ....Jpeg);
byte[] bytes = ms.();
= .(bytes);
Image = .();
();
}
( )
{
Image = .();
();
}
//輸出結果是
(Image image)
{
ms = new ();
image.Save(ms, ....Jpeg);
byte[] bytes = ms.();
= .(bytes);
Image = .();
();
}
void Clear()
{
if (File.())
File.();
if (File.())
File.();
}
}
3、使用例子(注意控件的):
void ( , e)
{
if (.Image != null)
.Image.();
if (.Image != null)
.Image.();
Image = .(" E://logo.jpg");
.Image = ;
Image = .("E://lena.jpg");
.Image = ;
}
三、解釋說明
使用外部I/O不僅僅是權宜之計,實際上的使用的就是外部I/O。就目前研究的水平來說,這是最穩定的。
目前搭建成功的框架已經能夠完成“調用的”目標,并且在調試、參數傳遞方面都很強。
如果是處理靜態圖片,已經夠用。
四、殺手程序
:
使用這種方法編寫的圖像處理預分析程序。