在瀏覽器中使用TensorFlow.js和Python構(gòu)建機(jī)器學(xué)習(xí)模型
概述
- TensorFlow.js (deeplearn.js)使我們能夠在瀏覽器中構(gòu)建機(jī)器學(xué)習(xí)和深度學(xué)習(xí)模型,而無(wú)需任何復(fù)雜的安裝步驟。
- TensorFlow.js的兩個(gè)組件——Core API和Layer API。
- 了解如何構(gòu)建一個(gè)很棒的使用Tensorflow.js對(duì)網(wǎng)絡(luò)攝像頭中的圖像進(jìn)行分類(lèi)的模型。
介紹
你喜歡用什么工具來(lái)編寫(xiě)機(jī)器學(xué)習(xí)模型?數(shù)據(jù)科學(xué)家們對(duì)這個(gè)永恒的問(wèn)題會(huì)給出各種不同的答案。一些人喜歡RStudio,另一些人更喜歡Jupyter Notebooks。我絕對(duì)屬于后者。
所以,當(dāng)我第一次遇到TensorFlow.js(以前是deeplearn.js)時(shí),我的心都要炸開(kāi)了。在瀏覽器中構(gòu)建機(jī)器學(xué)習(xí)模型?使用JavaScript?聽(tīng)起來(lái)好得令人難以置信!
超過(guò)43億人使用網(wǎng)絡(luò)瀏覽器——約占世界人口的55%。——維基百科(2019年3月)
谷歌的TensorFlow.js不僅將機(jī)器學(xué)習(xí)引入瀏覽器中,使機(jī)器學(xué)習(xí)大眾化,而且對(duì)于經(jīng)常使用JavaScript的開(kāi)發(fā)人員來(lái)說(shuō),它也是一個(gè)完美的機(jī)器學(xué)習(xí)門(mén)戶。
我們的網(wǎng)絡(luò)瀏覽器是最容易訪問(wèn)的平臺(tái)之一。這就是為什么構(gòu)建不僅能夠訓(xùn)練機(jī)器學(xué)習(xí)模型而且能夠在瀏覽器本身中“學(xué)習(xí)”或“遷移學(xué)習(xí)”的應(yīng)用程序是有意義的。
在本文中,我們將首先了解使用TensorFlow.js的重要性及其它的不同組件。然后,我們將深入討論使用TensorFlow.js在瀏覽器中構(gòu)建我們自己的機(jī)器學(xué)習(xí)模型。然后我們將構(gòu)建一個(gè)應(yīng)用程序,來(lái)使用計(jì)算機(jī)的網(wǎng)絡(luò)攝像頭檢測(cè)你的身體姿勢(shì)!
如果你是TensorFlow的新手,你可以在下面文章中了解更多:
- TensorFlow 101: Understanding Tensors and Graphs to get you Started with Deep Learning
- Introduction to Implementing Neural Networks using TensorFlow
目錄
一、為什么你應(yīng)該使用TensorFlow.js?
1.1 使用網(wǎng)絡(luò)攝像頭在瀏覽器中進(jìn)行圖像分類(lèi)
1.2 TensorFlow.js的特征
二、了解瀏覽器中的機(jī)器學(xué)習(xí)
2.1 Core API:使用Tensors工作
2.2 Layer API:像Keras一樣構(gòu)建模型
三、利用谷歌的預(yù)訓(xùn)練模型:PoseNet
一、為什么要使用TensorFlow.js?
我將用一種獨(dú)特的方法來(lái)回答這個(gè)問(wèn)題。我不會(huì)深入研究TensorFlow.js的理論方面,也不會(huì)列出它為什么是一個(gè)如此不可思議的工具。
相反,我將簡(jiǎn)單地向你展示如果不使用TensorFlow.js將會(huì)錯(cuò)過(guò)什么。那么,讓我們?cè)?分鐘內(nèi)構(gòu)建一個(gè)應(yīng)用程序,來(lái)使用你的網(wǎng)絡(luò)攝像頭對(duì)圖像進(jìn)行分類(lèi)。沒(méi)錯(cuò)——我們將直接進(jìn)入代碼部分!
這是最好的部分——你不需要安裝任何東西來(lái)做這個(gè)!只要一個(gè)文本編輯器和一個(gè)網(wǎng)絡(luò)瀏覽器即可。下面的動(dòng)圖展示了我們將要構(gòu)建的應(yīng)用程序:
在瀏覽器中使用TensorFlow.js和Python構(gòu)建機(jī)器學(xué)習(xí)模型
這多酷?。∥以跒g覽器里幾分鐘就完成了。那么,讓我們看一下步驟和代碼,以幫助你在Web瀏覽器中構(gòu)建自己的圖像分類(lèi)模型。
1.1 使用網(wǎng)絡(luò)攝像頭在瀏覽器中構(gòu)建圖像分類(lèi)模型
打開(kāi)你選擇的文本編輯器并創(chuàng)建一個(gè)文件index.html。將以下代碼保存于此文件內(nèi):
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <!-- title of the page -->
- <title>image_classification</title>
- <!-- load processing library-->
- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.min.js"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/addons/p5.dom.min.js"></script>
- <!-- load ml5.js -->
- <script src="https://unpkg.com/ml5@0.1.1/dist/ml5.min.js"></script>
- <!-- load index.js -->
- <script src="index.js"></script>
- </head>
- <body>
- <!-- this is where the video will be shown -->
- <video id="video"></video>
- </body>
- </html>
接下來(lái),創(chuàng)建另一個(gè)文件index.js并在其中編寫(xiě)以下代碼:
- let mobilenet;
- let video;
- let label = '';
- // when model is ready make predictions
- function modelReady() {
- console.log('Model is ready!!!');
- mobilenet.predict(gotResults);
- }
- function gotResults(error, results) {
- if (error) {
- console.error(error);
- } else {
- label = results[0].className;
- // loop the inference by calling itself
- mobilenet.predict(gotResults);
- }
- }
- // setup function
- function setup() {
- createCanvas(640, 550);
- // ml5 to create video capture
- video = createCapture(VIDEO);
- video.hide();
- background(0);
- // load the MobileNet and apply it on video feed
- mobilenet = ml5.imageClassifier('MobileNet', video, modelReady);
- }
- function draw() {
- background(0);
- // show video
- image(video, 0, 0);
- fill(255);
- textSize(32);
- // show prediction label
- text(label, 10, height - 20);
- }
保存這兩個(gè)文件,然后在谷歌Chrome或Mozilla Firefox等瀏覽器中打開(kāi)index.html文件。就是這樣!你現(xiàn)在已經(jīng)創(chuàng)建了一個(gè)可以使用你的網(wǎng)絡(luò)攝像頭在瀏覽器本身實(shí)時(shí)分類(lèi)圖像的應(yīng)用程序!下面是它在我的計(jì)算機(jī)上的樣子:
視頻連接:
- https://s3-ap-south-1.amazonaws.com/av-blog-media/wp-content/uploads/2019/05/mobilenet_demo.mp4?_=1
在這個(gè)例子中需要注意的要點(diǎn):
- 在上面的例子中,我們使用了一個(gè)預(yù)先訓(xùn)練的圖像分類(lèi)模型MobileNet(https://ai.googleblog.com/2017/06/mobilenets-open-source-models-for.html)
- 我們使用ml5.js(https://ml5js.org/)一個(gè)構(gòu)建在TensorFlow之上的庫(kù)。它將MobileNet模型加載到瀏覽器中,并對(duì)視頻提要執(zhí)行推理。
- 我們還利用P5.js(https://p5js.org/)庫(kù)來(lái)處理視頻輸入并在視頻本身上顯示標(biāo)簽。
我不需要在電腦上安裝任何東西。這個(gè)例子應(yīng)該適用于任何現(xiàn)代系統(tǒng),不管它是Linux、Windows還是MacOS——這就是使用JavaScript在web上構(gòu)建模型的強(qiáng)大功能。
現(xiàn)在,讓我們看看TensorFlow.js提供的強(qiáng)大功能,以及如何利用它們?cè)跒g覽器中部署機(jī)器學(xué)習(xí)模型。
1.2 TensorFlow.js的特征
TensorFlow.js是一個(gè)庫(kù),用于JavaScript開(kāi)發(fā)和訓(xùn)練ML模型,并在瀏覽器或Node.js上部署。
TensorFlow.js提供了許多的功能來(lái)供我們使用。
它是TensorFlow在JavaScript中的擴(kuò)展,JavaScript是我們?cè)诨ヂ?lián)網(wǎng)上使用的幾乎所有網(wǎng)站、瀏覽器或應(yīng)用程序邏輯背后的編程語(yǔ)言。JavaScript和Python一樣用途廣泛,所以使用它來(lái)開(kāi)發(fā)機(jī)器學(xué)習(xí)模型給我們帶來(lái)了很多好處:
如果ML模型是用web語(yǔ)言編寫(xiě)的,則更容易部署。
- 由于所有主流瀏覽器都支持JavaScript,所以你可以無(wú)處不在地使用它,而不必?fù)?dān)心平臺(tái)類(lèi)型或其他兼容性問(wèn)題。對(duì)于你的用戶也是如此。
- TensorFlow.js是一個(gè)客戶端庫(kù),這意味著它可以在用戶的瀏覽器中訓(xùn)練或運(yùn)行ML模型。這減輕了與數(shù)據(jù)隱私有關(guān)的任何擔(dān)憂。
- 在你的客戶端上運(yùn)行實(shí)時(shí)推斷可使你的應(yīng)用程序更具交互性,因?yàn)樗鼈兛梢粤⒓错憫?yīng)用戶輸入(例如我們前面構(gòu)建的webcam應(yīng)用程序)。
TensorFlow.js以其當(dāng)前的形式提供了以下主要功能:
- 瀏覽器中的機(jī)器學(xué)習(xí):你可以使用TensorFlow.js在瀏覽器中創(chuàng)建和訓(xùn)練ML模型。
- 谷歌的預(yù)訓(xùn)練模型:TensorFlow.js配備了一套由谷歌預(yù)訓(xùn)練的模型,用于對(duì)象檢測(cè)、圖像分割、語(yǔ)音識(shí)別、文本毒性分類(lèi)等任務(wù)。
- 遷移學(xué)習(xí):你可以通過(guò)對(duì)已經(jīng)訓(xùn)練過(guò)的模型的部分進(jìn)行再訓(xùn)練來(lái)執(zhí)行轉(zhuǎn)移學(xué)習(xí),比如TensorFlow.js中的MobileNet。
- 部署python模型:使用Keras或TensorFlow訓(xùn)練的模型可以很容易地導(dǎo)入瀏覽器/使用TensorFlow.js的部署。
在本文中,我們將關(guān)注前兩個(gè)功能。在本系列的第二部分(即將推出!)中,我們將討論如何在Python中轉(zhuǎn)移學(xué)習(xí)和部署我們的模型。
二、瀏覽器中的機(jī)器學(xué)習(xí)
TensorFlow.js提供了兩種方法來(lái)訓(xùn)練模型(非常類(lèi)似于TensorFlow):
- 第一種方法是使用Core API使用低級(jí)張量操作來(lái)定義模型。
- 第二種方法是使用Layers API定義模型,類(lèi)似于Keras。
讓我們通過(guò)幾個(gè)例子來(lái)理解這兩種方法。畢竟,學(xué)習(xí)一個(gè)概念最好的方法就是把它付諸實(shí)踐!
首先,設(shè)置你的HTML文件:
在你的電腦上建立一個(gè)新的index.html文件,并在其中編寫(xiě)以下代碼:
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <!-- load Tensorflow.js -->
- <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script>
- </head>
- <body>
- <h1>Tensorflow.js Core API</h1>
- <!-- <script src="index.js"></script> -->
- <script type="text/javascript">
- </script>
- </body>
- </html>
我們創(chuàng)建了一個(gè)基本的HTML頁(yè)面,并從云URL中加載了Tensorflow.js(第7行)。
關(guān)于安裝TensorFlow.js(deeplearn.js)的說(shuō)明:
由于TensorFlow.js是為瀏覽器而設(shè)計(jì)的,所以安裝和使用TensorFlow.js最簡(jiǎn)單的方法就是根本不安裝它。你可以簡(jiǎn)單地從HTML中的URL加載它即可。
如果你想在本地工作怎么辦呢?實(shí)際上,你可以在Jupyter Notebook中使用TensorFlow.js,就像你在Python或R中通常做的那樣。這是一個(gè)適合每個(gè)人的解決方案!
這種本地方法稍微長(zhǎng)一些,并且需要一些時(shí)間,所以本文不會(huì)使用它。如果你確實(shí)想學(xué)習(xí)如何操作,可以從為Jupyter安裝ijavascript內(nèi)核開(kāi)始。下面是我的Jupyter Notebook的截圖:
現(xiàn)在,使用TensorFlow.js的推薦方法是使用庫(kù)的官方URL直接加載它。你只需將以下行添加到HTML文件中:
- <scriptsrcscriptsrc="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script>
完成了!這真的很簡(jiǎn)單。
2.1 Core API:使用Tensors工作
Core API與TensorFlowCore非常相似,我們可以使用低級(jí)張量運(yùn)算和線性代數(shù)定義模型。
如果我們想要構(gòu)建自定義模型或想要從頭開(kāi)始構(gòu)建神經(jīng)網(wǎng)絡(luò),這非常有用。讓我們舉一個(gè)在瀏覽器中使用張量的例子。
首先在index.html文件中的<script> </ script>標(biāo)記之間添加以下代碼:
- const a = tf.tensor([1, 2, 3, 4]);
- const b = tf.tensor([10, 20, 30, 40]);
- const y = a.add(b); // equivalent to tf.add(a, b)
- const z = a.mul(b);
- y.print();
- z.print();
<script>標(biāo)簽基本上表示JavaScript。我們?cè)谶@些標(biāo)簽之間寫(xiě)的任何內(nèi)容都將作為JavaScript代碼執(zhí)行。以下是index.html現(xiàn)在的樣子:
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <!-- load Tensorflow.js -->
- <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.0.0/dist/tf.min.js"></script>
- </head>
- <body>
- <h1>Tensorflow.js Core API</h1>
- <!-- <script src="index.js"></script> -->
- <script type="text/javascript">
- const a = tf.tensor([1, 2, 3, 4]);
- const b = tf.tensor([10, 20, 30, 40]);
- const y = a.add(b); // equivalent to tf.add(a, b)
- const z = a.mul(b); // equivalent to tf.mul(a, b)
- y.print();
- z.print();
- </script>
- </body>
- </html>
在上面的代碼中,我們?cè)趦蓚€(gè)張量a和b上執(zhí)行基本的加法和乘法運(yùn)算,并將結(jié)果打印在瀏覽器中?,F(xiàn)在,轉(zhuǎn)到終端,打開(kāi)項(xiàng)目文件夾,然后使用以下命令啟動(dòng)Python服務(wù)器:
- python3 -m http.server
然后在你的瀏覽器打開(kāi)以下地址:
- http://localhost:8000/
當(dāng)你看到一個(gè)頁(yè)面顯示“Tensorflow.js Core API”時(shí),使用Ctrl+Shift+I鍵打開(kāi)控制臺(tái)(console)。這應(yīng)該在Chrome和Firefox都適用。我們?cè)诳刂婆_(tái)得到上述操作的輸出:
如果你想深入閱讀有關(guān)Core API的更多信息,那么我建議你閱讀CoreAPI官方文檔。
CoreAPI文檔:
- https://www.tensorflow.org/js/guide/tensors_operations
2.2 Layer API:像Keras一樣構(gòu)建模型
Layers API與Python中的Keras非常相似。就像Keras一樣,你可以使用序列的和函數(shù)的方法創(chuàng)建模型。
讓我們通過(guò)一個(gè)例子仔細(xì)研究序列方法。我們將在這些數(shù)據(jù)點(diǎn)上訓(xùn)練回歸模型:
這里,X和Y有一個(gè)線性關(guān)系——每個(gè)Y對(duì)應(yīng)于X + i(其中i是0、1、2、3……n+1)。讓我們?cè)谶@個(gè)數(shù)據(jù)集上訓(xùn)練一個(gè)基本的回歸模型。你可以在index.html文件中的<script></script>標(biāo)記之間編寫(xiě)以下代碼:
- const callbacks = {
- onEpochEnd: async (epoch, logs) => {
- console.log("epoch: " + epoch + JSON.stringify(logs))
- }
- };
- // Generate some synthetic data for training.
- const xs = tf.tensor2d([[1], [2], [3], [4]], [4, 1]);
- const ys = tf.tensor2d([[1], [3], [5], [7]], [4, 1]);
- // Build and compile model.
- async function basicRegression(){
- // Build a sequential model
- const model = tf.sequential();
- model.add(tf.layers.dense({units: 1, inputShape: [1]}));
- model.add(tf.layers.dense({units: 1, inputShape: [1]}));
- model.compile({optimizer: 'sgd', loss: 'meanSquaredError'});
- // Train model with fit().
- await model.fit(xs, ys, {epochs: 100, validationSplit: 0.1, callbacks: callbacks});
- // Run inference with predict().
- model.predict(tf.tensor2d([[5]], [1, 1])).print();
- }
- // Create a basic regression model
- basicRegression();
敏銳的讀者一定注意到,上面的語(yǔ)法與用Python構(gòu)建順序模型的Keras語(yǔ)法非常相似。我們回到瀏覽器控制臺(tái)(console)時(shí)會(huì)得到預(yù)測(cè)。
我們的簡(jiǎn)單回歸模型預(yù)測(cè)7.556,非常接近8的期望值。這是一個(gè)基本的例子,但我們可以清楚地看到,在瀏覽器中直接構(gòu)建機(jī)器學(xué)習(xí)模型是多么容易和有用。
TensorFlow.js能夠在瀏覽器中構(gòu)建機(jī)器學(xué)習(xí)和深度學(xué)習(xí)模型。它還自動(dòng)利用GPU(s)的強(qiáng)大功能,如果在你的系統(tǒng)模型訓(xùn)練期間可用。
下面是一些使用TensorFlow.js在一些標(biāo)準(zhǔn)數(shù)據(jù)集上訓(xùn)練的深度學(xué)習(xí)模型的例子:
你可以在tfjs-examples repository中瀏覽這些示例。
tfjs-examples repository:
- https://github.com/tensorflow/tfjs-examples
三、利用谷歌的預(yù)訓(xùn)練模型:PoseNet
TensorFlow.js提供了大量來(lái)自谷歌的預(yù)訓(xùn)練模型,用于許多有用的任務(wù),如目標(biāo)檢測(cè)、語(yǔ)音識(shí)別、圖像分割等。預(yù)先訓(xùn)練的模型的優(yōu)點(diǎn)是,我們可以使用它們而不需要任何重大的依賴(lài)關(guān)系或安裝,并且可以開(kāi)箱即用。
人們普遍預(yù)計(jì)谷歌將在未來(lái)幾個(gè)月推出更多模型。你可以在下面鏈接查看可用的預(yù)訓(xùn)練模型:
相關(guān)鏈接:
- https://www.tensorflow.org/js/models
我們將在本文中使用PoseNet。PoseNet是一種視覺(jué)模型,可以通過(guò)估計(jì)人體關(guān)鍵關(guān)節(jié)的位置來(lái)估計(jì)一個(gè)人在圖像或視頻中的姿勢(shì)。
PoseNet是如何工作的?
這是一個(gè)迷人的概念。姿勢(shì)估計(jì)是一種計(jì)算機(jī)視覺(jué)技術(shù),用于檢測(cè)圖像和視頻中的人物。例如,這可以幫助我們確定某人的肘部在圖像中出現(xiàn)的位置。
只是要清楚-姿勢(shì)估計(jì)不是關(guān)于識(shí)別誰(shuí)在一個(gè)圖像中。該算法只是簡(jiǎn)單地估計(jì)關(guān)鍵身體關(guān)節(jié)的位置。
檢測(cè)到的關(guān)鍵點(diǎn)設(shè)置為“Part”和“ID”索引,置信度得分在0.0和1.0之間(1.0是最高的)。
以下是PoseNet給出的輸出類(lèi)型的示例:
難以置信,對(duì)吧?!我們將使用ml5.js庫(kù)來(lái)使用PoseNet。ml5.js是一個(gè)基于TensorFlow.js和p5.js的庫(kù)。p5.js是另一個(gè)庫(kù)可以使你更容易在瀏覽器中訪問(wèn)網(wǎng)絡(luò)攝像頭。
ml5.js旨在使機(jī)器學(xué)習(xí)對(duì)廣大的藝術(shù)家,創(chuàng)意編碼員和學(xué)生來(lái)說(shuō)變得平易近人。該庫(kù)以TensorFlow.js為基礎(chǔ),通過(guò)簡(jiǎn)單的語(yǔ)法在瀏覽器中提供對(duì)機(jī)器學(xué)習(xí)算法和模型的訪問(wèn)。
例如,你可以使用ml5.js在5行代碼中使用MobileNet創(chuàng)建圖像分類(lèi)模型,如下所示:
正是由于Ml5.js的簡(jiǎn)單性,使得它非常適合在瀏覽器中快速構(gòu)建原型,這也是我們?cè)陧?xiàng)目中使用它的原因。
讓我們回到PoseNet。創(chuàng)建一個(gè)新文件index.html并添加以下代碼:
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
- <!-- load p5.js -->
- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>
- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/addons/p5.dom.min.js"></script>
- <!-- load ml5.js -->
- <script src="https://unpkg.com/ml5@0.2.3/dist/ml5.min.js" type="text/javascript"></script>
- <!-- keep the video in center of browser -->
- <style type="text/css">
- body{
- text-align: center;
- }
- </style>
- </head>
- <body>
- <h1>PoseNet demo with Ml5.js</h1>
- <p id="status">Loading Model...</p>
- <div id="videoContainer"></div>
- <!-- load the posenet.js file -->
- <script src="posenet.js"></script>
- </body>
- </html>
這將創(chuàng)建一個(gè)基本的HTML網(wǎng)頁(yè)并加載必要的文件。
- ml5.js和p5.js是通過(guò)其官方URL加載的。
- posenet.js是我們將編寫(xiě)用于使用PoseNet的代碼的文件。
現(xiàn)在,我們將編寫(xiě)用于使用PoseNet的JavaScript代碼。在與index.html相同的文件夾中創(chuàng)建一個(gè)新文件posenet.js。以下是完成此項(xiàng)工作所需的步驟:
- 加載PoseNet模型并從網(wǎng)絡(luò)攝像頭捕獲視頻
- 檢測(cè)身體關(guān)節(jié)的關(guān)鍵點(diǎn)
- 顯示檢測(cè)到的身體關(guān)節(jié)
- 繪制估計(jì)的身體骨骼
讓我們從第一步開(kāi)始。
步驟1:加載PoseNet模型并從網(wǎng)絡(luò)攝像頭捕獲視頻
我們將使用ml5.js加載PoseNet。與此同時(shí),p5.js使我們可以用幾行代碼從網(wǎng)絡(luò)攝像頭捕獲視頻:
- let video;
- let poseNet;
- let poses = [];
- function setup() {
- const canvas = createCanvas(640, 480);
- canvas.parent('videoContainer');
- // Video capture
- video = createCapture(VIDEO);
- video.size(width, height);
- // Create a new poseNet method with a single detection
- poseNet = ml5.poseNet(video, modelReady);
- // This sets up an event that fills the global variable "poses"
- // with an array every time new poses are detected
- poseNet.on('pose', function(results) {
- poses = results;
- });
- function modelReady(){
- select('#status').html('model Loaded')
- }
以上代碼塊中最重要的是:
- createCapture(VIDEO):它是一個(gè)p5.js函數(shù),用于通過(guò)攝像頭捕獲視頻來(lái)創(chuàng)建視頻元素。
- ml5.poseNet(video,modelRead):我們使用ml5.js加載poseNet模式。通過(guò)傳入視頻,我們告訴模型處理視頻輸入。
- PoseNet.on():每當(dāng)檢測(cè)到一個(gè)新的姿勢(shì)時(shí),就執(zhí)行這個(gè)函數(shù)。
- modelReady():當(dāng)PoseNet完成加載時(shí),我們調(diào)用這個(gè)函數(shù)來(lái)顯示模型的狀態(tài)。
步驟2:檢測(cè)身體關(guān)節(jié)的關(guān)鍵點(diǎn)
下一步是檢測(cè)姿勢(shì)。你可能已經(jīng)注意到,在前面的步驟中,我們通過(guò)調(diào)用poseNet.on()將每個(gè)檢測(cè)到的位姿保存到pose變量中。這個(gè)函數(shù)在后臺(tái)連續(xù)運(yùn)行。無(wú)論何時(shí)找到一個(gè)新的姿勢(shì),它都會(huì)以以下格式給出身體關(guān)節(jié)的位置:
- 'score'是指模型的置信度
- 'part'表示檢測(cè)到的身體關(guān)節(jié)/關(guān)鍵點(diǎn)
- 'position'包含檢測(cè)到的部分的x和y位置
我們不必為此部分編寫(xiě)代碼,因?yàn)樗亲詣?dòng)生成的。
步驟3:顯示檢測(cè)到的人體關(guān)節(jié)
我們知道被檢測(cè)到的人體關(guān)節(jié)及其x和y位置?,F(xiàn)在,我們只需要在視頻上畫(huà)出它們來(lái)顯示檢測(cè)到的人體關(guān)節(jié)。我們已經(jīng)看到,PoseNet給出了一個(gè)檢測(cè)到的人體關(guān)節(jié)列表,每個(gè)關(guān)節(jié)及其x和y位置的置信度評(píng)分。
我們將使用20%的閾值(keypoint.score > 0.2)置信度得分,以便繪制一個(gè)關(guān)鍵點(diǎn)。下面是實(shí)現(xiàn)這一操作的代碼:
- // A function to draw ellipses over the detected keypoints
- function drawKeypoints() {
- // Loop through all the poses detected
- for (let i = 0; i < poses.length; i++) {
- // For each pose detected, loop through all the keypoints
- let pose = poses[i].pose;
- for (let j = 0; j < pose.keypoints.length; j++) {
- // A keypoint is an object describing a body part (like rightArm or leftShoulder)
- let keypoint = pose.keypoints[j];
- // Only draw an ellipse is the pose probability is bigger than 0.2
- if (keypoint.score > 0.2) {
- fill(255, 0, 0);
- noStroke();
- ellipse(keypoint.position.x, keypoint.position.y, 10, 10);
- }
- }
- }
- }
步驟4:繪制估計(jì)的身體骨架
除了關(guān)鍵點(diǎn)或身體關(guān)節(jié),PoseNet還可以檢測(cè)估計(jì)的身體骨架。我們可以使用pose變量來(lái)繪制骨架:
- // A function to draw the skeletons
- function drawSkeleton() {
- // Loop through all the skeletons detected
- for (let i = 0; i < poses.length; i++) {
- let skeleton = poses[i].skeleton;
- // For every skeleton, loop through all body connections
- for (let j = 0; j < skeleton.length; j++) {
- let partA = skeleton[j][0];
- let partB = skeleton[j][1];
- stroke(255, 0, 0);
- line(partA.position.x, partA.position.y, partB.position.x, partB.position.y);
- }
- }
- }
在這里,我們遍歷檢測(cè)到的骨架并創(chuàng)建連接關(guān)鍵點(diǎn)的線。代碼還是相當(dāng)簡(jiǎn)單。
現(xiàn)在,最后一步是重復(fù)調(diào)用drawSkeleton()和drawKeypoints()函數(shù),以及我們從網(wǎng)絡(luò)攝像頭捕獲的視頻源。我們可以使用p5.js的draw()函數(shù)來(lái)實(shí)現(xiàn),該函數(shù)在setup()之后直接調(diào)用,并重復(fù)執(zhí)行:
- function draw() {
- image(video, 0, 0, width, height);
- // We can call both functions to draw all keypoints and the skeletons
- drawKeypoints();
- drawSkeleton();
- }
接下來(lái),轉(zhuǎn)到終端窗口,進(jìn)入項(xiàng)目文件夾,然后啟動(dòng)Python服務(wù)器:
- python3 -m http.server
然后轉(zhuǎn)到你的瀏覽器并打開(kāi)以下地址:
- http://localhost:8000/
瞧!你的PoseNet應(yīng)該很好地檢測(cè)到了你的身體姿勢(shì)(如果你已經(jīng)正確地遵循了所有步驟)。以下是我的模型的情況:
尾記
你可以看到我為什么喜歡TensorFlow.js。它非常有效率,甚至不需要你在構(gòu)建模型時(shí)擔(dān)心復(fù)雜的安裝步驟。
TensorFlow.js展示了通過(guò)將機(jī)器學(xué)習(xí)帶到瀏覽器中使機(jī)器學(xué)習(xí)更容易訪問(wèn)的許多前景。同時(shí),它還具有數(shù)據(jù)隱私、交互性等優(yōu)點(diǎn)。這種組合使得它成為數(shù)據(jù)科學(xué)家工具箱中的一個(gè)非常強(qiáng)大的工具,特別是如果你想部署你的機(jī)器學(xué)習(xí)應(yīng)用程序的話。
在下一篇文章中,我們將探討如何在瀏覽器中應(yīng)用遷移學(xué)習(xí),并使用TensorFlow.js部署機(jī)器學(xué)習(xí)或深度學(xué)習(xí)模型。
我們用PoseNet做的項(xiàng)目可以更進(jìn)一步,通過(guò)訓(xùn)練另一個(gè)分類(lèi)器來(lái)構(gòu)建一個(gè)姿態(tài)識(shí)別應(yīng)用程序。我鼓勵(lì)你去嘗試一下!