ラベル OpenCV の投稿を表示しています。 すべての投稿を表示
ラベル OpenCV の投稿を表示しています。 すべての投稿を表示

2017年3月8日水曜日

OpenCV3 でカメラを使って静止画を撮影

概要

わざわざ OpenCV を使う必要が全くないのだが、せっかく Mac にインストールしたので Mac の Web カメラを使って OpenCV3 で静止画 ( 写真 ) を撮ってみました

環境

  • Mac OS X 10.11.3
  • Python 3.5.1
  • Numpy 1.10.4
  • OpenCV 3.1.0

Python スクリプト

Mac 内臓のカメラを起動して静止画を撮影するスクリプトです
OpenCV3 が使える環境があればそのまま実行するだけで使えるはずです

import numpy as np
import cv2
import datetime

print("Start capturing camera")
cap = cv2.VideoCapture(0)
# Default size: 780 x 1280
# cap.set(cv2.CAP_PROP_FRAME_WIDTH, 240)
# cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    # Display the resulting frame
    cv2.imshow('frame', gray)

    if cv2.waitKey(33) & 0xFF == ord('q'):
        break
    elif cv2.waitKey(33) & 0xFF == ord('s'):
        now = datetime.datetime.now()
        filename = now.strftime("%Y%m%d_%H%M%S")
        print(filename)
        cv2.imwrite(filename + '.png', frame)
        img = cv2.imread(filename + '.png')
        # height, width = img.shape[:2]
        # f = open(filename + '_pixels.txt', 'w')
        # f.write(','.join(str(v) for v in img.tolist()))
        # f.close()
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

ポイント説明

実行するとカメラが起動します
カメラのサイズは cap.set(cv2.CAP_PROP_FRAME_WIDTH, 240), cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 240) で指定することができます

カメラは静止画を連続的に映すことで動画にしています
なので cv2.imshow('frame', gray) までの流れは while ループ内に入れる必要があります

cv2.waitKey(33) & 0xFF で入力されるキーを 33ms だけ待ちます
もちろん 33ms 内に入力がない場合は再度、動画を映すために while ループの先頭に戻ります
この 33ms の時間を伸ばすとキー入力の待ち時間は長くなるのですが、逆にその間 cv2.imshow('frame', gray) が呼ばれないためカメラが止まった状態になってしまいます

33ms の間にキー入力がありかつ入力されたキーが q だった場合は終了します
s だった場合に静止画を撮影します
撮影自体は cv2.imwrite(filename + '.png', frame) で行っています
今回はファイル名がかぶらないように日時をファイル名に付与しています

全体の流れは以上です
あとはおまけて画像の情報を取得するロジックをコメントアウトで記載しています

最後に

紹介は以上です
説明書いていて気づいたんですが、カメラを起動した状態でイベント等が発生したら静止画を撮るみたいなことってどうやって実現するんだろうと思いました
うーん、機会があれば挑戦したい

参考サイト

2017年3月7日火曜日

node-opencv で検出した物体の中心を算出する方法

概要

前回 Canny アルゴリズムを使って四角形を検出してみました
今回は検出した Contours (輪郭) の中心点を求める方法を紹介します

環境

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

四角形の中心点を検出するサンプル

スクリプトの全体は以下の通りです

  • vim draw_center.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_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);
          var moments = contours.moments(i);
          var cgx = Math.round(moments.m10 / moments.m00);
          var cgy = Math.round(moments.m01 / moments.m00);
          im.line([cgx - 5, cgy], [cgx + 5, cgy], RED);
          im.line([cgx, cgy - 5], [cgx, cgy + 5], RED);
          console.log("detect rectangle, x: %d, y: d%", cgx, cgy)
      }
    }
    w = new cv.NamedWindow("shapes detect", 1);
    w.show(im);
    w.blockingWaitKey(0, 50);
    detect();
  })
}
detect();
  • node draw_center.js

ポイントは case: 4 で四角形を検出した後に contours.moments を使って Moments の情報を取得しているところです
m00, m01, m10, m11 は空間モーメントを保持しているフィールドでこれを使って中心点を算出することができます

あとは算出した空間モーメントの情報と im.line を使って動画に中心点を描画します

動作確認

実行して四角形のものを近づけると枠線と中心点が描画されているのがわかると思います
opencv_draw_center.png

ターミナルには検出した輪郭の中心点の情報が出力されます

detect rectangle, x: 157, y: d% 122

最後に

検出した四角形の中心点を算出して描画してみました

今回はグレースケールにしないで検出してみました
精度をあげる場合、普通はグレースケールにして影や反射などの影響を抑てください
サンプル用に描画した線がはっきりわかるようにカラーでやってみました

参考サイト

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 力が足りないので今回はこのくらいにしておきます

参考サイト

2017年3月5日日曜日

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

概要

Mac のカメラを使って OpenCV + Nodejs で顔検出をしてみました
公式のサンプルが静止画の顔検出だったので動画でリアルタイムに顔検出してみました

環境

  • Mac OS X 10.10.5
  • OpenCV .2.4.12
  • Nodejs 0.12.0
  • npm 2.5.1

OpenCV のインストール

node-opencv は OpenCV3 にまだ対応していません
今回は OpenCV のバージョン 2 をインストールします

  • brew install pkg-config
  • brew link --overwrite numpy
  • brew install homebrew/science/opencv
  • brew install ffmpeg
  • npm install opencv

とりあえずこれでインストールできました
自分の場合、過去 に OpenCV3 をインストールしていたので若干コマンドが異なる可能性があるかもしれません

顔検出するサンプルスクリプト

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

  • vim face_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 detect = function(){
  s.read(function(err, im){
    if (err) throw err;
    im.detectObject(cv.FACE_CASCADE, {}, function(err, faces){
      console.log("I spy", faces.length, "faces...")
      for (var i = 0; i < faces.length; i++) {
        face = faces[i];
        im.rectangle([face.x, face.y], [face.width, face.height], rectColor, rectThickness);
      }
      w = new cv.NamedWindow("face detect", 1)
      w.show(im)
      w.blockingWaitKey(0, 50);
      detect();
    })
  })
}
detect()
  • node face_detect.js

まず opencv を require して VideoCapture を使ってビデオを使用する準備をします

detect という関数を作成してこれを無限ループさせます
s.read でカメラで撮影している画面を読み込みます
読み込んだら読み込んだオブジェクトを元に im.detectObject で顔検出します

顔が検出できたら顔の分だけ四角で囲います
読み込んでかつ四角で囲った画像を w.show(im) で出力します
これを無限にループすることで動画のようにリアルタイムに顔検出しているように見せています

最後に

実際に実行できると別ウィンドウが立ち上がります
Mac に付属のカメラの画像が表示されているので顔を近づけると四角で囲まれると思います

今回ウィンドウサイズを 320 x 240 にしています
サイズを上げても問題ないですが、かなり動きが重くなるので PC のスペックに合わせて調整してください

とりあえずカメラで顔認識することができました
今度は Mac 内臓のカメラではなく外部のカメラとかを使ってやってみようと思います

参考リンク

2017年3月4日土曜日

Mac (Elcapitan) に OpenCV3 をインストール

概要

Mac (Elcapitan) に OpenCV3 をインストールしてみました
ほぼすべての作業を Homebrew だけで行えます

環境

  • Mac OS X 10.11.3
  • Python 3.5.1
  • Numpy 1.10.4
  • OpenCV 3.1.0

Python3 インストール

Python3 でなければなりません

  • brew install python3

既存の Python2.7 とかがインストールされている場合は python コマンドではなく python3 コマンドを使ってください

$ python3
Python 3.5.1 (default, Mar 29 2016, 19:48:38)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.29)] on darwin
Type “help”, “copyright”, “credits” or “license” for more information.

Numpy インストール

OpenCV3 の動作に Numpy が必要になるのでインストールします
これも Homebrew でインストールできます

  • brew tap homebrew/python
  • brew install numpy --with-python3

Numpy のインストール時に make bootstrap が走るのですがこれに時間がかかります
また、PC のリソース ( 主に CPU ) が非常にかかります
目測ですが、Numpy のインストールが完了するまでに 1 時間ほどかかったような気がします

OpenCV3 インストール

Numpy のインストールが終わったら OpenCV3 をインストールします

  • brew tap homebrew/science
  • brew install opencv3 --with-python3
  • brew link opencv3 --force
$ python3
Python 3.5.1 (default, Mar 29 2016, 19:48:38)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> cv2.__version__
'3.1.0'

こんな感じで Python3 から使えるようになっていればインストール完了です

簡単なサンプル

OpenCV3 の公式サイトにたくさんのサンプルがあるのでとりあえず一番はじめにやるであろう静止画の解析を行うサンプルを動かしてみました

  • vim opencv3_tutorial.py
import numpy as np
import cv2

# Load an color image in grayscale
img = cv2.imread('messi5.jpg', 0)

cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.imwrite('messigray.png', img)
  • wget http://i.stack.imgur.com/CcZCp.jpg -O messi5.jpg
  • python3 opencv_tutorial.py

よくわからないのですが、サンプルがメッシの画像を使っているのでダウンロードしてから動かしてください
サンプルは画像をプレビューで表示して、表示されたグレースケールの画像を PNG 形式で保存するコードになります

Python だとこんな簡単に使えるのか

最後に

Mac に OpenCV3 をインストールしてサンプルを動かすところまでやってみました
せっかくインストールしたので動画解析とか静止画の特徴抽出とか難しいこともやってみたいなと思っています

参考サイト