歡迎訪問我的GitHub
這里分類和匯總了欣宸的全部原創(含配套原始碼):https://github.com/zq2599/blog_demos
本篇概覽
-
本文是《JavaCV的攝像頭實戰》系列的第十三篇,前文《JavaCV的攝像頭實戰之十二:性別檢測》中,借助訓練好的卷積神經網路模型開發出了識別性別的應用,今天在前文基礎上做少量改動,實作年齡識別的功能,效果如下圖:
-
應用主要功能如下圖所示:
-
如果您看過《JavaCV的攝像頭實戰》系列的其他文章,就會發現上圖中只有藍色部分是新增內容,其余的步驟都是固定套路,《JavaCV的攝像頭實戰》系列的每一個應用玩的都是相同套路:別看步驟挺多,其實都是同一個流程
關于性別和年齡檢測
- 使用卷積神經網路推理性別和年齡的更多技術細節,這里有更詳細的說明:
https://talhassner.github.io/home/publication/2015_CVPR - 本篇會使用已訓練好的Caffe 模型,訓練該模型的資料來自Flickr相冊,通過從 iPhone5(或更高版本)智能手機設備自動上傳組裝而成,并由其作者根據知識共享 (CC) 許可向公眾發布,共有26580張照片,涉及2284人,這些人的年齡一共被標識成八組:(0-2、4-6、8-13、15-20、25-32、38-43、48-53、60 -)
- 關于資料源的更多詳細,請參考:https://talhassner.github.io/home/projects/Adience/Adience-data.html
- 論文地址:https://talhassner.github.io/home/projects/cnn_agegender/CVPR2015_CNN_AgeGenderEstimation.pdf
原始碼下載
- 《JavaCV人臉識別三部曲》的完整原始碼可在GitHub下載到,地址和鏈接資訊如下表所示(https://github.com/zq2599/blog_demos):
名稱 | 鏈接 | 備注 |
---|---|---|
專案主頁 | https://github.com/zq2599/blog_demos | 該專案在GitHub上的主頁 |
git倉庫地址(https) | https://github.com/zq2599/blog_demos.git | 該專案原始碼的倉庫地址,https協議 |
git倉庫地址(ssh) | [email protected]:zq2599/blog_demos.git | 該專案原始碼的倉庫地址,ssh協議 |
- 這個git專案中有多個檔案夾,本篇的原始碼在javacv-tutorials檔案夾下,如下圖紅框所示:
- javacv-tutorials里面有多個子工程,《JavaCV的攝像頭實戰》系列的代碼在simple-grab-push工程下:
準備:檔案下載
- 本次實戰需要三個檔案:
- 人臉檢測的模型檔案:https://raw.github.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_alt.xml
- 年齡識別的組態檔:https://raw.githubusercontent.com/GilLevi/AgeGenderDeepLearning/master/age_net_definitions/deploy.prototxt
- 年齡識別的模型檔案:https://raw.githubusercontent.com/GilLevi/AgeGenderDeepLearning/master/models/age_net.caffemodel
- 我已將上述檔案打包上傳到CSDN,您也可以在CSDN下載(無需積分):
https://download.csdn.net/download/boling_cavalry/70730586
準備:代碼介面簡介
- 編碼前,先把涉及到的所有java檔案說明一下:
- AbstractCameraApplication.java:主程式的抽象類,這里面定義了打開攝像頭、抓取每一幀、處理每一幀的基本框架,避免每個應用都把這些事情重復做一遍
- PreviewCameraWithGenderAge.java:主程式,是AbstractCameraApplication的實作類,本次實戰的核心功能人臉檢測和年齡檢測,都委托給它的成員變數detectService去完成
- DetectService.java:檢測服務的介面,里面定義了幾個重要的api,例如初始化、處理每一幀、釋放資源等
- AgeDetectService.java:前文GenderDetectService的子類,僅僅是處理推理結果的邏輯與前文的性別識別略有不同,其余功能完全繼承自性別識別
- 以上代碼,咱們已經在前文寫過一次了,今天當然不需要重復再做一次,今天是在上述代碼基礎上做兩處小幅度修改,接下來就開始吧
改動一:主程式(PreviewCameraWithGenderAge.java)
- 卷積神經網路所需的配置和模型檔案,是在主程式的main方法內設定的,上一章是性別檢測,這里替換為年齡檢測的檔案,如下所示,請您將路徑換為自己電腦上的檔案路徑:
public static void main(String[] args) {
String base = "E:\\temp\\202112\\25\\opencv\\";
DetectService detectService = new AgeDetectService(
base + "haarcascade_frontalface_alt.xml",
base + "age\\deploy.prototxt",
base + "age\\age_net.caffemodel");
new PreviewCameraWithGenderAge(detectService).action(1000);
}
改動二:檢測服務實作(GenderDetectService的子類)
- 前文《性別檢測》的核心功能都集中在GenderDetectService.java中,今天要做的年齡檢測,除了推理結果的處理邏輯略有不同,其余功能與《性別檢測》完全一致
- 所以,實作年齡檢測的最簡單方法就是寫一個子類繼承GenderDetectService,這個子類中只有神經網路推理結果的處理邏輯,完整代碼如下,注釋中已經有了詳細說明,就不多贅述了:
package com.bolingcavalry.grabpush.extend;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.DoublePointer;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point;
import static org.bytedeco.opencv.global.opencv_core.minMaxLoc;
/**
* @author willzhao
* @version 1.0
* @description 檢測年齡的服務
* @date 2021/12/3 8:09
*/
@Slf4j
public class AgeDetectService extends GenderDetectService {
/**
* 設定訓練模型時劃分的年齡段,所以推理結果也是這樣的年齡段
*/
private static final String[] AGES = new String[]{"0-2", "4-6", "8-13", "15-20", "25-32", "38-43", "48-53", "60-"};
/**
* 構造方法,在此指定proto和模型檔案的下載地址
*
* @param classifierModelFilePath
* @param cnnProtoFilePath
* @param cnnModelFilePath
*/
public AgeDetectService(String classifierModelFilePath, String cnnProtoFilePath, String cnnModelFilePath) {
super(classifierModelFilePath, cnnProtoFilePath, cnnModelFilePath);
}
@Override
protected String getDescriptionFromPredictResult(Mat prob) {
DoublePointer pointer = new DoublePointer(new double[1]);
Point max = new Point();
// 把prob理解為一個陣列,
// 第一個元素是"0-2"的置信度
// 第二個元素是"4-6"的置信度
// 第三個元素是"8-13"的置信度
// 第四個元素是"15-20"的置信度
// ...
// 第八個元素是"60-"的置信度
// minMaxLoc方法幫忙我們找出了置信度最高的元素,max是元素位置,pointer是這個元素的置信度
minMaxLoc(prob, null, pointer, null, max, null);
// 如果置信度太低,那就是"難以置信",就回傳空字串
if (pointer.get()<0.6d) {
return "";
} else {
// 如果置信度可信,就回傳該元素對應的年齡范圍
return AGES[max.x()];
}
}
}
- 至此,編碼完成,按套路出牌讓咱們省下不少時間,接下來開始驗證
驗證
- 確保攝像頭作業正常,運行PreviewCameraWithGenderAge類的main方法(再次提醒,main方法中檔案的位置,注意是年齡檢測的模型檔案,不是性別檢測的)
- 天氣很冷,為了領到免費盒飯,群眾演員早就等得不耐煩了,讓他站在攝像頭前,如下圖,年齡識別成功,且實時展示:
- 至此,本地視窗預覽集成人臉檢測和年齡檢測的功能就完成了,得益于JavaCV的強大,整個程序是如此的輕松愉快,接下來請繼續關注欣宸原創,《JavaCV的攝像頭實戰》系列還會呈現更多豐富的應用;
關于性別+年齡識別
- 如果您關注過網上關于性別和年齡識別相關的技術文章,您會發現通常這些文章會將兩種識別集成在一起講,并且代碼的效果也是繼承了兩種識別的,如下圖:
- 也行您會有疑問:欣宸為何不把兩種識別放在一篇文章和一個demo中,這樣內容更完整demo也更強大?
- 之所以分文兩篇,是因為年齡和性別識別的套路比較接近,如果在一篇文中講完,無非是多寫幾行代碼多打幾行字,不會對技術帶來提升,那還不如每篇只聚焦一個功能,把初始化、使用、資源釋放等技術點說清楚,至于單獨用還是組合用,留給聰明的讀者按自己的需求去自由組合即可
歡迎關注博客園:程式員欣宸
學習路上,你不孤單,欣宸原創一路相伴...
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556514.html
標籤:其他
下一篇:返回列表