背景
上一篇博客中試水了一下華爲機器學習服務,感覺效果還是不錯的,但是也不知道這些能力到底能幹嘛,於是乎……就給我找到了一個大哥寫的一篇講微笑抓拍的文章,改吧了一下代碼,頓時就可以用作自定義表情抓拍了。
鏈接戳下面↓
如果想看原版可以看原版
但是我就覺得太囉嗦了,重新整理了一下,原文裏面有具體的代碼配置,這裏我都不多說了哈
代碼已經上傳到某位師兄的github上了,talk is cheap
原文的代碼鏈接戳這裏
效果展示
這個是華爲官方放出來的人臉識別,看得出來在實時性上表現的很不錯,同時可以支持識別人臉的朝向,支持檢測人臉的表情(高興、厭惡、驚訝、傷心、憤怒、生氣),支持檢測人臉屬性(性別、年齡、穿戴),支持檢測是否睜眼閉眼,支持人臉以及鼻子、眼睛、嘴脣、眉毛等特徵的座標檢測
實際過程
原文中寫了很多代碼級的如何將華爲機器學習服務中的人臉識別服務抽離出來,然後將這個功能重新封裝。簡而言之就是幾點:
1. 添加一些配置項
其中包括maven的依賴,sdk的依賴(可以單獨只引入人臉識別模型而不用把其他模型全部引用進來),相機權限的開通等,這些配置項這位善良的大哥已經在po出來的代碼中都修改好了,非常的良心。
2. 代碼開發
在這一部分,我理解他是先設定一些參數,比如最小人臉在相機中的比例,關鍵點的數量等等,然後把這些參數傳給一個叫 MLAnalyzerFactory.getInstance().getFaceAnalyzer的分析器,這個分析器是華爲機器學習服務SDK中提供的,感覺好像重寫了他的回調函數,應該……就好了吧……
看起來很簡單的樣子,所以我就稍微改了一下下:
2.1 主要代碼如下:
public void transactResult(MLAnalyzer.Result<MLFace> result) {
SparseArray<MLFace> faceSparseArray = result.getAnalyseList();
int flag = 0;
for (int i = 0; i < faceSparseArray.size(); i++) {
MLFaceEmotion emotion = faceSparseArray.valueAt(i).getEmotions();
if (emotion.getSmilingProbability() > smilingPossibility) {
flag++;
}
}
if (flag > faceSparseArray.size() * smilingRate && safeToTakePicture) {
safeToTakePicture = false;
mHandler.sendEmptyMessage(TAKE_PHOTO);
}
}
faceSparseArray應該是SDK中提供的一種數據結構,裏面包含了一系列的人臉檢測的參數,包括表情,性別、年齡、穿戴,是否睜眼閉眼,鼻子、眼睛、嘴脣、眉毛等特徵的座標檢測等等。
在這裏那位大哥只調用了表情的參數,
MLFaceEmotion emotion = faceSparseArray.valueAt(i).getEmotions();
然後緊接着做了一個判斷,我理解的是如果微笑的概率大於你設定的特定閾值纔會認爲是微笑。
emotion.getSmilingProbability() > smilingPossibility
最後一部分就比較好理解了,如果出現了微笑的話就take photo啦
mHandler.sendEmptyMessage(TAKE_PHOTO);
這裏還有一個小點需要注意,判斷語句中的flag的值其實是實際檢測到笑臉的人臉個數(原來是支持多人臉的-_-||),底下的smilingRate是作者隨意定義的一個值,原文設立的是0.8,也就是說如果相機上有五個人,只要四個人笑就能夠拍照啦~
2.2 我的代碼如下:
需要修改的第一個地方是handler,把原來的handler裏面刪掉~
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case SMILE:
Toast.makeText(LiveFaceAnalyseActivity.this, "Smile", Toast.LENGTH_SHORT).show();
break;
case ANGRY:
Toast.makeText(LiveFaceAnalyseActivity.this, "angry", Toast.LENGTH_SHORT).show();
break;
case DISGUST:
Toast.makeText(LiveFaceAnalyseActivity.this, "disgust", Toast.LENGTH_SHORT).show();
break;
case FEAR:
Toast.makeText(LiveFaceAnalyseActivity.this, "fear", Toast.LENGTH_SHORT).show();
break;
case SAD:
Toast.makeText(LiveFaceAnalyseActivity.this, "sad", Toast.LENGTH_SHORT).show();
break;
case SURPRISE:
Toast.makeText(LiveFaceAnalyseActivity.this, "surprise", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
};
需要修改的第二個地方是
public void transactResult(MLAnalyzer.Result<MLFace> result) {
SparseArray<MLFace> faceSparseArray = result.getAnalyseList();
for (int i = 0; i < faceSparseArray.size(); i++) {
MLFaceEmotion emotion = faceSparseArray.valueAt(i).getEmotions();
if (emotion.getSmilingProbability() > smilingPossibility) {
mHandler.sendEmptyMessage(SMILE);
}
if (emotion.getAngryProbability() > 0.85f) {
mHandler.sendEmptyMessage(ANGRY);
}
if (emotion.getDisgustProbability() > 0.85f) {
mHandler.sendEmptyMessage(DISGUST);
}
if (emotion.getFearProbability() > 0.85f) {
mHandler.sendEmptyMessage(FEAR);
}
if (emotion.getSadProbability() > 0.85f) {
mHandler.sendEmptyMessage(SAD);
}
if (emotion.getSurpriseProbability() > 0.85f) {
mHandler.sendEmptyMessage(SURPRISE);
}
}
}
懂的人都知道我也沒幹啥,只是對着文檔找到了支持的所有表情然後依次識別,看看你到底是什麼表情~
具體的參數可以參考:
同時除了表情
裏面提供了超級多的參數可以調用
具體調用如下:
總結
表情識別就這樣做完啦,感謝那位大哥的分享,代碼寫的很優秀~ 一下子除了表情,開閉眼識別,帽子鬍子識別都可以做了~ 哈哈哈哈哈
效果不錯喲