2017年3月6日月曜日

node-opencv を使って Mac のカメラで四角形の検出をしてみた

概要

前回 顔検出をやってみました
今回は顔ではなく四角形を検出してみました
OpenCV が動作する環境は前回の記事を参考に構築しておいてください

環境

  • Mac OS X 10.10.5
  • OpenCV .2.4.12
  • Nodejs 0.12.0
  • npm 2.5.1
  • node-opencv 5.0.0

四角形を検出するサンプル

今回作成したサンプルは以下の通りです

  • vim shapes_detect.js
var cv = require('opencv');
var s = new cv.VideoCapture(0);

var camWidth = 320;
var camHeight = 240;
var rectColor = [0, 255, 0];
var rectThickness = 2;
s.setWidth(camWidth);
s.setHeight(camHeight);

var lowThresh = 0;
var highThresh = 100;
var nIters = 2;
var minArea = 2000;

var RED   = [0, 0, 255]; // B, G, R

var detect = function(){
  s.read(function(err, im){
    if (err) throw err;
    width = im.width();
    height = im.height();
    if (width < 1 || height < 1) throw new Error('Image has no size');
    im.convertGrayscale();
    im_canny = im.copy();
    im_canny.canny(lowThresh, highThresh, 3, true);
    im_canny.dilate(nIters);
    contours = im_canny.findContours();
    for (i = 0; i < contours.size(); i++) {
      if (contours.area(i) < minArea) continue;
      var arcLength = contours.arcLength(i, true);
      contours.approxPolyDP(i, 0.02 * arcLength, true);
      switch(contours.cornerCount(i)) {
        case 4:
          im.drawContour(contours, i, RED);
      }
    }
    w = new cv.NamedWindow("shapes detect", 1);
    w.show(im);
    w.blockingWaitKey(0, 50);
    detect();
  })
}
detect();
  • node shapes_detect.js

今回も静止画ではなく動画でリアルタイムに検出しています
まず以下の部分で特徴抽出を行います

im.convertGrayscale();
im_canny = im.copy();
im_canny.canny(lowThresh, highThresh, 3, true);
im_canny.dilate(nIters);
contours = im_canny.findContours();

canny という特徴抽出方式を採用しています
抽出精度を上げるために画像をグレースケールします
canny のパラメータおよび diliate の nIters はいろいろ試してみましたがサンプルの値が一番いい感じに抽出できました
この辺りは実際にデバッグしながら抽出具合を確認するといいと思います
パラメータが決まったら findContours で実際に輪郭抽出します

抽出した輪郭の分だけループします
approxPolyDP で輪郭の抽出精度を決定します
具体的には輪郭の角の丸みをどれくらいまで許すかを設定します
0.02 * arcLength の部分がはじめは 0.01 だったのですが、0.02 の方が期待した四角形を抽出できたので 0.02 に変更しています

switch(contours.cornerCount(i)) で抽出した輪郭の角の数に合わせて画像に線を引きます
今回は角の数が「4」の時だけ線を描画しています
なので例えばここを 3 にすれば三角形を抽出することができますし 5 にすれば五角形を抽出することができます

あとは w.show(im) を使ってリアルタイムに画像を表示しています

実行結果

実際に試すと以下のような感じになります
opencv_detect_shapes_result.png

光の下限や背景によって抽出精度がだいぶ変わります
四角形の部分が影になっていても駄目だし、抽出したい物体と同じ色の背景でもうまく抽出できないことがあると思います

今回のパラメータで実行すれば iPhone6 とかの四角形も検出することができます
approxPolyDP のパラメータを 0.01 -> 0.02 にすることで実現できました

最後に

紹介は以上です
動画でリアルタイムで抽出する場合は背景や光加減が逐一変化するので検出精度にムラがあると思います
もう少しうまくパラメータチューニングできればその辺もうまくできるのかもしれませんが、自分に OpenCV 力が足りないので今回はこのくらいにしておきます

参考サイト

0 件のコメント:

コメントを投稿