OpenCV 4.13.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 4.13.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
ブラウザでディープネットワークを実行する方法

前のチュートリアル: YOLO DNN
次のチュートリアル: ディープラーニングのカスタムレイヤー対応

原著者Dmitry Kurtaev
互換性OpenCV >= 3.3.1

はじめに

このチュートリアルでは、OpenCV.js を使ってブラウザ上で直接ディープラーニングモデルを実行する方法を示す。顔検出モデルと顔認識モデルのパイプラインのサンプルを参照する。

顔検出

顔検出ネットワークは BGR 画像を入力として受け取り、顔を含む可能性のあるバウンディングボックスの集合を生成する。必要なのは、信頼度の高いボックスを選択することだけである。

顔認識

このネットワークは OpenFace と呼ばれる(プロジェクト: https://github.com/cmusatyalab/openface)。顔認識モデルはサイズ 96x96 の RGB 顔画像を受け取る。そして入力された顔を多次元単位球面上の点として表す 128 次元の単位ベクトルを返す。したがって、2つの顔の違いは、2つの出力ベクトル間の角度として表される。

サンプル

このサンプル全体は、OpenCV.js の機能を使う JavaScript コードを含む HTML ページである。以下にこのページの埋め込みを表示する。Start ボタンを押すとデモが開始される。Add a person を押すと、未知の人物として認識された人物に名前を付けられる。次に、コードの主要部分を説明する。

  1. 入力画像上の顔を検出するために顔検出ネットワークを実行する。
    function detectFaces(img) {
    netDet.setInputSize(new cv.Size(img.cols, img.rows));
    var out = new cv.Mat();
    netDet.detect(img, out);
    var faces = [];
    for (var i = 0, n = out.data32F.length; i < n; i += 15) {
    var left = out.data32F[i];
    var top = out.data32F[i + 1];
    var right = (out.data32F[i] + out.data32F[i + 2]);
    var bottom = (out.data32F[i + 1] + out.data32F[i + 3]);
    left = Math.min(Math.max(0, left), img.cols - 1);
    top = Math.min(Math.max(0, top), img.rows - 1);
    right = Math.min(Math.max(0, right), img.cols - 1);
    bottom = Math.min(Math.max(0, bottom), img.rows - 1);
    if (left < right && top < bottom) {
    faces.push({
    x: left,
    y: top,
    width: right - left,
    height: bottom - top,
    x1: out.data32F[i + 4] < 0 || out.data32F[i + 4] > img.cols - 1 ? -1 : out.data32F[i + 4],
    y1: out.data32F[i + 5] < 0 || out.data32F[i + 5] > img.rows - 1 ? -1 : out.data32F[i + 5],
    x2: out.data32F[i + 6] < 0 || out.data32F[i + 6] > img.cols - 1 ? -1 : out.data32F[i + 6],
    y2: out.data32F[i + 7] < 0 || out.data32F[i + 7] > img.rows - 1 ? -1 : out.data32F[i + 7],
    x3: out.data32F[i + 8] < 0 || out.data32F[i + 8] > img.cols - 1 ? -1 : out.data32F[i + 8],
    y3: out.data32F[i + 9] < 0 || out.data32F[i + 9] > img.rows - 1 ? -1 : out.data32F[i + 9],
    x4: out.data32F[i + 10] < 0 || out.data32F[i + 10] > img.cols - 1 ? -1 : out.data32F[i + 10],
    y4: out.data32F[i + 11] < 0 || out.data32F[i + 11] > img.rows - 1 ? -1 : out.data32F[i + 11],
    x5: out.data32F[i + 12] < 0 || out.data32F[i + 12] > img.cols - 1 ? -1 : out.data32F[i + 12],
    y5: out.data32F[i + 13] < 0 || out.data32F[i + 13] > img.rows - 1 ? -1 : out.data32F[i + 13],
    confidence: out.data32F[i + 14]
    })
    }
    }
    out.delete();
    return faces;
    };
    入力 blob のサイズを変えて、検出品質と効率のバランスを調整できる。入力 blob が大きいほど、より小さな顔を検出できる。
  2. 入力された顔画像から 128 次元の単位特徴ベクトルを得るために顔認識ネットワークを実行する。
    function face2vec(face) {
    var blob = cv.blobFromImage(face, 1.0, {width: 112, height: 112}, [0, 0, 0, 0], true, false)
    netRecogn.setInput(blob);
    var vec = netRecogn.forward();
    blob.delete();
    return vec;
    };
  3. 認識を実行する。
    function recognize(face) {
    var vec = face2vec(face);
    var bestMatchName = 'unknown';
    var bestMatchScore = 30; // Threshold for face recognition.
    for (name in persons) {
    var personVec = persons[name];
    var score = vec.dot(personVec);
    if (score > bestMatchScore) {
    bestMatchScore = score;
    bestMatchName = name;
    }
    }
    vec.delete();
    return bestMatchName;
    };
    新しい特徴ベクトルを登録済みのものと照合する。最も一致した人物の名前を返す。
  4. メインループ。
    var isRunning = false;
    const FPS = 30; // Target number of frames processed per second.
    function captureFrame() {
    var begin = Date.now();
    cap.read(frame); // Read a frame from camera
    cv.cvtColor(frame, frameBGR, cv.COLOR_RGBA2BGR);
    var faces = detectFaces(frameBGR);
    faces.forEach(function(rect) {
    cv.rectangle(frame, {x: rect.x, y: rect.y}, {x: rect.x + rect.width, y: rect.y + rect.height}, [0, 255, 0, 255]);
    if(rect.x1>0 && rect.y1>0)
    cv.circle(frame, {x: rect.x1, y: rect.y1}, 2, [255, 0, 0, 255], 2)
    if(rect.x2>0 && rect.y2>0)
    cv.circle(frame, {x: rect.x2, y: rect.y2}, 2, [0, 0, 255, 255], 2)
    if(rect.x3>0 && rect.y3>0)
    cv.circle(frame, {x: rect.x3, y: rect.y3}, 2, [0, 255, 0, 255], 2)
    if(rect.x4>0 && rect.y4>0)
    cv.circle(frame, {x: rect.x4, y: rect.y4}, 2, [255, 0, 255, 255], 2)
    if(rect.x5>0 && rect.y5>0)
    cv.circle(frame, {x: rect.x5, y: rect.y5}, 2, [0, 255, 255, 255], 2)
    var face = frameBGR.roi(rect);
    var name = recognize(face);
    cv.putText(frame, name, {x: rect.x, y: rect.y}, cv.FONT_HERSHEY_SIMPLEX, 1.0, [0, 255, 0, 255]);
    });
    cv.imshow(output, frame);
    // Loop this function.
    if (isRunning) {
    var delay = 1000 / FPS - (Date.now() - begin);
    setTimeout(captureFrame, delay);
    }
    };
    アプリケーションのメインループはカメラからフレームを受け取り、フレーム上で検出されたすべての顔について認識を行う。この関数は、OpenCV.js が初期化され、ディープラーニングモデルがダウンロードされたときに一度だけ開始する。