More Related Content
PPTX
HoloLens2とMeta QuestではじめるWebXR PPTX
AI x WebXR: フェイストラッキングを用いた擬似3D表現を解説! PDF
OpenCV/ARCore/Unityで作る塗り絵AR PPTX
PPTX
PDF
Spresense Study meeting#1 How to use the Camera board PPTX
Depth from Videos in the Wild: Unsupervised Monocular Depth Learning from Unk... PDF
シェーダだけで世界を創る!three.jsによるレイマーチング What's hot
PPTX
AI x WebAR: MediaPipeのハンドトラッキングを使ってみよう PDF
Dockerfile を書くためのベストプラクティス解説編 PDF
3分でわかるAzureでのService Principal PPTX
Oracleからamazon auroraへの移行にむけて PDF
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について ODP
PPTX
【準備編】OculusQuest/HoloLens2対応WebXR開発 PDF
HTMLを書くだけで誰でも簡単!A-FrameではじめるWeb AR/VR PDF
新入社員のための大規模ゲーム開発入門 サーバサイド編 PDF
20200930 AWS Black Belt Online Seminar Amazon Kinesis Video Streams PDF
コンテナの作り方「Dockerは裏方で何をしているのか?」 PDF
Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~ PDF
はじめようARCore:自己位置推定・平面検出・FaceTracking PDF
PPTX
PPTX
SPAセキュリティ入門~PHP Conference Japan 2021 PDF
PPTX
A-Frameで始めるWebXRとハンドトラッキング (HoloLens2/Oculus Quest対応) PDF
PDF
Similar to AI x OpenCV x WebAR: Selfie Segmentationを使ってみよう
PDF
PPTX
AI x WebAR MediaPipeの顔認識を使ってみよう! in 織りなすラボ PPTX
AI x WebAR! MediaPipeの顔認識を使ってみよう! PDF
PDF
segmentation-modelsでざっくり動かすセマンティックセグメンテーション(U-Net) PDF
OpenCVとARCoreで作るスタンプAR in 宮崎 PPTX
OpenCVでつくろうARスタンプアプリ in 熊本 PDF
PDF
PDF
LIFULL HOME'S「かざして検索」リリースの裏側 KEY
PPTX
PDF
2018/12/28 LiDARで取得した道路上点群に対するsemantic segmentation PPTX
Optim インターンシップ 機械学習による画像の領域分割 PDF
論文紹介: Exploiting semantic segmentation to boost reinforcement learning in vid... More from Takashi Yoshinaga
PPTX
ARコンテンツ作成勉強会( #AR_Fukuoka )紹介 PPTX
iPad LiDARでエンジニアカフェを3Dスキャン PPTX
PPTX
PPTX
【準備編!】HoloLens 2/Oculus Quest対応WebXRハンズオン PPTX
Holo-SDKハンズオン:はじめようヘッドトラッキングを用いた3D表現 PPTX
FUKUOKA Engineers Day 2021 発表資料:AR Fukuoka & HoloBox紹介 PPTX
Voxon Photonics VX1で遊んでみた PPTX
PPTX
PPTX
PPTX
iPad LiDARで作ってみた in AR Fukuoka 忘年会2020 PPTX
MRTKで始めるAR開発 (HoloLens 1 and 2, ARCore, ARkit) PPTX
OSC2020 Fukuoka: インストールいらず、WebAR入門 PPTX
Oculus Quest 1&2 開発のはじめの一歩 with A-Frame WebVR PPTX
Spatial Copy & Paste @HoloLensゆるっとLT会 PPTX
エンジニアカフェ1周年イベント:WebAR/VR開発入門 PPTX
ノンプログラミングで始めるAR (HoloLens 2 / ARCore / ARKit) 開発 with MRTK PPTX
[Netlify版] 0から始めようWebAR/VR入門ハンズオン with 織りなすラボ PPTX
[Glitch版] 0から始めようWebAR/VR入門ハンズオン with 織りなすラボ AI x OpenCV x WebAR: Selfie Segmentationを使ってみよう
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
ライブラリ読み込みの解説
<!--① OpenCVの読み込み (SelfieSegmentationのみの利用なら不要)-->
<script src="https://docs.opencv.org/3.4.1/opencv.js"></script>
<!--② カメラをmediapipeで簡単に利用するためのツール-->
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/camera_utils/camera_utils.js"
crossorigin="anonymous"></script>
<!--③ selfie segmentationの読み込み-->
<script src="https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/
selfie_segmentation.js" crossorigin="anonymous"></script>
OpenCV Camera Utils Selfie Segmentation
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
javascriptを用いた初期化
window.onload = function(){
videoElm = document.getElementById('input_video'); //ビデオ要素の取得
canvasElm = document.getElementById('output_canvas'); //表示用のCanvasを取得
canvasCtx = canvasElm.getContext('2d’); //Canvas描画に関する情報にアクセス
//Segmentationを使用するための関連ファイルの取得と初期化
let selfieSegmentation = new SelfieSegmentation({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/${file}`;
}});
//Segmentationで使う学習モデルを選択
selfieSegmentation.setOptions({ modelSelection: 0, });
//Segmentation結果を処理する関数を登録
selfieSegmentation.onResults(onResults);
//カメラの初期化
let camera= new Camera(videoElm, {
onFrame: async () => {
await selfieSegmentation.send({image: videoElm});
},
width: 640, height: 360
});
//カメラ動作開始
camera.start();
};
function onResults(results) {/*Segmentationの結果を利用する*/ };
- 28.
javascriptを用いた初期化
window.onload = function(){
videoElm = document.getElementById('input_video'); //ビデオ要素の取得
canvasElm = document.getElementById('output_canvas'); //表示用のCanvasを取得
canvasCtx = canvasElm.getContext('2d’); //Canvas描画に関する情報にアクセス
//Segmentationを使用するための関連ファイルの取得と初期化
let selfieSegmentation = new SelfieSegmentation({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/${file}`;
}});
//Segmentationで使う学習モデルを選択
selfieSegmentation.setOptions({ modelSelection: 0, });
//Segmentation結果を処理する関数を登録
selfieSegmentation.onResults(onResults);
//カメラの初期化
let camera= new Camera(videoElm, {
onFrame: async () => {
await selfieSegmentation.send({image: videoElm});
},
width: 640, height: 360
});
//カメラ動作開始
camera.start();
};
function onResults(results) {/*Segmentationの結果を利用する*/ };
- 29.
javascriptを用いた初期化
window.onload = function(){
videoElm = document.getElementById('input_video'); //ビデオ要素の取得
canvasElm = document.getElementById('output_canvas'); //表示用のCanvasを取得
canvasCtx = canvasElm.getContext('2d’); //Canvas描画に関する情報にアクセス
//Segmentationを使用するための関連ファイルの取得と初期化
let selfieSegmentation = new SelfieSegmentation({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/${file}`;
}});
//Segmentationで使う学習モデルを選択
selfieSegmentation.setOptions({ modelSelection: 0, });
//Segmentation結果を処理する関数を登録
selfieSegmentation.onResults(onResults);
//カメラの初期化
let camera= new Camera(videoElm, {
onFrame: async () => {
await selfieSegmentation.send({image: videoElm});
},
width: 640, height: 360
});
//カメラ動作開始
camera.start();
};
function onResults(results) {/*Segmentationの結果を利用する*/ };
これの実現に使用
詳細は後ほど実装
- 30.
javascriptを用いた初期化
window.onload = function(){
videoElm = document.getElementById('input_video'); //ビデオ要素の取得
canvasElm = document.getElementById('output_canvas'); //表示用のCanvasを取得
canvasCtx = canvasElm.getContext('2d’); //Canvas描画に関する情報にアクセス
//Segmentationを使用するための関連ファイルの取得と初期化
let selfieSegmentation = new SelfieSegmentation({locateFile: (file) => {
return `https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/${file}`;
}});
//Segmentationで使う学習モデルを選択
selfieSegmentation.setOptions({ modelSelection: 0, });
//Segmentation結果を処理する関数を登録
selfieSegmentation.onResults(onResults);
//カメラの初期化
let camera= new Camera(videoElm, {
onFrame: async () => {
await selfieSegmentation.send({image: videoElm});
},
width: 640, height: 360
});
//カメラ動作開始
camera.start();
};
function onResults(results) {/*Segmentationの結果を利用する*/ };
videoElmの映像を
selfieSegmentationに渡す
画像サイズはあまり大きくない
ように設定(for OpenCV)
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
人物領域にカメラ画像を描画
//canvasのサイズを設定
if(!initialized){
initialized=true;
canvasElm.width=results.image.width*2;
canvasElm.height=results.image.height*2;
}
canvasCtx.save();
//描画内容をクリア
canvasCtx.clearRect(0, 0, canvasElm.width,canvasElm.height);
//マスク画像をcanvasのサイズに引き伸ばして描画
canvasCtx.drawImage(results.segmentationMask, 0, 0,
canvasElm.width, canvasElm.height);
//不透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'source-in’;
//カメラ画像を描画
canvasCtx.drawImage(results.image, 0, 0,
canvasElm.width, canvasElm.height);
canvasCtx.restore();
Lesson04
- 39.
- 40.
背景の塗りつぶし
canvasCtx.save();
//描画内容をクリア
canvasCtx.clearRect(0, 0, canvasElm.width,canvasElm.height);
//マスク画像をcanvasのサイズに引き伸ばして描画
canvasCtx.drawImage(results.segmentationMask, 0, 0,
canvasElm.width, canvasElm.height);
//不透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'source-in';
//カメラ画像を描画
canvasCtx.drawImage(results.image, 0, 0,
canvasElm.width, canvasElm.height);
//透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'destination-atop';
//背景色を緑(#00FF00)に設定し、canvasと同サイズの長方形(Rectangle)を描画
canvasCtx.fillStyle = '#00FF00';
canvasCtx.fillRect(0, 0, canvasElm.width, canvasElm.height);
canvasCtx.restore();
Lesson05
- 41.
- 42.
塗りつぶしとカメラ画像の入れ替え
Lesson06
canvasCtx.save();
//描画内容をクリア
canvasCtx.clearRect(0, 0, canvasElm.width,canvasElm.height);
//マスク画像をcanvasのサイズに引き伸ばして描画
canvasCtx.drawImage(results.segmentationMask, 0, 0,
canvasElm.width, canvasElm.height);
//不透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'source-in';
//カメラ画像を描画
canvasCtx.drawImage(results.image, 0, 0,
canvasElm.width, canvasElm.height);
//透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'destination-atop';
//背景色を緑(#00FF00)に設定し、canvasと同サイズの長方形(Rectangle)を描画
canvasCtx.fillStyle = '#00FF00';
canvasCtx.fillRect(0, 0, canvasElm.width, canvasElm.height);
canvasCtx.restore();
- 43.
塗りつぶしとカメラ画像の入れ替え
Lesson06
canvasCtx.save();
//描画内容をクリア
canvasCtx.clearRect(0, 0, canvasElm.width,canvasElm.height);
//マスク画像をcanvasのサイズに引き伸ばして描画
canvasCtx.drawImage(results.segmentationMask, 0, 0,
canvasElm.width, canvasElm.height);
//不透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'source-in';
//背景色を緑(#00FF00)に設定し、canvasと同サイズの長方形(Rectangle)を描画
canvasCtx.fillStyle = '#00FF00';
canvasCtx.fillRect(0, 0, canvasElm.width, canvasElm.height);
//透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'destination-atop';
//カメラ画像を描画
canvasCtx.drawImage(results.image, 0, 0,
canvasElm.width, canvasElm.height);
canvasCtx.restore();
- 44.
- 45.
- 46.
- 47.
- 48.
変数の追加
let videoElm ;
letcanvasElm;
let canvasCtx;
let cvCanvasElm; //OpenCVで使う画像を表示
let cvCanvasCtx; //cVCanvasElmの描画に関する情報
let initialized=false;
//初期化
window.onload = function() {
//ビデオ要素の取得
videoElm = document.getElementById('input_video');
//表示用のCanvasを取得
canvasElm = document.getElementById('output_canvas');
//Canvas描画に関する情報にアクセス
canvasCtx = canvasElm.getContext('2d');
//opencv処理結果表示用のCanvasと描画に関する情報を取得
cvCanvasElm = document.getElementById('opencv_canvas');
cvCanvasCtx= cvCanvasElm.getContext('2d’);
/*スペーつの都合により省略*/
} Lesson07
- 49.
- 50.
- 51.
- 52.
- 53.
OpenCVの処理結果を表示
function cvFilter(results){
//入力画像をOpenCV用のcanvasに表示
cvCanvasCtx.drawImage(results.image, 0,0);
//cvCanvasElmでの表示画像をOpenCVに渡す(Mat形式)
let src = cv.imread(cvCanvasElm);
//処理結果を格納するMatを作成
let dst = new cv.Mat();
//カラー画像をグレーススケール画像に変換
cv.cvtColor(src, dst, cv.COLOR_RGB2GRAY, 0);
//canvasでの表示のためカラー形式に戻す(見た目はグレーのまま)
cv.cvtColor(dst, dst, cv.COLOR_GRAY2RGBA);
//Matをcanvasで描画できるフォーマットに変換
let imgData = new ImageData(
new Uint8ClampedArray(dst.data, dst.cols, dst.rows),
dst.cols ,dst.rows);
//画像を描画
cvCanvasCtx.putImageData(imgData,0,0);
//Matのメモリを解放
src.delete(); dst.delete();
} Lesson11
- 54.
- 55.
エッジ検出
Lesson12
//入力画像をOpenCV用のcanvasに表示
cvCanvasCtx.drawImage(results.image, 0, 0);
//cvCanvasElmでの表示画像をOpenCVに渡す(Mat形式)
letsrc = cv.imread(cvCanvasElm);
//処理結果を格納するMatを作成
let dst = new cv.Mat();
//カラー画像をグレーススケール画像に変換
cv.cvtColor(src, dst, cv.COLOR_RGB2GRAY, 0);
//Cannyフィルタを用いたエッジ検出
cv.Canny(dst, dst, 50, 90, 3, false);
//canvasでの表示のためカラー形式に戻す(見た目はグレーのまま)
cv.cvtColor(dst, dst, cv.COLOR_GRAY2RGBA);
//Matをcanvasで描画できるフォーマットに変換
let imgData = new ImageData(
new Uint8ClampedArray(dst.data, dst.cols, dst.rows),
dst.cols ,dst.rows);
//画像を描画
cvCanvasCtx.putImageData(imgData,0,0);
//Matのメモリを解放
src.delete(); dst.delete();
- 56.
- 57.
Canny Filter
cv.Canny(source, result,minVal, maxVal, 3, false);
隣のピクセルとの濃淡差
https://docs.opencv.org/3.4.15/d7/de1/tutorial_js_canny.html
隣接ピクセルとの濃淡差をチェックし、ある値(=maxVal)以上ならエッジとみなす。
ただし、少しでも下回ったらエッジと判定されなくなると連続性が低下するので、
隣接するピクセルがエッジと判断され、かつminVal以上なら引き続きエッジとする。
0
255
- 58.
白黒反転
Lesson13
//cvCanvasElmでの表示画像をOpenCVに渡す(Mat形式)
let src =cv.imread(cvCanvasElm);
//処理結果を格納するMatを作成
let dst = new cv.Mat();
//カラー画像をグレーススケール画像に変換
cv.cvtColor(src, dst, cv.COLOR_RGB2GRAY, 0);
//Cannyフィルタを用いたエッジ検出
cv.Canny(dst, dst, 50, 90, 3, false);
//白黒反転
cv.bitwise_not(dst,dst);
//canvasでの表示のためカラー形式に戻す(見た目はグレーのまま)
cv.cvtColor(dst, dst, cv.COLOR_GRAY2RGBA);
//Matをcanvasで描画できるフォーマットに変換
let imgData = new ImageData(
new Uint8ClampedArray(dst.data, dst.cols, dst.rows),
dst.cols ,dst.rows);
//画像を描画
cvCanvasCtx.putImageData(imgData,0,0);
//Matのメモリを解放
src.delete(); dst.delete();
- 59.
- 60.
- 61.
画像処理結果を人物領域に描き込む
function onResults(results) {
if(!initialized){
initialized=true;
canvasElm.width=results.image.width*2;
canvasElm.height=results.image.height*2;
cvCanvasElm.width=results.image.width;
cvCanvasElm.height=results.image.height;
}
cvFilter(results);
canvasCtx.save();
canvasCtx.clearRect(0,0, canvasElm.width, canvasElm.height);
canvasCtx.drawImage(results.segmentationMask, 0, 0,
canvasElm.width, canvasElm.height);
//不透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'source-in';
//canvasCtx.fillStyle = '#00FF00';
//canvasCtx.fillRect(0, 0, canvasElm.width, canvasElm.height);
塗りつぶしに関する2行をコメントアウト
- 62.
結果画像の表示
function onResults(results) {
if(!initialized){
initialized=true;
canvasElm.width=results.image.width*2;
canvasElm.height=results.image.height*2;
cvCanvasElm.width=results.image.width;
cvCanvasElm.height=results.image.height;
}
cvFilter(results);
canvasCtx.save();
canvasCtx.clearRect(0,0, canvasElm.width, canvasElm.height);
canvasCtx.drawImage(results.segmentationMask, 0, 0,
canvasElm.width, canvasElm.height);
//不透明な領域に書き込み許可
canvasCtx.globalCompositeOperation = 'source-in';
//canvasCtx.fillStyle = '#00FF00’;
//canvasCtx.fillRect(0, 0, canvasElm.width, canvasElm.height);
//OpenCV用のcanvasの表示内容を書き込む
canvasCtx.drawImage(cvCanvasElm, 0, 0,
canvasElm.width, canvasElm.height);
Lesson14
- 63.
- 64.
- 65.