前言
作為一個(gè)軟件開(kāi)發(fā)者,我們除了要學(xué)會(huì)復(fù)制,黏貼,還要學(xué)會(huì)調(diào)用API和優(yōu)秀的開(kāi)源類(lèi)庫(kù)。
也許,有人說(shuō)C#做不了人工智能,如果你相信了,那只能說(shuō)明你的思想還是狹隘的。
做不了人工智能的不是C#這種語(yǔ)言,而是你,我這種普通的程序員。
做人工智能需要一定的學(xué)歷背景,一定的數(shù)學(xué)基礎(chǔ)和公司專(zhuān)項(xiàng)的資源供給;而這種機(jī)緣小之又小,你我既然是普通的程序員,就必然與此無(wú)緣。
但在人工智能如日中天的當(dāng)下,接觸深度學(xué)習(xí)是必然會(huì)發(fā)生的事情,所以我們要做的就是,學(xué)會(huì)調(diào)用相關(guān)的類(lèi)庫(kù)。
現(xiàn)在,讓我們邁出C#學(xué)習(xí)人工智能的第一步,通過(guò)調(diào)用Affdex來(lái)鎖定圖片中人物的面部,然后將其截取出來(lái)。
準(zhǔn)備工作
首先,我們需要先訪問(wèn)官網(wǎng)下載Affdex的Sdk。
在官網(wǎng)找中找到下載Affdex的Sdk的地方也是個(gè)挺困難的事。。。所以下載鏈接如下:
下載Affdex_Sdk網(wǎng)址
<https://knowledge.affectiva.com/docs/getting-started-with-the-emotion-sdk-for-windows#section-2-import-into-your-application>
進(jìn)入網(wǎng)頁(yè)后,向下拉動(dòng)滾動(dòng)條,找到到下圖所示位置,點(diǎn)擊Download進(jìn)行下載。
下載完成后得到Sdk,如下圖:
下面,我們雙擊進(jìn)行安裝,不過(guò)安裝SDK有一些限制,需要預(yù)先安裝NET Framework4.0和C++
2015。如果電腦里已經(jīng)安裝了,就不必?fù)?dān)心了;如果安裝的是C++2015-2017這類(lèi)型的,則需要卸載了,重新安裝C++2015的版本,否則Affdex的SDK將安裝失敗。
安裝完成后,我們?nèi)グ惭b目錄找到Affdex.dll,affdex-native.dll,tensorflow.dll三個(gè)文件,如下圖:
我們先將它們復(fù)制出來(lái),等待使用。
簡(jiǎn)單的介紹一下,這三個(gè)類(lèi)庫(kù)中,Affdex.dll是可以被C#項(xiàng)目直接引用的,而另外兩個(gè)文件是Affdex.dll的依賴(lài)文件;也就是說(shuō),affdex-native.dll,tensorflow.dll需要在生成時(shí),輸出到運(yùn)行目錄下。
有經(jīng)驗(yàn)的朋友想必已經(jīng)發(fā)現(xiàn)了,這里有個(gè)類(lèi)庫(kù)名叫tensorflow.dll,tensorflow是什么?。可晕俣纫幌麓蠹揖蜁?huì)了解了,它是專(zhuān)門(mén)來(lái)做深度學(xué)習(xí)的。
也就是說(shuō)Affdex是支持深度學(xué)習(xí)的。
----------------------------------------------------------------------------------------------------
現(xiàn)在我們來(lái)學(xué)習(xí)Affdex的使用。
首先我們新建一個(gè)WPF項(xiàng)目,然后引用Affdex.dll。
然后將項(xiàng)目的運(yùn)行平臺(tái)設(shè)置為64位,因?yàn)?,這樣處理圖片的速度能快一點(diǎn),如下圖:
在Affdex中我們可以發(fā)現(xiàn)四個(gè)探頭—VideoDetector,PhotoDetector,F(xiàn)rameDetector,CameraDetector。
在這里我們要處理的是圖片,所以我們選擇PhotoDetector,下面我們創(chuàng)建一個(gè)PhotoWindow.Xaml頁(yè)面來(lái)使用PhotoDetector處理圖片。
代碼實(shí)現(xiàn)
首先,我們定義一個(gè)PhotoDetector的屬性,用于處理圖片。
然后我們?cè)跇?gòu)造函數(shù)中對(duì)他進(jìn)行實(shí)例化,代碼如下:
private Affdex.PhotoDetector Detector { get; set; } public PhotoWindow() {
InitializeComponent(); uint maxNumFaces = 1;//最多識(shí)別圖片中幾張臉 Detector = new
Affdex.PhotoDetector(maxNumFaces, Affdex.FaceDetectorMode.SMALL_FACES);
Detector.setImageListener(this); Detector.setProcessStatusListener(this);
Detector.start(); }
在上述代碼中可以看到,除了初始化PhotoDetector,我們還做了一個(gè)圖片監(jiān)聽(tīng)設(shè)置setImageListener,那么圖片監(jiān)聽(tīng)是干什么的呢?
很簡(jiǎn)單,圖片被PhotoDetector處理完,我們需要知道圖片處理結(jié)果呀,而這個(gè)圖片監(jiān)聽(tīng)正是是用來(lái)返回圖片處理結(jié)果的。
可以看到圖片監(jiān)聽(tīng)設(shè)置的入?yún)⑹莟his,也就是說(shuō),需要把圖片的處理結(jié)果返回給當(dāng)前頁(yè)面。
如果就這樣寫(xiě)是會(huì)編譯報(bào)錯(cuò)的,會(huì)提示setImageListener的入?yún)㈠e(cuò)誤。
我們查看setImageListener的入?yún)?,發(fā)現(xiàn)它的入?yún)⑹且粋€(gè)ImageListener接口,即,setImageListener的入?yún)⑹且粋€(gè)要實(shí)現(xiàn)了ImageListener接口的類(lèi)。
到這里,我們就都明白了,現(xiàn)在我們讓當(dāng)前PhotoWindow.xaml窗體繼承接口ImageListener,并實(shí)現(xiàn)接口ImageListener內(nèi)的方法。
public partial class PhotoWindow : Window, Affdex.ImageListener
===========================================================================
public void onImageCapture(Affdex.Frame frame) { } public void
onImageResults(Dictionary<int, Face> faces, Affdex.Frame frame) { }
如上述代碼所示,在我們實(shí)現(xiàn)的接口onImageResults里有兩個(gè)參數(shù):faces、frame。
其中faces是最重要的,這里包含Affdex分析圖片的結(jié)果。
----------------------------------------------------------------------------------------------------
現(xiàn)在,Affdex的配置代碼已經(jīng)寫(xiě)完了,我們可以把圖片讀取出來(lái)調(diào)用Affdex處理了。
public PhotoWindow() { InitializeComponent(); uint maxNumFaces =
1;//最多識(shí)別圖片中幾張臉 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; //計(jì)算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); }
如上述代碼所示,我們?cè)趩?dòng)了Detector后,讀取了一個(gè)人物圖片,然后把人物圖片的像素?cái)?shù)組解析出來(lái),生成一個(gè)Frame;這個(gè)Frame是Affdex的類(lèi),用于保存圖像數(shù)據(jù)信息。
最后,我們把生成的Frame對(duì)象,扔給Detecotor的Process方法處理。
Detecotor處理完成后,會(huì)觸發(fā)onImageResults方法。
在onImageResults方法里,入?yún)aces包含了處理結(jié)果。
現(xiàn)在我們使用faces里的內(nèi)容,來(lái)定位圖片中人物面部的位置。
public void onImageResults(Dictionary<int, Face> faces, Affdex.Frame frame) {
Face face = null; if (faces != null && faces.Values != null &&
faces.Values.Count() > 0) { face =
faces.Values.First();//因?yàn)槲覀兊腄etector只識(shí)別了一個(gè)臉,所以這里最多只有一個(gè)數(shù)據(jù) } 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); }
如上述代碼所示,我們?cè)趏nImageResults里做了【最簡(jiǎn)單】人物面部坐標(biāo)定位,并進(jìn)行了剪切。?
處理結(jié)果如下圖所示:
結(jié)語(yǔ)
事實(shí)上,上面介紹的只是Affdex最基礎(chǔ)調(diào)用,而且,這里并沒(méi)有使用到深度學(xué)習(xí)的內(nèi)容,只是簡(jiǎn)單的掃描和分析。
想要使用深度學(xué)習(xí)的內(nèi)容還需要進(jìn)一步學(xué)習(xí)該開(kāi)源控件,不過(guò),萬(wàn)事開(kāi)頭難,我們現(xiàn)在已經(jīng)邁出了第一步。
----------------------------------------------------------------------------------------------------
到此C#開(kāi)發(fā)學(xué)習(xí)人工智能的第一步就完成了。
代碼已經(jīng)傳到Github上了,歡迎大家下載。
Github地址:https://github.com/kiba518/WpfAffdex
<https://github.com/kiba518/WpfAffdex>
----------------------------------------------------------------------------------------------------
注:此文章為原創(chuàng),任何形式的轉(zhuǎn)載都請(qǐng)聯(lián)系作者獲得授權(quán)并注明出處!
若您覺(jué)得這篇文章還不錯(cuò),請(qǐng)點(diǎn)擊下方的【推薦】,非常感謝!
https://www.cnblogs.com/kiba/p/11416919.html
<https://www.cnblogs.com/kiba/p/11416919.html>
?
熱門(mén)工具 換一換
