C#開發學習人工智能的第一步

C#開發學習人工智能的第一步

前言

作為一個軟件開發者,我們除了要學會複製,黏貼,還要學會調用API和優秀的開源類庫。

也許,有人說C#做不了人工智能,如果你相信了,那隻能說明你的思想還是狹隘的。

做不了人工智能的不是C#這種語言,而是你,我這種普通的程序員。

做人工智能需要一定的學歷背景,一定的數學基礎和公司專項的資源供給;而這種機緣小之又小,你我既然是普通的程序員,就必然與此無緣。

但在人工智能如日中天的當下,接觸深度學習是必然會發生的事情,所以我們要做的就是,學會調用相關的類庫。

現在,讓我們邁出C#學習人工智能的第一步,通過調用Affdex來鎖定圖片中人物的面部,然後將其截取出來。

準備工作

首先,我們需要先訪問官網下載Affdex的Sdk。

在官網找中找到下載Affdex的Sdk的地方也是個挺困難的事。。。所以下載鏈接如下:

下載Affdex_Sdk網址

進入網頁後,向下拉動滾動條,找到到下圖所示位置,點擊Download進行下載。

C#開發學習人工智能的第一步

下載完成後得到Sdk,如下圖:

C#開發學習人工智能的第一步

下面,我們雙擊進行安裝,不過安裝SDK有一些限制,需要預先安裝NET Framework4.0和C++ 2015。如果電腦裡已經安裝了,就不必擔心了;如果安裝的是C++2015-2017這類型的,則需要卸載了,重新安裝C++2015的版本,否則Affdex的SDK將安裝失敗。

安裝完成後,我們去安裝目錄找到Affdex.dll,affdex-native.dll,tensorflow.dll三個文件,如下圖:

C#開發學習人工智能的第一步

我們先將它們複製出來,等待使用。

簡單的介紹一下,這三個類庫中,Affdex.dll是可以被C#項目直接引用的,而另外兩個文件是Affdex.dll的依賴文件;也就是說,affdex-native.dll,tensorflow.dll需要在生成時,輸出到運行目錄下。

有經驗的朋友想必已經發現了,這裡有個類庫名叫tensorflow.dll,tensorflow是什麼啊?稍微百度一下大家就會了解了,它是專門來做深度學習的。

也就是說Affdex是支持深度學習的。

----------------------------------------------------------------------------------------------------

現在我們來學習Affdex的使用。

首先我們新建一個WPF項目,然後引用Affdex.dll。

然後將項目的運行平臺設置為64位,因為,這樣處理圖片的速度能快一點,如下圖:

C#開發學習人工智能的第一步

在Affdex中我們可以發現四個探頭—VideoDetector,PhotoDetector,FrameDetector,CameraDetector。

在這裡我們要處理的是圖片,所以我們選擇PhotoDetector,下面我們創建一個PhotoWindow.Xaml頁面來使用PhotoDetector處理圖片。

代碼實現

首先,我們定義一個PhotoDetector的屬性,用於處理圖片。

然後我們在構造函數中對他進行實例化,代碼如下:

private Affdex.PhotoDetector Detector { get; set; }
public PhotoWindow()
{
InitializeComponent();
uint maxNumFaces = 1;//最多識別圖片中幾張臉
Detector = new Affdex.PhotoDetector(maxNumFaces, Affdex.FaceDetectorMode.SMALL_FACES);
Detector.setImageListener(this);
Detector.setProcessStatusListener(this);
Detector.start();
}

在上述代碼中可以看到,除了初始化PhotoDetector,我們還做了一個圖片監聽設置setImageListener,那麼圖片監聽是幹什麼的呢?

很簡單,圖片被PhotoDetector處理完,我們需要知道圖片處理結果呀,而這個圖片監聽正是是用來返回圖片處理結果的。

可以看到圖片監聽設置的入參是this,也就是說,需要把圖片的處理結果返回給當前頁面。

如果就這樣寫是會編譯報錯的,會提示setImageListener的入參錯誤。

我們查看setImageListener的入參,發現它的入參是一個ImageListener接口,即,setImageListener的入參是一個要實現了ImageListener接口的類。

到這裡,我們就都明白了,現在我們讓當前PhotoWindow.xaml窗體繼承接口ImageListener,並實現接口ImageListener內的方法。

public partial class PhotoWindow : Window, Affdex.ImageListener
===========================================================================
public void onImageCapture(Affdex.Frame frame)
{
}
public void onImageResults(Dictionary faces, Affdex.Frame frame)
{
}

如上述代碼所示,在我們實現的接口onImageResults裡有兩個參數:faces、frame。

其中faces是最重要的,這裡包含Affdex分析圖片的結果。

----------------------------------------------------------------------------------------------------

現在,Affdex的配置代碼已經寫完了,我們可以把圖片讀取出來調用Affdex處理了。

 

public PhotoWindow()
{
InitializeComponent();
uint maxNumFaces = 1;//最多識別圖片中幾張臉
Detector = new Affdex.PhotoDetector(maxNumFaces, Affdex.FaceDetectorMode.SMALL_FACES);
Detector.setImageListener(this);
Detector.start();

byte[] bytes = FileHelper.FileToBytes(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "timg.jpg"));
BitmapSource bitmapSource = ImageHelper.BytesToBitmapImage(bytes);
var w = bitmapSource.Width;
var h = bitmapSource.Height;
var stride = bitmapSource.Format.BitsPerPixel * (int)w / 8; //計算Stride
byte[] byteList = new byte[(int)h * stride];
bitmapSource.CopyPixels(byteList, stride, 0);
Affdex.Frame frame = new Affdex.Frame((int)w, (int)h, byteList, Affdex.Frame.COLOR_FORMAT.BGRA);
Detector.process(frame);
}

如上述代碼所示,我們在啟動了Detector後,讀取了一個人物圖片,然後把人物圖片的像素數組解析出來,生成一個Frame;這個Frame是Affdex的類,用於保存圖像數據信息。

最後,我們把生成的Frame對象,扔給Detecotor的Process方法處理。

Detecotor處理完成後,會觸發onImageResults方法。

在onImageResults方法裡,入參faces包含了處理結果。

現在我們使用faces裡的內容,來定位圖片中人物面部的位置。

public void onImageResults(Dictionary faces, Affdex.Frame frame)
{
Face face = null;
if (faces != null && faces.Values != null && faces.Values.Count() > 0)
{

face = faces.Values.First();//因為我們的Detector只識別了一個臉,所以這裡最多隻有一個數據
}
int top = (int)face.FeaturePoints.Min(r => r.X);
int left = (int)face.FeaturePoints.Min(r => r.Y);
int bottom = (int)face.FeaturePoints.Max(r => r.X);
int right = (int)face.FeaturePoints.Max(r => r.Y);
ImageHelper.cutPicture(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "timg.jpg"),
left, top, right , bottom - top);
}

如上述代碼所示,我們在onImageResults裡做了【最簡單】人物面部座標定位,並進行了剪切。

處理結果如下圖所示:

C#開發學習人工智能的第一步

結語

事實上,上面介紹的只是Affdex最基礎調用,而且,這裡並沒有使用到深度學習的內容,只是簡單的掃描和分析。

想要使用深度學習的內容還需要進一步學習該開源控件,不過,萬事開頭難,我們現在已經邁出了第一步。


分享到:


相關文章: