Go 的人臉識別教程 - 第一部分
整個人臉識別領域是我喜歡閱讀的內容。自己實現一個人臉識別系統會讓你聽起來像 Tony Stark 並且你可以將它們用於各種不同的專案,例如自動鎖門,或者為你的辦公室建立一個監控系統,僅舉幾例。
在此教程中,我們將使用 Go 中一些內建的庫去構建自己的,非常簡單的人臉識別系統。我們首先在靜態影象上進行簡單的人臉識別,並且看看它是如何工作的,然後我們將在這個小教程的第二部分拓展到成視訊輸入的實時人臉識別。
視訊教程
此教程以視訊格式,如果您希望支援我和我的頻道,請點贊並訂閱我的頻道!
Kagami/go-face 包
在這個基礎教程中,我們將使用封裝了 dlib 機器學習工具包的 kagami/go-face 包 。
注意: Kagami 實際上寫了他如何寫這個包。這一定是一個有趣的文章並且你可以在這裡找到它:https://hackernoon.com/face-recognition-with-go-676a555b8a7e
dlib 工具包
它是用 C++ 構建的,它在面部識別與檢測方面都令人驚奇。根據它的文件,在 Wild 基準測試中檢測標記面部的準確度約為 99.4%,這難以置信,也是為什麼許多第三方庫將其作為基礎的原因
注意:我在前面的教程中介紹了 Dlib 工具包的 Python 庫 - face_recognition. 如果你想檢視此教程的 Python 實現,在這裡: 介紹 Python 的人臉識別
安裝
我不想撒謊,讓它啟動並執行起來比用標準的 Go 包更痛苦一些,你需要在計算機上安裝 pkg-config
和 dlib
。如果你在 MacOS 上執行,命令如下:
$ brew install pkg-config dlib $ sed -i '' 's/^Libs: .*/& -lblas -llapack/' /usr/local/lib/pkgconfig/dlib-1.pc
開始
我們首先需要下載 kagami/go-face 包
,可以使用如下 go get
命令:
$ go get -u github.com/Kagami/go-face
在你的 GOPATH 目錄中建立一個名為 go-face-recognition
的新目錄。在此目錄中建立一個名為 main.go
的檔案,這是我們所有原始碼所在位置。
完成操作後,你需要從 TutorialEdge/ go-face-recognition-tutorial repo 的 image/
目錄中獲取檔案。最簡單的方法是 clone repo 到另一個目錄,只需複製圖片目錄到當前的工作目錄
$ git clone https://github.com/TutorialEdge/go-face-recognition-tutorial.git
一旦成功 clone 後,我們就有了啟動人臉識別的所需的 .dat
檔案。你應該還看到一些其他包含復仇者聯盟面孔的 .jpg
檔案列表。
package main import ( "fmt" "github.com/Kagami/go-face" ) const dataDir = "testdata" func main() { fmt.Println("Facial Recognition System v0.01") rec, err := face.NewRecognizer(dataDir) if err != nil { fmt.Println("Cannot INItialize recognizer") } defer rec.Close() fmt.Println("Recognizer Initialized") }
好的,如果我們嘗試在這時候執行程式,應該會在我們程式的輸出中看到 Facial Recognition System v0.01
和 Recognizer Initialized
. 我們已經成功的設定了所需的一切,為了做一些很酷的高階人臉識別!
計算圖片中的面孔
我們對這個 package 的第一個真正測試是我們是否能準確地計算照片中的面孔數量。出於本教程的目的,我們將使用此照片:
如你所見,沒什麼特別的,只有 Tony Stark 那張孤獨的臉。
因此,我們現在需要拓展已有的程式,以便能分析此影象,然後計算所述影象中的面孔數量:
package main import ( "fmt" "log" "path/filepath" "github.com/Kagami/go-face" ) const dataDir = "testdata" func main() { fmt.Println("Facial Recognition System v0.01") rec, err := face.NewRecognizer(dataDir) if err != nil { fmt.Println("Cannot INItialize recognizer") } defer rec.Close() fmt.Println("Recognizer Initialized") // we create the path to our image with filepath.Join avengersImage := filepath.Join(dataDir, "tony-stark.jpg") // we then call RecognizeFile passing in the path // to our file to retrieve the number of faces and any // potential errors faces, err := rec.RecognizeFile(avengersImage) if err != nil { log.Fatalf("Can't recognize: %v", err) } // we print out the number of faces in our image fmt.Println("Number of Faces in Image: ", len(faces)) }
當我們執行它時,應該會看到以下輸出:
$ go run main.go Facial Recognition System v0.01 Recognizer Initialized Number of Faces in Image:1
太棒了!我們已經能夠分析並確認一張影象中包含了一張人臉。讓我們嘗試一個包含更多復仇者的影象:
當我們更新第 24 行時:
avengersImage := filepath.Join(dataDir, "avengers-01.jpg")
重新執行我們的程式,應該會看到我們的程式能夠確認 2 個人在這個此影象中。
人臉識別
很好,我們可以計算一張圖片中有多少張面孔,現在來實際地確認這些人是誰?
為此,我們需要一些參考照片,例如,如果我們想要從照片中識別 Tony Stark,我們需要帶他名字的樣例照片。識別軟體能分析與他相識的人臉照片,然後將其匹配。
因此,讓我們用 avengers-02.jpg
作為 Tony Stark 的參考照片,然後看看是否能識別這張影象包含他的臉
avengersImage := filepath.Join(dataDir, "avengers-02.jpeg") faces, err := rec.RecognizeFile(avengersImage) if err != nil { log.Fatalf("Can't recognize: %v", err) } fmt.Println("Number of Faces in Image: ", len(faces)) var samples []face.Descriptor var avengers []int32 for i, f := range faces { samples = append(samples, f.Descriptor) // Each face is unique on that image so Goes to its own category. avengers = append(avengers, int32(i)) } // Name the categories, i.e. people on the image. labels := []string{ "Dr Strange", "Tony Stark", "Bruce Banner", "Wong", } // Pass samples to the recognizer. rec.SetSamples(samples, avengers)
因此,在上面的程式碼中,我們已經從左到右檢查了面孔並標記了合適的名字。我們的識別系統能使用這些參考樣例來嘗試對對後續檔案進行自己的人臉識別。
讓我們嘗試用已有的 Tony Stark 圖片測試我們的識別系統,然後看看是否能根據 avengers-02.jpeg 檔案生成的人臉描述符來識別它:
// Now let's try to classify some not yet known image. testTonyStark := filepath.Join(dataDir, "tony-stark.jpg") tonyStark, err := rec.RecognizeSingleFile(testTonyStark) if err != nil { log.Fatalf("Can't recognize: %v", err) } if tonyStark == nil { log.Fatalf("Not a single face on the image") } avengerID := rec.Classify(tonyStark.Descriptor) if avengerID < 0 { log.Fatalf("Can't classify") } fmt.Println(avengerID) fmt.Println(labels[avengerID])
現在嘗試驗證這不是僥倖,並試著看看我們的影象識別系統是否適用於 Dr Strange 。
testDrStrange := filepath.Join(dataDir, "dr-strange.jpg") drStrange, err := rec.RecognizeSingleFile(testDrStrange) if err != nil { log.Fatalf("Can't recognize: %v", err) } if drStrange == nil { log.Fatalf("Not a single face on the image") } avengerID = rec.Classify(drStrange.Descriptor) if avengerID < 0 { log.Fatalf("Can't classify") }
最後,讓我們試著用 Wong 的圖片:
testWong := filepath.Join(dataDir, "wong.jpg") wong, err := rec.RecognizeSingleFile(testWong) if err != nil { log.Fatalf("Can't recognize: %v", err) } if wong == nil { log.Fatalf("Not a single face on the image") } avengerID = rec.Classify(wong.Descriptor) if avengerID < 0 { log.Fatalf("Can't classify") } fmt.Println(avengerID) fmt.Println(labels[avengerID])
當你一起執行時,你應該會看到以下輸出:
$ go run main.go Facial Recognition System v0.01 Recognizer Initialized Number of Faces in Image:4 1 Tony Stark 0 Dr Strange 3 Wong
太棒了,我們已經構建了一個真正簡單的人臉識別系統,讓我們能識別不同的復仇者。
挑戰:在所有復仇者上建立一些參考檔案,並嘗試將人臉識別程式碼提取到一個可重用的函式中
完整原始碼
可在 Github: Tutorialedge/go-face-recognition-tutorial 中找到本教程完整的原始碼
結論
在此教程中,我們成功地構建了一個十分簡單的人臉識別系統,能在靜態影象上執行。這個系列教程有望成為下一部分的基礎,我們將在研究如何如何在視訊流的實時上下文中進行識別。
希望你喜歡本教程,如果您這樣完成了,請在下面的評論部分告訴我們!
注意:如果你想實時追蹤新的 Go 文章釋出到網站的時間,那麼請在 Twitter 隨時關注我所有的最新訊息: @Elliot_F .