本週完成的工作主要包括以下三方面的內容:
- 情緒檢測的web集成
- 手勢識別的web集成和優化
- 視線追蹤模型的進一步優化
情緒檢測web集成
集成的具體細節方面:輸入爲圖片的dataURL,即圖片的base64格式,最小4848,最大40964096
輸出爲表示情緒的7維向量,使用json格式表示。7維分別是:
- anger:憤怒
- disgust:厭惡
- fear:恐懼
- happiness:高興
- neutral:平靜
- sadness:傷心
- surprise:驚訝
相關代碼如下
var facepp = new FACEPP(APIKEY,APISERET,1);
function getEmotion(base64Image){
console.log(base64Image);
//圖片的base64數據
//const base64Image=arrayBufferToBase64(img);
// 以二進制的方式上傳圖片
// 將base64轉爲二進制
//let imageData = facepp.dataURItoBlob(base64Image);
//根據個人需求填寫的參數,這裏全部寫上了,包括年齡性別等,詳情看官方文檔
let attributes = 'gender,age,smiling,headpose,facequality,blur,eyestatus,emotion,ethnicity,beauty,mouthstatus,eyegaze,skinstatus';
//上傳圖片,獲取結果
let dataDic = {'image_base64':base64Image,'return_landmark':2,'return_attributes':attributes};
//調用接口,檢測人臉
facepp.detectFace(dataDic,success);
}
function success(e){
//console.log(JSON.stringify(e,null,"\t"))
const faces = e.faces;
const face=faces[0];
var emotion=face.attributes.emotion
console.log(emotion);
}
// Converts canvas to an image
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL();
return image;
}
window.onload=function(){
var img=new Image();
img.src="test.png";
//img.setAttribute('crossOrigin', 'anonymous');
var canvas=document.getElementById('picCan');
var canCC=canvas.getContext('2d');
img.onload = function(){
canCC.drawImage(img,0,0,500,400);
};
var base64Image=canvas.toDataURL("image/png");
// 在控制檯中可以查看獲取的情緒json,F12啓動
getEmotion(base64Image);
}
</script>
手勢識別的web集成和優化
在WEB頁面的攝像頭獲取基本邏輯和Python中的差不多,只不過在html中需要 <video >和<canvas>兩個標籤,這兩個都是H5中的新標籤,<video >標籤定義視頻,比如電影片段或其他視頻流而<canvas>標籤定義圖形,比如圖表和其他圖像。需要注意的是<canvas>標籤只是圖形容器,必須使用腳本來繪製圖形.
用於獲取攝像頭視頻流並展示的html頁面如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Video Capture Example</title>
</head>
<body>
<video id="videoInput" height=240 width=320></video>
<canvas id="canvasFrame" height=240 width=320 ></canvas>
<canvas id="FirstFrame" height=240 width=320 ></canvas>
<canvas id="canvasOutput" height=240 width=320 ></canvas>
<script src="js代碼邏輯" type="text/javascript"></script>
</body>
</html>
視頻獲取的js代碼如下
let video = document.getElementById("videoInput");
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
.then(function (stream) {
video.height = HEIGHT;
video.width = WIDTH;
video.srcObject = stream;
video.play();
}).catch(function (err) {
console.log("An error occured! " + err);
});
視頻處理部分
var frame = new cv.Mat(HEIGHT, WIDTH, cv.CV_8UC4);
cap.read(frame);
// cv.bilateralFilter(frame, frame, 5, 50, 100,cv.BORDER_DEFAULT) // 雙邊濾波 gg
cv.flip(frame,frame,1) // 反轉
var gray = new cv.Mat();
cv.cvtColor(frame, gray, cv.COLOR_RGBA2GRAY);
var ksize = new cv.Size(21,21);
cv.GaussianBlur(gray,gray, ksize ,0)
// console.log(firstFrame)
幀間差分法獲取移動物體
if(firstFrame == null){
console.log('enter')
firstFrame = gray;
setTimeout(processVideo,0)
}
cv.imshow("FirstFrame", frame);
// let frameDelta = new cv.Mat(HEIGHT, WIDTH, cv.CV_8UC1);
var frameDelta = new cv.Mat();
cv.absdiff(first Frame, gray, frameDelta) // 幀間差
var thresh = new cv.Mat();
cv.threshold(frameDelta,thresh, 25, 255, cv.THRESH_BINARY)
let M = new cv.Mat();
let anchor = new cv.Point(-1, -1);
cv.dilate(thresh,thresh,M,anchor, 2)
當畫面發生變化,也就是有運動物體時,效果圖如下
視線追蹤模型的進一步優化
爲了根據新設計的數據集進一步優化模型,我們首先要做的是採集數據。數據採集工具是根據lookielookie項目進行改造的。主要實現步驟如下
1.注視鼠標指針然後按下空格來採集數據
採集後右上角的數字會增加,同時如果點擊"draw heatmap"按鈕會繪製出當前採集的屏幕座標:
小一點的點用於訓練,大一點的點用於驗證。
2.保存採集的數據
採集一段時間數據之後,可以點擊"save dataset"按鈕來保存數據,數據會以json文件形式下載到默認的下載目錄中,文件名爲dataset.json:
完成採集後,就是訓練過程了,具體的訓練代碼可以參加這篇博客
經過反覆調整batch,learning rate,在模型上訓練400輪的結果如下
複雜模型訓練結果和驗證結果
簡單模型上的訓練驗證結果
在小數據集(251個樣本)上,從上圖中可以看出,同樣在400輪的基礎上,複雜模型在訓練集上表現很好,在驗證集上表現很差,可見有嚴重的過擬合;在簡單模型上,訓練集上的表現和複雜模型差不多,但在驗證集上表現就比複雜模型好很多了。
而且在訓練輪數增加之後,複雜模型loss能更進一步降到0.001左右,而簡單模型就基本在0.008左右。
對於這種現象,下一步我們決定適當減少複雜模型的特徵,並擴充數據集,再對比簡單模型看效果是否有改善。