ノードの顔検出.さびとwebassemblyのJS
31552 ワード
最後の記事で紹介した.この記事ではノードの書き方を紹介します.サービス応用としてのJSベースAI
AIの今日の支配的なプログラミング言語はPythonです.しかし、Web用のプログラミング言語はJavaScriptです.Web上のサービスとしてAI機能を提供するためには、JavaScript、特にノードにAIアルゴリズムをラップする必要があります.js
しかし、PythonもJavaScript自体も計算集約的なAIアプリケーションに適していません.彼らは高レベル、すなわち、低速、重量のランタイムを持つ言語です.彼らの使いやすさは、低いパフォーマンスのコストで来ます.PythonはネイティブのC/C++モジュールでAI計算をラップすることによってこれを回避しました.ノード.JSは同じことをすることができましたが、より良い方法があります.
WebBassembly VMSはノードとの密な統合を提供します.JSと他のJavaScriptのランタイム.彼らは非常にパフォーマンス、メモリセーフ、デフォルトでセキュア、オペレーティングシステム全体に移植可能です.しかし、我々のアプローチは、webassemblyとネイティブコードの最高の機能を組み合わせたものです.
ノード.サービスアプリケーションとしてのjsベースのaiは3つの部分から成る. ノード.JSアプリケーションはWebサービスを提供し、AI BASICなどの計算集約タスクを実行するためにWebBassembly関数を呼び出します. データの準備、後処理、および他のシステムとの統合は、webassembly関数によって行われます.最初に、我々はさびを支持します.アプリケーション開発者はこの関数を書かなければなりません. AIモデルの実際の実行は、パフォーマンスを最大化するためにネイティブコードによって行われます.コードのこの部分は非常に短く、セキュリティと安全性のために審査されます.アプリケーション開発者はこのネイティブプログラムをwebassembly関数から呼びます-- Pythonとノードでネイティブ関数がどのように使われるかのように.今日の.
今の例を見てみよう!
The face detection web service ユーザーが写真をアップロードすることができます、そして、それは緑の箱でマークされるすべての絵でイメージを表示します.
The Node.js application ファイルのアップロードと応答を処理します.
The
モデルパラメータをどのように渡したかに注目してください
必須条件としては、Rust , Nodeをインストールする必要があります.ジェイピーSecond State WebAssembly VM , とssvmup ツール.Check out the instruction 手順、または単に私たちのDocker画像を使用します.また、あなたのマシンにTensorFlowライブラリを必要とします.
天然さび木枠
実際には、我々のラッパーは、検出された顔の周りのボックスの座標を取得します.モデルは実際に各顔に目、口、鼻の各検出顔と位置の信頼レベルを提供します.モデルの取得テンソル名を変更することで、ラッパーはこの情報を取得し、WASM関数に戻ることができます.
別のモデルを使用したい場合は、例に従って簡単に自分のモデルのラッパーを作成する必要があります.あなただけの入力とテンソル名とそのデータ型の出力を知る必要があります.
この目標を達成するために、我々はプロジェクトと呼ばれるnative model zoo , できるだけ多くのtensorflowモデルのために錆ラッパーを使用する準備を整えること.
本論文では,ノードにおけるサービスユース事例として実世界aiを実装する方法を示した.rustとwebassemblyを使用したjs.我々のアプローチは、より多くのアプリケーション開発者のためのAIライブラリとして機能することができる“モデル動物園”に貢献するために、コミュニティ全体にフレームワークを提供します.
次のチュートリアルでは、画像分類のための別のTensorflowモデルをレビューし、ラッパーを拡張して、類似モデルのクラスをサポートする方法を示します.
AIの今日の支配的なプログラミング言語はPythonです.しかし、Web用のプログラミング言語はJavaScriptです.Web上のサービスとしてAI機能を提供するためには、JavaScript、特にノードにAIアルゴリズムをラップする必要があります.js
しかし、PythonもJavaScript自体も計算集約的なAIアプリケーションに適していません.彼らは高レベル、すなわち、低速、重量のランタイムを持つ言語です.彼らの使いやすさは、低いパフォーマンスのコストで来ます.PythonはネイティブのC/C++モジュールでAI計算をラップすることによってこれを回避しました.ノード.JSは同じことをすることができましたが、より良い方法があります.
WebBassembly VMSはノードとの密な統合を提供します.JSと他のJavaScriptのランタイム.彼らは非常にパフォーマンス、メモリセーフ、デフォルトでセキュア、オペレーティングシステム全体に移植可能です.しかし、我々のアプローチは、webassemblyとネイティブコードの最高の機能を組み合わせたものです.
動作方法
ノード.サービスアプリケーションとしてのjsベースのaiは3つの部分から成る.
今の例を見てみよう!
顔検出例
The face detection web service ユーザーが写真をアップロードすることができます、そして、それは緑の箱でマークされるすべての絵でイメージを表示します.
The Rust source code for executing the MTCNN face detection model is based on Cetra's excellent tutorial: Face Detection with Tensorflow Rust. We made changes to make the Tensorflow library work in WebAssembly.
The Node.js application ファイルのアップロードと応答を処理します.
app.post('/infer', function (req, res) {
let image_file = req.files.image_file;
var result_filename = uuidv4() + ".png";
// Call the infer() function from WebAssembly (SSVM)
var res = infer(req.body.detection_threshold, image_file.data);
fs.writeFileSync("public/" + result_filename, res);
res.send('<img src="' + result_filename + '"/>');
});
ご覧のように、JavaScriptアプリケーションは単にイメージデータとパラメータdetection_threshold
, に指定される最小の顔を指定するinfer()
関数を返します.The infer()
function は錆で書かれ、webassemblyにコンパイルされ、JavaScriptから呼び出すことができます.The
infer()
関数は入力画像データを配列に平坦化する.テンソルフローモデルを設定し、モデルへの入力として平坦化画像データを使用する.TensorFlowモデルの実行は、各フェイスボックスの4つの角の座標を示す数値のセットを返します.The infer()
関数は、各顔の周りに緑色の箱を描画し、それを変更した画像をWebサーバー上のPNGファイルに保存します.#[wasm_bindgen]
pub fn infer(detection_threshold: &str, image_data: &[u8]) -> Vec<u8> {
let mut dt = detection_threshold;
... ...
let mut img = image::load_from_memory(image_data).unwrap();
// Run the tensorflow model using the face_detection_mtcnn native wrapper
let mut cmd = Command::new("face_detection_mtcnn");
// Pass in some arguments
cmd.arg(img.width().to_string())
.arg(img.height().to_string())
.arg(dt);
// The image bytes data is passed in via STDIN
for (_x, _y, rgb) in img.pixels() {
cmd.stdin_u8(rgb[2] as u8)
.stdin_u8(rgb[1] as u8)
.stdin_u8(rgb[0] as u8);
}
let out = cmd.output();
// Draw boxes from the result JSON array
let line = Pixel::from_slice(&[0, 255, 0, 0]);
let stdout_json: Value = from_str(str::from_utf8(&out.stdout).expect("[]")).unwrap();
let stdout_vec = stdout_json.as_array().unwrap();
for i in 0..stdout_vec.len() {
let xy = stdout_vec[i].as_array().unwrap();
let x1: i32 = xy[0].as_f64().unwrap() as i32;
let y1: i32 = xy[1].as_f64().unwrap() as i32;
let x2: i32 = xy[2].as_f64().unwrap() as i32;
let y2: i32 = xy[3].as_f64().unwrap() as i32;
let rect = Rect::at(x1, y1).of_size((x2 - x1) as u32, (y2 - y1) as u32);
draw_hollow_rect_mut(&mut img, rect, *line);
}
let mut buf = Vec::new();
// Write the result image into STDOUT
img.write_to(&mut buf, image::ImageOutputFormat::Png).expect("Unable to write");
return buf;
}
The face_detection_mtcnn
command ネイティブコードでMTCNN tensorflowモデルを実行します.これは、画像幅、画像の高さ、検出しきい値の3つの引数をとります.平坦化されたRGB値として準備された実際の画像データは、webassemblyinfer()
経由STDIN
. モデルからの結果はJSONで符号化され、STDOUT
.モデルパラメータをどのように渡したかに注目してください
detection_threshold
モデルテンソルmin_size
, そしてinput
テンソルは入力画像データを通過する.The box
テンソルを使用してモデルから結果を取得します.fn main() -> Result<(), Box<dyn Error>> {
// Get the arguments passed in from WebAssembly
let args: Vec<String> = env::args().collect();
let img_width: u64 = args[1].parse::<u64>().unwrap();
let img_height: u64 = args[2].parse::<u64>().unwrap();
let detection_threshold: f32 = args[3].parse::<f32>().unwrap();
let mut buffer: Vec<u8> = Vec::new();
let mut flattened: Vec<f32> = Vec::new();
// The image bytes are read from STDIN
io::stdin().read_to_end(&mut buffer)?;
for num in buffer {
flattened.push(num.into());
}
// Load up the graph as a byte array and create a tensorflow graph.
let model = include_bytes!("mtcnn.pb");
let mut graph = Graph::new();
graph.import_graph_def(&*model, &ImportGraphDefOptions::new())?;
let mut args = SessionRunArgs::new();
// The `input` tensor expects BGR pixel data from the input image
let input = Tensor::new(&[img_height, img_width, 3]).with_values(&flattened)?;
args.add_feed(&graph.operation_by_name_required("input")?, 0, &input);
// The `min_size` tensor takes the detection_threshold argument
let min_size = Tensor::new(&[]).with_values(&[detection_threshold])?;
args.add_feed(&graph.operation_by_name_required("min_size")?, 0, &min_size);
// Default input params for the model
let thresholds = Tensor::new(&[3]).with_values(&[0.6f32, 0.7f32, 0.7f32])?;
args.add_feed(&graph.operation_by_name_required("thresholds")?, 0, &thresholds);
let factor = Tensor::new(&[]).with_values(&[0.709f32])?;
args.add_feed(&graph.operation_by_name_required("factor")?, 0, &factor);
// Request the following outputs after the session runs.
let bbox = args.request_fetch(&graph.operation_by_name_required("box")?, 0);
let session = Session::new(&SessionOptions::new(), &graph)?;
session.run(&mut args)?;
// Get the bounding boxes
let bbox_res: Tensor<f32> = args.fetch(bbox)?;
let mut iter = 0;
let mut json_vec: Vec<[f32; 4]> = Vec::new();
while (iter * 4) < bbox_res.len() {
json_vec.push([
bbox_res[4 * iter + 1], // x1
bbox_res[4 * iter], // y1
bbox_res[4 * iter + 3], // x2
bbox_res[4 * iter + 2], // y2
]);
iter += 1;
}
let json_obj = json!(json_vec);
// Return result JSON in STDOUT
println!("{}", json_obj.to_string());
Ok(())
}
私たちの目標は、開発者がライブラリとして使用できるように、一般的なAIモデルのネイティブ実行ラッパーを作成することです.顔検出例の配備
必須条件としては、Rust , Nodeをインストールする必要があります.ジェイピーSecond State WebAssembly VM , とssvmup ツール.Check out the instruction 手順、または単に私たちのDocker画像を使用します.また、あなたのマシンにTensorFlowライブラリを必要とします.
$ wget https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-gpu-linux-x86_64-1.15.0.tar.gz
$ sudo tar -C /usr/ -xzf libtensorflow-gpu-linux-x86_64-1.15.0.tar.gz
フェイス検出の例を配置するには、ネイティブのTensorFlowモデルドライバから開始します.のソースコードからコンパイルすることができますthis project .# in the native_model_zoo/face_detection_mtcnn directory
$ cargo install --path .
次に、web application project . svmupコマンドを実行して、rustからwebassembly関数を構築します.このWebBassembly機能がWebアプリケーションのデータ準備ロジックを実行することを思い出します.# in the nodejs/face_detection_service directory
$ ssvmup build
WebAssembly関数を使用して、ノードを開始することができます.JSアプリケーション.$ npm i express express-fileupload uuid
$ cd node
$ node server.js
Webサービスは現在、あなたのコンピュータのポート8080で利用可能です.独自のselifyや家族やグループの写真を試してみてください!TensorFlowモデル動物園
天然さび木枠
face_detection_mtcnn
テンソルフローライブラリの脆弱なラッパーです.これは、冷凍保存モデルとして知られて訓練されたTensorflowモデルをロードし、モデルの入力を設定し、モデルを実行し、モデルから出力値を取得します.実際には、我々のラッパーは、検出された顔の周りのボックスの座標を取得します.モデルは実際に各顔に目、口、鼻の各検出顔と位置の信頼レベルを提供します.モデルの取得テンソル名を変更することで、ラッパーはこの情報を取得し、WASM関数に戻ることができます.
別のモデルを使用したい場合は、例に従って簡単に自分のモデルのラッパーを作成する必要があります.あなただけの入力とテンソル名とそのデータ型の出力を知る必要があります.
この目標を達成するために、我々はプロジェクトと呼ばれるnative model zoo , できるだけ多くのtensorflowモデルのために錆ラッパーを使用する準備を整えること.
次は何
本論文では,ノードにおけるサービスユース事例として実世界aiを実装する方法を示した.rustとwebassemblyを使用したjs.我々のアプローチは、より多くのアプリケーション開発者のためのAIライブラリとして機能することができる“モデル動物園”に貢献するために、コミュニティ全体にフレームワークを提供します.
次のチュートリアルでは、画像分類のための別のTensorflowモデルをレビューし、ラッパーを拡張して、類似モデルのクラスをサポートする方法を示します.
Reference
この問題について(ノードの顔検出.さびとwebassemblyのJS), 我々は、より多くの情報をここで見つけました https://dev.to/alabulei1/high-performance-and-safe-ai-as-a-service-in-node-js-43lgテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol