<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                來源: https://codeantenna.com/a/jRxHFeO0F9 # 手把手 Golang 實現靜態圖像與視頻流人臉識別 [實時音視頻互動應用開發教程](https://codeantenna.com/tag/%E5%AE%9E%E6%97%B6%E9%9F%B3%E8%A7%86%E9%A2%91%E4%BA%92%E5%8A%A8%E5%BA%94%E7%94%A8%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B "【實時音視頻互動應用開發教程】標簽搜索")[技術干貨](https://codeantenna.com/tag/%E6%8A%80%E6%9C%AF%E5%B9%B2%E8%B4%A7 "【技術干貨】標簽搜索")[音視頻](https://codeantenna.com/tag/%E9%9F%B3%E8%A7%86%E9%A2%91 "【音視頻】標簽搜索")[人臉識別](https://codeantenna.com/tag/%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB "【人臉識別】標簽搜索") * * * 說起人臉識別,大家首先想到的實現方式應該是 Python 去做相關的處理,因為相關的機器學習框架,庫都已經封裝得比較好了。但是我們今天討論的實現方式換成 Golang,利用 Golang 去做靜態圖像和視頻流人臉識別的相應處理。 # 靜態圖像人臉識別 首先我們來進行靜態的人臉識別,Golang 這邊相較于 Python 社區來說相對少一些,不過依然有一些優秀的庫可以供我們使用。今天我們用到的就是[go-face](https://github.com/Kagami/go-face)這個庫。該庫利用[dlib](http://dlib.net/)去實現人臉識別,一個很受歡迎的機器學習工具集,它可以說是人臉識別中使用最多的軟件包之一。在產學界有廣泛應用,涵蓋了機器人學,嵌入式設備,移動設備等等。在它官網的文檔中提到在 Wild 基準測試中識別標記面部的準確度達到驚人的 99.4%,這也說明為什么它能得到廣泛的應用。 在我們開始碼代碼之前,首先需要安裝 dlib。Windows 平臺相對麻煩一些,具體在官網有安裝方案,這里我介紹兩個平臺。 ### Ubuntu 18.10+, Debian sid 最新版本的 Ubuntu 和 Debian 都提供合適的 dlib 包,所以只需要運行。 ~~~ # Ubuntu sudo apt-get install libdlib-dev libblas-dev liblapack-dev libjpeg-turbo8-dev # Debian sudo apt-get install libdlib-dev libblas-dev liblapack-dev libjpeg62-turbo-dev ~~~ ### macOS 確保安裝了[Homebrew](https://brew.sh/)。 ~~~ brew install dlib ~~~ ## 創建項目及準備工作 在 GOPATH 的 src 目錄下,創建項目文件,命令如下。 ~~~ sudo makedir go-face-test # 創建 main.go sudo touch main.go ~~~ 然后進入該目錄下,生成 mod 文件。 ~~~ sudo go mod init ~~~ 調用該命令后,在 go-face-test 目錄下應該已經生成了**go.mod**文件。 該庫需要三個模型**shape\_predictor\_5\_face\_landmarks.dat**,**mmod\_human\_face\_detector.dat**和**dlib\_face\_recognition\_resnet\_model\_v1.dat**,在 go-face-test 目錄下下載相應的測試數據。 ~~~ git clone https://github.com/Kagami/go-face-testdata testdata ~~~ 最終的項目結構應該如圖。 ![img](https://codeantenna.com/image/https://img-blog.csdnimg.cn/img_convert/d6cb565d63c8dedc183f3aec0ff65ca8.png) ## 代碼實現 首先,我們利用代碼檢查環境是否正常。初始化識別器,釋放資源。 ~~~ package main import ( "fmt" "github.com/Kagami/go-face" ) const dataDir = "testdata" // testdata 目錄下兩個對應的文件夾目錄 const ( modelDir = dataDir + "/models" imagesDir = dataDir + "/images" ) func main() { fmt.Println("Face Recognition...") // 初始化識別器 rec, err := face.NewRecognizer(modelDir) if err != nil { fmt.Println("Cannot INItialize recognizer") } defer rec.Close() fmt.Println("Recognizer Initialized") } ~~~ 編譯然后運行代碼。 ~~~ sudo go run main.go ~~~ 應該得到下面輸出。 ~~~ Face Recognition... Recognizer Initialized ~~~ 到這一步,我們已經成功的設置好了需要的一切。 ## 檢測圖片中人臉數量 首先準備一張林俊杰的照片,放到任意目錄下,為了演示方便,我放在了**main.go**同級目錄下。 ![img](https://codeantenna.com/image/https://img-blog.csdnimg.cn/img_convert/a8d39c1387669f2c39f370fb36465c21.png) 如你所見,現在什么都沒有,只有一張圖片,接下來我們要讓計算機計算圖片中的人臉數量。 ~~~ package main import ( "fmt" "log" "github.com/Kagami/go-face" ) const dataDir = "testdata" // testdata 目錄下兩個對應的文件夾目錄 const ( modelDir = dataDir + "/models" imagesDir = dataDir + "/images" ) func main() { fmt.Println("Face Recognition...") // 初始化識別器 rec, err := face.NewRecognizer(modelDir) if err != nil { fmt.Println("Cannot INItialize recognizer") } defer rec.Close() fmt.Println("Recognizer Initialized") // 調用該方法,傳入路徑。返回面部數量和任何錯誤 faces, err := rec.RecognizeFile("linjunjie.jpeg") if err != nil { log.Fatalf("無法識別: %v", err) } // 打印人臉數量 fmt.Println("圖片人臉數量: ", len(faces)) } ~~~ 核心代碼其實就是一行,go-face 封裝進行識別的方法,傳入相應路徑的圖片文件,執行代碼后結果如下。 ~~~ Face Recognition... Recognizer Initialized 圖片人臉數量: 1 ~~~ 現在笨笨的計算機已經會數人臉數量了。那…如果一張照片里面有多人準不準呢,我們試試看,準備一張多人合照圖片。 ![img](https://codeantenna.com/image/https://img-blog.csdnimg.cn/img_convert/41a01981bc1a3e4bde40c67d7d733e4e.png) heyin.jpeg 我們將第 31 行代碼換成如下即可。 ~~~ faces, err := rec.RecognizeFile("heyin.jpeg") ~~~ 運行后的結果應該打印 (**圖片人臉數量: 6**),接下來正式看展我們的人臉識別。 ## 人臉識別 首先我們準備一張合照,這里依然沿用上面的**heyin.jpeg**。 整個處理過程大致分為以下幾步。 1.將合影中人物映射到唯一 ID, 然后將唯一 ID 和對應人物相關聯。 ~~~ var samples []face.Descriptor var peoples []int32 for i, f := range faces { samples = append(samples, f.Descriptor) // 每張臉唯一 id peoples = append(peoples, int32(i)) } // Pass samples to the recognizer. rec.SetSamples(samples, peoples) ~~~ 2.接下來我們封裝一個人臉識別的方法,傳入識別器和照片路徑,打印對應人物 ID,人物名字。 ~~~ func RecognizePeople(rec *face.Recognizer, file string) { people, err := rec.RecognizeSingleFile(file) if err != nil { log.Fatalf("無法識別: %v", err) } if people == nil { log.Fatalf("圖片上不是一張臉") } peopleID := rec.Classify(people.Descriptor) if peopleID < 0 { log.Fatalf("無法區分") } fmt.Println(peopleID) fmt.Println(labels[peopleID]) } ~~~ 3.最后我們傳入想要識別的圖片,目前傳入了 3 張圖片,感興趣的小伙伴可以傳入其他圖片嘗試。 ![img](https://codeantenna.com/image/https://img-blog.csdnimg.cn/img_convert/1594691a7c1390c1bc7ba601f0819ee6.png) jay.jpeg ![img](https://codeantenna.com/image/https://img-blog.csdnimg.cn/img_convert/a8d39c1387669f2c39f370fb36465c21.png) linjunjie.jpeg ![img](https://codeantenna.com/image/https://img-blog.csdnimg.cn/img_convert/912ba5a73c9e61cab142af45cc2db0b4.png) taozhe.jpeg 4.調用三次。 ~~~ RecognizePeople(rec, "jay.jpeg") RecognizePeople(rec, "linjunjie.jpeg") RecognizePeople(rec, "taozhe.jpeg") ~~~ 代碼如下 ~~~ package main import ( "fmt" "log" "github.com/Kagami/go-face" ) const dataDir = "testdata" // testdata 目錄下兩個對應的文件夾目錄 const ( modelDir = dataDir + "/models" imagesDir = dataDir + "/images" ) // 圖片中的人名 var labels = []string{ "蕭敬騰", "周杰倫", "unknow", "王力宏", "陶喆", "林俊杰", } func main() { fmt.Println("Face Recognition...") // 初始化識別器 rec, err := face.NewRecognizer(modelDir) if err != nil { fmt.Println("Cannot INItialize recognizer") } defer rec.Close() fmt.Println("Recognizer Initialized") // 調用該方法,傳入路徑。返回面部數量和任何錯誤 faces, err := rec.RecognizeFile("heyin.jpeg") if err != nil { log.Fatalf("無法識別: %v", err) } // 打印人臉數量 fmt.Println("圖片人臉數量: ", len(faces)) var samples []face.Descriptor var peoples []int32 for i, f := range faces { samples = append(samples, f.Descriptor) // 每張臉唯一 id peoples = append(peoples, int32(i)) } // 傳入樣例到識別器 rec.SetSamples(samples, peoples) RecognizePeople(rec, "jay.jpeg") RecognizePeople(rec, "linjunjie.jpeg") RecognizePeople(rec, "taozhe.jpeg") } func RecognizePeople(rec *face.Recognizer, file string) { people, err := rec.RecognizeSingleFile(file) if err != nil { log.Fatalf("無法識別: %v", err) } if people == nil { log.Fatalf("圖片上不是一張臉") } peopleID := rec.Classify(people.Descriptor) if peopleID < 0 { log.Fatalf("無法區分") } fmt.Println(peopleID) fmt.Println(labels[peopleID]) } ~~~ ## 運行結果 最后我們運行代碼。 ~~~ go build main.go ./main ~~~ 結果如下 ~~~ 圖片人臉數量: 6 1 周杰倫 5 林俊杰 4 陶喆 ~~~ 恭喜你,你已經成功的識別出這三張圖片是誰了,到這一步,靜態的圖像人臉識別已經完成了。 ## 靜態人臉識別總結 到這一步我們已經可以成功的利用 Go 實現了靜態人臉識別。將其運用到項目中也不是不可,不過它有諸多局限,使用的場景較為單一,只能用在例如用戶上傳人臉身份識別,單一人臉識別等場景;圖片格式較為單一,暫時不支持 PNG 格式等缺點。 # 視頻流人臉識別 ## 背景 靜態的人臉識別應用場景較為局限,不能夠放到比較重要的環境中,例如金融,保險,安防等領域,存在偽造等可能。而且單純的靜態人臉識別,意義不大。動態的視頻流擁有更加廣闊的應用空間,充分應用在智能安防,手勢識別,美顏等領域。5G 時代,眾多業務將圍繞視頻這一塊展開,如何將視頻業務與核心業務實現解耦,聲網的**RTE**組件做得不錯,作為 RTE-PaaS 的開創者,聲網已經有較多的技術積累,通過 RTE 組件的形式有很多好處。 **RTE 優點** 1.應用無關性 可以在不同的項目間共享,實現復用,避免多次開發的重復性工作 2.平臺無關性 廣泛應用于操作系統,編程語言及各領域 3.豐富的三方模塊 能夠提供例如白板教學,視頻美顏,鑒黃等眾多模塊供開發者使用 ## 代碼實現 這里我們來實現一下視頻流的相關人臉識別,之前的靜態識別就是為了動態視頻流人臉識別做鋪墊。我們來說一下視頻流的人臉識別的實現思路,靜態的圖像人臉識別已經完成,而視頻是多幀的連續,我們只需要抽取片段捕獲關鍵幀,識別出人像,人后輸出對應關聯的人名。 ### 準備工作 這里我們用到的是[gocv](https://gocv.io/getting-started/macos/)(底層使用 OpenCV),這里我們暫時略過具體的安裝流程,按照官方文檔安裝即可。 1.設置視頻捕捉的設備,一般來說默認 0 ~~~ // set to use a video capture device 0 deviceID := 0 // open webcam webcam, err := gocv.OpenVideoCapture(deviceID) if err != nil { fmt.Println(err) return } defer webcam.Close() ~~~ 2.打開展示窗口 ~~~ // open display window window := gocv.NewWindow("Face Detect") defer window.Close() ~~~ 3.準備圖像矩陣,檢測到人臉時顯示矩形框的配置 ~~~ // prepare image matrix img := gocv.NewMat() defer img.Close() // color for the rect when faces detected blue := color.RGBA{0, 0, 255, 0} ~~~ 4.加載人臉識別分類器,用一個死循環,里面加上我們的相關識別服務 ~~~ for { if ok := webcam.Read(&img); !ok { fmt.Printf("cannot read device %v\n", deviceID) return } if img.Empty() { continue } // detect faces rects := classifier.DetectMultiScale(img) fmt.Printf("found %d faces\n", len(rects)) // draw a rectangle around each face on the original image for _, r := range rects { gocv.Rectangle(&img, r, blue, 3) imgFace := img.Region(r) buff, err:=gocv.IMEncode(".jpg",imgFace) if err != nil { fmt.Println("encoding to jpg err:%v", err) break } RecognizePeopleFromMemory(rec, buff) } // show the image in the window, and wait 1 millisecond window.IMShow(img) window.WaitKey(1) } ~~~ 其中有幾個步驟需要將一下,目前來說**gocv.IMEncode**只支持將捕獲到的圖片轉成**PNG**,**JPG**,**GIF**三種格式。轉換后的字節流放在內存中,然后將字節流傳入我們的人臉識別函數中即可。 ~~~ // RecognizeSingle returns face if it's the only face on the image or // nil otherwise. Only JPEG format is currently supported. Thread-safe. func (rec *Recognizer) RecognizeSingle(imgData []byte) (face *Face, err error) { faces, err := rec.recognize(0, imgData, 1) if err != nil || len(faces) != 1 { return } face = &faces[0] return } ~~~ **注意事項** > 由于 go-face 只支持 JPEG 的格式,所以我們捕捉的幀只能轉換成 JPG 格式 然后簡單的封裝一個字符流的識別函數。這里需要說明一下,之所以將 log.Fatal 換成了 log.Println 的原因是在視頻流級別的識別中可能會出現沒有人臉的情況,這個時候程序應當是正常運行的,不能退出。 ~~~ func RecognizePeopleFromMemory(rec *face.Recognizer, img []byte) { people, err := rec.RecognizeSingle(img) if err != nil { log.Println("無法識別: %v", err) return } if people == nil { log.Println("圖片上不是一張臉") return } peopleID := rec.Classify(people.Descriptor) if peopleID < 0 { log.Println("無法區分") return } fmt.Println(peopleID) fmt.Println(labels[peopleID]) } ~~~ 最后完整代碼如下 ~~~ package main import ( "fmt" "image/color" "log" "github.com/Kagami/go-face" "gocv.io/x/gocv" ) const dataDir = "testdata" // testdata 目錄下兩個對應的文件夾目錄 const ( modelDir = dataDir + "/models" imagesDir = dataDir + "/images" ) // 圖片中的人名 var labels = []string{ "蕭敬騰", "周杰倫", "unknow", "王力宏", "陶喆", "林俊杰", } func main() { // 初始化識別器 rec, err := face.NewRecognizer(modelDir) if err != nil { fmt.Println("Cannot INItialize recognizer") } defer rec.Close() fmt.Println("Recognizer Initialized") // 調用該方法,傳入路徑。返回面部數量和任何錯誤 faces, err := rec.RecognizeFile("heyin.jpeg") if err != nil { log.Fatalf("無法識別: %v", err) } // 打印人臉數量 fmt.Println("圖片人臉數量: ", len(faces)) var samples []face.Descriptor var peoples []int32 for i, f := range faces { samples = append(samples, f.Descriptor) // 每張臉唯一 id peoples = append(peoples, int32(i)) } // Pass samples to the recognizer. rec.SetSamples(samples, peoples) RecognizePeople(rec, "jay.jpeg") RecognizePeople(rec, "linjunjie.jpeg") RecognizePeople(rec, "taozhe.jpeg") // set to use a video capture device 0 deviceID := 0 // open webcam webcam, err := gocv.OpenVideoCapture(deviceID) if err != nil { fmt.Println(err) return } defer webcam.Close() // open display window window := gocv.NewWindow("Face Detect") defer window.Close() // prepare image matrix img := gocv.NewMat() defer img.Close() // color for the rect when faces detected blue := color.RGBA{0, 0, 255, 0} // load classifier to recognize faces classifier := gocv.NewCascadeClassifier() defer classifier.Close() if !classifier.Load("./haarcascade_frontalface_default.xml") { fmt.Println("Error reading cascade file: data/haarcascade_frontalface_default.xml") return } fmt.Printf("start reading camera device: %v\n", deviceID) for { if ok := webcam.Read(&img); !ok { fmt.Printf("cannot read device %v\n", deviceID) return } if img.Empty() { continue } // detect faces rects := classifier.DetectMultiScale(img) if len(rects) == 0 { continue } fmt.Printf("found %d faces\n", len(rects)) // draw a rectangle around each face on the original image for _, r := range rects { gocv.Rectangle(&img, r, blue, 3) imgFace := img.Region(r) buff, err:=gocv.IMEncode(".jpg",imgFace) if err != nil { fmt.Println("encoding to jpg err:%v", err) break } RecognizePeopleFromMemory(rec, buff) } // show the image in the window, and wait 1 millisecond window.IMShow(img) window.WaitKey(1) } } func RecognizePeople(rec *face.Recognizer, file string) { people, err := rec.RecognizeSingleFile(file) if err != nil { log.Fatalf("無法識別: %v", err) } if people == nil { log.Fatalf("圖片上不是一張臉") } peopleID := rec.Classify(people.Descriptor) if peopleID < 0 { log.Fatalf("無法區分") } fmt.Println(peopleID) fmt.Println(labels[peopleID]) } func RecognizePeopleFromMemory(rec *face.Recognizer, img []byte) { people, err := rec.RecognizeSingle(img) if err != nil { log.Println("無法識別: %v", err) return } if people == nil { log.Println("圖片上不是一張臉") return } peopleID := rec.Classify(people.Descriptor) if peopleID < 0 { log.Println("無法區分") return } fmt.Println(peopleID) fmt.Println(labels[peopleID]) } ~~~ 接下來我們運行代碼,應該能夠拉起攝像頭,這個時候我手持林俊杰的照片進行識別,我們可以看到左下角已經輸出對應的人名了。 ![img](https://codeantenna.com/image/https://img-blog.csdnimg.cn/img_convert/6437c45ce91fb97f1140a03f37724233.png) ## 視頻流人臉識別總結 到這一步,恭喜你,你已經能夠完成視頻流人臉識別了。但是,這里要說明一下,為了快速的實現,我們的樣本集是比較少的,識別成功率相對來說比較低。不過一個簡單的動態人臉識別已經搭好了。 # 總結 雖然我們實現了動態的人臉識別,但是在更為復雜的應用場景下難以實現相應的需求,而且存在圖片格式等限制,缺乏人臉處理的其他模塊,美顏,鑒黃等功能。不過通過第三方的 SDK,例如聲網等平臺去實現對應的需求,園區的人臉識別,視頻會議,云課堂等場景,能夠實現快速搭建,能夠幾行代碼就能夠完成相應的接入,并圍繞 RTE 等組件進行人臉識別的相關開發。為開發節約大量時間和成本,可以將開發重心轉移到更加核心的業務。 版權聲明:本文為CSDN博主「agora\_cloud」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。 原文鏈接:[https://blog.csdn.net/agora\_cloud/article/details/119522891](https://blog.csdn.net/agora_cloud/article/details/119522891)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看