こんにちは。
GMOアドマーケティング、16新卒エンジニアのT.Iです。
今年4月に入社し、配属後の7月からは主にRuby on Railsを使った開発を行っていますが、学生の頃は画像処理プログラミングを行っていたため、今回はこれまでの経験を活かしてRubyとOpenCVを活用した基本的な画像処理プログラミングを紹介致します。
OpenCVとは?
OpenCV(Open Source Computer Vision Library)は1998年にIntelが開発を始め、その後Willow GarageやItseezに開発が引き継がれている無償のオープンソース映像/画像処理ライブラリ集。
BSDライセンスで配布されており、クロスプラットフォーム指向で設計されていることから画像処理の分野で幅広く利用されています。
OpenCVはC++やPythonなどをサポート言語としていますが、その人気から様々なバインディングが世界中で開発されています。
今回はその一つである「ruby-opencv」を使ったOpenCVによる画像処理を紹介致します。
OpenCVのインストール(OS X El Capitan)
早速OpenCVをインストールしてみましょう。
OpenCV公式ページからインストールすることも可能ですが、今回はhomebrewでインストールを行いました。
1 2 3 4 |
$ brew update $ brew install -v cmake $ brew tap homebrew/science $ brew install opencv |
次にPython用のOpenCVライブラリを読み込むため、それぞれの環境に合わせたパスを任意の場所(~/.bashrc など)に設定します。
1 |
export PYTHONPATH="/usr/local/lib/python2.7/site-packages/:$PYTHONPATH" |
以上でOpenCVの設定は完了です。
問題なくインストールができているかPythonの対話モードで確認してみましょう。
1 2 3 |
$ python >>> import cv2 >>> cv2.__version__ |
ruby-opencvのインストール
RubyでOpenCVを扱うためにruby-opencvをインストールします。
ruby-opencvはGitHubで公開されているため、README.mdを参考に以下のコマンドでインストールしてみましょう。
1 |
$ gem install ruby-opencv -- --with-opencv-dir=/path/to/opencvdir |
以上で準備が整ったので、公開されているリポジトリを参考にいくつかコードを動かしてみましょう。
二値化処理
ruby-opencvの動作確認も兼ねてまずは二値化処理を試してみます。
二値化とは、濃淡のある画像をある閾値を元に白か黒の二階調のみで表現する処理のことをいい、画像処理の世界では特にメジャーな処理の一つです。
今回はテストとして二値化処理に加えて、グレースケール変換とキャニー法によるエッジ検出も行いました。
今回処理の対象とする入力画像は画像処理のサンプル画像としておなじみのlennaの画像を用います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
require 'opencv' include OpenCV #画像を読み込む src_img = CvMat.load('Lenna.bmp') gray_img = src_img.BGR2GRAY bin_img = gray_img.threshold(128, 255, :binary) canny_img = src_img.BGR2GRAY.canny(120,200) GUI::Window.new('src').show(src_img) GUI::Window.new('gray').show(gray_img) GUI::Window.new('bin').show(bin_img) GUI::Window.new('canny').show(canny_img) GUI::wait_key |
上記のコードを実行すると、それぞれ「入力画像」「グレースケール画像」「二値化画像」「エッジ検出」を表す4つのウィンドウが開きます。
入力画像に対してそれぞれの処理が反映されていることを確認できました。
Haar分類器による顔検出
続いてHaar分類器を用いた顔検出を試してみます。
顔検出を行うためにまずはHarr-like特徴ファイルを用意しましょう。
OpenCVをインストールしたディレクトリに学習済みのファイルが用意されているため、今回は「haarcascade_frontalface_alt.xml」という正面顔用の学習ファイルを用いてプログラムを実行します。
1 2 3 4 5 6 7 8 9 10 11 12 |
require 'opencv' include OpenCV data = '学習ファイル(haarcascade_frontalface_alt.xml)を読み込む' detector = CvHaarClassifierCascade::load(data) src_img = CvMat.load("Lenna.bmp") detector.detect_objects(src_img).each do |region| src_img.rectangle!(region.top_left, region.bottom_right, :color => CvColor::Blue, :thickness => 3) end GUI::Window.new('Result').show(src_img) GUI::wait_key |
正しく顔部分が認識できました。
テンプレートマッチング
最後にテンプレートマッチングを試します。
テンプレートマッチングは、その名の通りあらかじめ用意したテンプレート画像が探索対象となる入力画像のどこにあるのかを探す手法の一つです。
今回は以下の入力画像と入力画像からトリミングした猫の画像を用意し、テンプレートマッチングにより猫を探すものとします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
require 'opencv' include OpenCV src_img = CvMat.load('cat_sample.jpg') #探索対象画像 tmp_img = CvMat.load('cat_tmp.jpg') #テンプレート画像 result = src_img.match_template(tmp_img, CV_TM_SQDIFF) pt1 = result.min_max_loc[2] pt2 = CvPoint.new(pt1.x + tmp_img.width, pt1.y + tmp_img.height) result_img = src_img.rectangle(pt1, pt2, :color => CvColor::Black, :thickness => 3) GUI::Window.new('src_img').show(src_img) GUI::Window.new('tmp_img').show(tmp_img) GUI::Window.new('result_img').show(result_img) GUI::wait_key |
問題なく認識することができました。
もちろんこんなこともできます。
さいごに
今回はRubyからOpenCVを動かす方法と、ruby-opencvの基本的な機能を紹介しました。
C++やPythonと比較すると機能は少なくなりますが、環境構築・コードともに非常にシンプルなのでRubyで画像処理をしてみたいという方はぜひ試してみてください。
※ソフトウェアのダウンロードやインストールは自己責任で御願い致します。
参考リンク
https://github.com/ruby-opencv/ruby-opencv
2016卒のWebエンジニア。
採用やマネジメントもやってます。