Howto

Armadillo-810でOpenCVを用いた画像処理

インテリジェントカメラ向け組み込みプラットフォームであるArmadillo-810は、カメラモジュールからの入力画像を対象に様々な画像処理を行う事が可能です。
本HowToではOpenCVを用いて簡単な画像処理(グレースケール化、エッジ画像化)を行うサンプルを作成し、Atmark Distに組み込んで実際にArmadillo-810上で画像処理プログラムを動作させるまでの一連の流れをご紹介します。

1. OpenCVとは
2. まずはArmadillo-810上で動作させたい場合
3. 開発環境
4. ソースコードの作成
5. Atmark Distへの組み込み
6. 動作確認

OpenCVとは

OpenCVとはオープンソースのコンピュータビジョン向けライブラリであり、様々な画像処理アルゴリズムが実装されています。
このライブラリを使用する事で、カメラからの入力画像に対して高度な画像処理を比較的容易、かつ短時間で実現する事が可能になります。
一例として、手の形状認識や画像上の特定領域の色判別等がOpenCVを利用して実装可能です。

OpenCVに関するより詳細な情報は以下をご参照下さい。
http://opencv.org/

まずはArmadillo-810上で動作させたい場合

本HowToで最終的に作成されるカーネルイメージ、及びユーザーランドイメージは以下になります。

すぐに画像処理プログラムを動作させたい場合は以下のイメージを使用してArmadillo-810を起動し、動作確認手順に従ってプログラムをご使用下さい。

カーネルイメージlinux.bin.gz
ユーザーランドイメージromfs.img.gz

開発環境

開発環境としてはATDE5を使用します。 ATDE5にはOpenCVのARM向けクロスビルド用ライブラリが含まれており、簡単にクロスコンパイルを行う事が可能です。
本HowToで使用しているユーザーランド、Linuxカーネル、ATDEのバージョンを以下に示します。

ユーザーランドatmark-dist-20130206
Linuxカーネルlinux-3.4-at1
ATDEatde5-amd64-20130211

ソースコードの作成

サンプルのソースコードを以下に示します。 ATDE5上の任意の作業ディレクトリ内でopencv_sampleという名前でディレクトリを作成し、そのディレクトリ直下にsample_convert.cという名前で下記内容のファイルを作成してください。
(本HowToではホームディレクトリ直下にopencv_sampleを作成するものとします。)

#include<stdio.h>
#include<opencv/cv.h>
#include<opencv/highgui.h>

int main(int argc, char **argv)
{
    int i;
    CvCapture *capture;
    IplImage *src_img, *dst_img, *dst_img2;

    //CvCapture構造体の初期化、引数で使用するカメラを指定する。
    capture = cvCreateCameraCapture(atoi(argv[1]));
    //カメラからの入力画素数の設定。
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);
    
    //カメラからのキャプチャが失敗した場合はエラー終了
    for(i=0; i<20 ;i++){
      if((src_img = cvQueryFrame (capture)) == NULL){
        printf("camera_error\n");
        return -1;
      }
    }

    //8bit,1chの画像領域を生成
    dst_img = cvCreateImage(cvGetSize(src_img),IPL_DEPTH_8U,1);
    dst_img2 = cvCreateImage(cvGetSize(src_img),IPL_DEPTH_8U,1);

    //グレースケールへ変換
    cvCvtColor(src_img, dst_img, CV_BGR2GRAY);

    //エッジ画像へ変換
    cvCanny(dst_img, dst_img2, 50.0, 200.0, 3);

    //作成した画像の保存
    cvSaveImage("src_img.bmp", src_img, NULL);
    cvSaveImage("dst_img.bmp", dst_img, NULL);
    cvSaveImage("dst_img2.bmp", dst_img2, NULL);

    //終了処理
    cvReleaseCapture(&capture);
    cvReleaseImage(&dst_img);
    cvReleaseImage(&dst_img2);

    return 0;
}

本サンプルの動作を以下に簡単に説明します。
まずcvCreateCameraCapture関数でArmadillo-810に接続されたカメラを指定し、元となる画像をcvQueryFrame関数により取得します。
(cvCreateCameraCapture関数の引数には使用したいビデオデバイスファイルに対応した番号(/dev/video*以下の数字)を渡します。)

カメラからの画像を取得後、cvCvtColor関数によるグレースケール化、及びcvCanny関数によるエッジ画像化を行い、カメラ取得画像(src_img.bmp)、グレースケール画像(dst_img.bmp)、エッジ画像(dst_img2.bmp)をcvSaveImage関数によってカレントディレクトリに640x480の画像として保存します。
(元となるカメラからの取得画像が極端にコントラストの低い画像であった場合、エッジ抽出が出来ない可能性があります。)

Atmark Distへの組み込み

以下、ATDE5のホームディレクトリ直下にatmark-dist、及びlinuxカーネルのディレクトリが存在するものとし、atmark-dist内からlinuxカーネルのディレクトリへlinux-3.xの名前でシンボリックリンクが張られているものとします。

atmark@atde5:~$ cd atmark-dist-20130206/
atmark@atde5:~/atmark-dist-20130206$ ln -s ../linux-3.4-at1 ./linux-3.x

Atmark Distへの組み込みを実現するため、opencv_sampleディレクトリの直下に、 以下の内容のMakefileを作成して下さい。

EXEC = sample_convert
OBJS = sample_convert.o
LDLIBS := -lopencv_core -lopencv_highgui -lopencv_imgproc -lm

all: $(EXEC)

$(EXEC): $(OBJS)
    $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)

romfs:
    $(ROMFSINST) /usr/bin/$(EXEC)

clean:

なお、OpenCVの機能はlibopencv_coreやlibopencv_objdetect等複数のSharedライブラリに分割されており、リンクさせるべきライブラリは使用するOpenCVの関数によって変わります。
ライブラリとそれに含まれる関数との対応関係を知りたい場合は以下をご参照下さい。
http://docs.opencv.org/

上記Makefileを作成後、まず「Armadillo 実践開発ガイド 第一部」に記載の手順を参考に
~/atmark-dist/vendors/AtmarkTechno/Armadillo-810/を
~/atmark-dist/vendors/AtmarkTechno/Armadillo-810-opencv/へとコピーします。

atmark@atde5:~$ cp -r ~/atmark-dist-20130206/vendors/AtmarkTechno/Armadillo-810/ ~/atmark-dist-20130206/vendors/AtmarkTechno/Armadillo-810-opencv

次に、opencv_sampleディレクトリを~/atmark-dist/vendors/AtmarkTechno/Armadillo-810-opencv/以下へコピーします。

atmark@atde5:~$ cp -r opencv_sample/ ./atmark-dist-20130206/vendors/AtmarkTechno/Armadillo-810-opencv/

その後、~/atmark-dist/vendors/AtmarkTechno/Armadillo-810-opencv/Makefileの以下の記載を

SUBDIR_y =    

次のように変更します。

SUBDIR_y =    opencv_sample/

上記Makefileの変更後、~/atmark-dist/へ移動し、Armadillo-810-opencv用のイメージをビルドします。
~/atmark-dist/image内を見ると、22Mbyte程度のromfs.img.gzが作成されているので、これをArmadillo-810のNOR flashのユーザーランド領域へ書き込む事で、openCVのサンプルが組み込まれたイメージを動作させる事が出来ます。

動作確認

今回のサンプルではカメラから画像を取得していますが、Armadillo-810のデフォルトイメージではUVC-gadgetが動作しているため、カメラからの画像取得時に競合が起こります。 このため、UVC-gadgetの停止が必要になります。起動スクリプトを書き換えるか、以下のようにプロセスをkillする等、必要に応じて対処して下さい。

[armadillo ~]# ps aux |grep uvc-gadget
[armadillo ~]# kill -9 xxxx

UVC-gadgetを停止後、Armadillo-810カメラモジュールのビデオデバイスファイル(/dev/video1)に対応する"1"をsample convertの引数として指定する事でサンプルが実行可能です。

[armadillo ~]# sample_convert 1

サンプルの実行により一連の画像が生成されるので、ftp等でホストPC側にコピーする事で実行結果を確認する事が出来ます。以下は生成された画像の例です。(左上:src_img.bmp、右上:dst_img.bmp、下:dst_img2.bmp)