Html5呼叫手機攝像頭並實現人臉識別的實現

需求

混合App開發,原生殼子+webApp,在web部分呼叫原生攝像頭功能並且在網頁指定區域顯示攝像頭內容,同時可以手動拍照並進行人臉識別,將識別結果顯示在網頁上。

技術棧

vue、Html5、video標籤、Android、IOS、百度AI

分析

1、使用navigator。mediaDevices。getUserMedia呼叫系統原生攝像頭功能

2、video標籤顯示攝像頭內容

3、canvas標籤獲取圖片

4、將影象上傳伺服器,透過百度AI識別圖片

5、web顯示識別結果

核心程式碼

1、呼叫系統原生攝像頭功能並使用video標籤顯示html:

<video

id="webcam"

style="videoStyle"

width="videoWidth"

height="videoHeight"

loop

preload

>

</video>

JavaScript:

initVideo() {

let that = this;

this.video = document.getElementById("webcam");

setTimeout(() => {

if (

navigator.mediaDevices.getUserMedia ||

navigator.getUserMedia ||

navigator.webkitGetUserMedia ||

navigator.mozGetUserMedia

) {

//呼叫使用者媒體裝置, 訪問攝像頭

this.getUserMedia(

{

video: {

width: {

ideal: that.videoWidth,

max: that.videoWidth

},

height: {

ideal: that.videoHeight,

max: that.videoHeight

},

facingMode: "user", //前置攝像頭

frameRate: {

ideal: 30,

min: 10

}

}

},

this.videoSuccess,

this.videoError

);

} else {

this.$toast.center("攝像頭開啟失敗,請檢查許可權設定!");

}

}, 300);

},

getUserMedia(constraints, success, error) {

if (navigator.mediaDevices.getUserMedia) {

//最新的標準API

navigator.mediaDevices

.getUserMedia(constraints)

.then(success)

.catch(error);

} else if (navigator.webkitGetUserMedia) {

//webkit核心瀏覽器

navigator.webkitGetUserMedia(constraints, success, error);

} else if (navigator.mozGetUserMedia) {

//firfox瀏覽器

navigator.mozGetUserMedia(constraints, success, error);

} else if (navigator.getUserMedia) {

//舊版API

navigator.getUserMedia(constraints, success, error);

}

}

videoSuccess(stream) {

this.mediaStreamTrack = stream;

this.video.srcObject = stream;

this.video.play();

},

videoError(error) {

console.error(error);

this.$toast.center("攝像頭開啟失敗,請檢查許可權設定!");

},

2、canvas獲取攝像頭圖片

JavaScript:

this.canvas = document.createElement("canvas");

....

let context = this.canvas.getContext("2d");

context.drawImage(this.video, 0, 0, this.videoWidth, this.videoHeight);

this.imgSrc = this.canvas.toDataURL("image/png");

3、呼叫百度AI識別圖片

JavaScript:

let that = this;

let base64Data = this.canvas.toDataURL();

let blob = this.dataURItoBlob(base64Data);

var file = new FormData();

file.append("file", blob);

file.append("key", that.uuid);

util.ajax

.post("XXXXXXXXXX", file, {

headers: {

"Content-Type": "multipart/form-data"

}

})

.then(function(response) {

if ((response.status = 200)) {

.....識別成功,顯示結果

} else {

......識別失敗

}

})

.catch(function(error) {

console.error(error);

});

//base64轉換為Blob

dataURItoBlob(base64Data) {

var byteString;

if (base64Data.split(",")[0].indexOf("base64") >= 0)

byteString = atob(base64Data.split(",")[1]);

else byteString = unescape(base64Data.split(",")[1]);

var mimeString = base64Data

.split(",")[0]

.split(":")[1]

.split(";")[0];

var ia = new Uint8Array(byteString.length);

for (var i = 0; i < byteString.length; i++) {

ia[i] = byteString.charCodeAt(i);

}

return new Blob([ia], { type: mimeString });

},

手機適配

1、由於Android6之後,Android的許可權管理出現變化,Android原生的殼子,需要做如下處理:

myWebView.setWebChromeClient(new WebChromeClient() {

@TargetApi(Build.VERSION_CODES.LOLLIPOP)

@Override

public void onPermissionRequest(final PermissionRequest request) {

request.grant(request.getResources());

}

});

2、IOS系統,Safari11之後可用

3、OverconstrainedError錯誤,部分Android手機會報OverconstrainedError錯誤,原因是攝像頭引數設定不合理,找不到指定設定。

注:如程式碼有錯誤請主動聯絡釋出者。