Android x Beagleboard-xM x USBカメラ で OpenCVリアルタイム画像処理 〜AndroidビルドからOpenCVサンプル実行まで〜


香川高専で開かれる「組込みAndroid入門講座」向けの記事です。
http://www.kagawa-nct.ac.jp/newfile/20120201101107_1.html


だれでも自宅でカンタンにできちゃうので情報公開しておきます。

USBCameraつなげたBeagleboard-xMにAndroidOpenCVな記事です。

Step 1. AndroidBeagleboard-xMへ載せる
Step 1-2. Androidが起動するかチェック
Step 2. USBカメラを使うためKernelのコンフィグを変更しリビルド
Step 2-2. KernelをSDへコピーして起動
Step 3. OpenCVデモ実行


準備するもの

  • PC(以下推奨スペック)
  • Beagleboard-xM(現時点でrev.Cで確認)
  • 4GB以上のmicroSD(xM付属のものは読み込みが極端に遅いため、できれば別で用意する。オススメはVerbatim 4G class 6が安くて速度もそこそこ。Panasonic 4G class 4。ちなみにT社製は当たり外れがあるから避けたほうがいい。)
  • USBシリアル変換ケーブル
  • USBマウス
  • USBカメラ(UVC対応のもの。2000円以下のカメラで十分)
  • HDMI-DVIケーブル
  • USBケーブル(オスA-miniB)
  • microSDカードリーダ


以下、作業手順です。



プレゼン資料




Step 0. 準備
※実習のPCではすでに準備が終わっています。「実習ここから」まで飛ばしてください。-----------------


http://software-dl.ti.com/dsps/dsps_public_sw/sdo_tii/TI_Android_DevKit/TI_Android_GingerBread_2_3_4_DevKit_2_1/index_FDS.html
のページから

をPCへダウンロードします。

Step 1. AndroidBeagleboard-xMへ載せる
ダウンロードしたbeagleboard-xm.tar.gzを作業ディレクトリへコピーして展開します。

(作業ディレクトリを作ります)
$ cd
$ mkdir -p Workspace/Android
$ cd Workspace/Android
(作業ディレクトリでtar.gzファイルを展開します)
$ mv ~/Download/beagleboard-xm.tar.gz .
$ tar zxvf beagleboard-xm.tar.gz
$ cd beagleboard-xm


※実習ここから-------
以下引き続きPC上で作業します。



まず、Androidbeagleboardに載せてしまいましょう。



※公式パッケージではUSBカメラの動作確認できなかったため
Androidフレームワークのカメラライブラリを変更し、USBカメラへ対応させたイメージ
beagleboard-xm-custom.tar.gzを用意しました。
実習ではこちらを使ってください。

$ cd ~/Workspace/Android
$ wget http://dl.dropbox.com/u/3858050/beagleboard-xm-custom.tar.gz
$ tar zxvf beagleboard-xm-custom.tar.gz
$ cd beagleboard-xm-custom

wgetのリンク先変更しました。redさん報告thx


展開後にできたmkmmc-android.shを実行するために
microSDのデバイス名をチェックしましょう。
そのためにdmesgコマンドを使います。
dmesgはカーネルログ情報を出力するコマンドです。
microSDをPCへ挿し、dmesgコマンドでデバイス名を確認します。
バイスを認識した直後の情報は一番下の方に出てくるはずです。
sdbやsdcなどが、知りたいデバイス名です。

$ dmesg
...
[98044.552172] sd 3:0:0:0: [sdb] 7839744 512-byte logical blocks: (4.01 GB/3.73 GiB)
[98044.561241] sd 3:0:0:0: [sdb] Write Protect is off
[98044.561246] sd 3:0:0:0: [sdb] Mode Sense: 0b 00 00 08
[98044.567056] sd 3:0:0:0: [sdb] Assuming drive cache: write through
[98044.634095] sd 3:0:0:0: [sdb] Assuming drive cache: write through
[98044.634102] sdb: sdb1 sdb2 sdb3 ※これがデバイス
[98044.715246] sd 3:0:0:0: [sdb] Assuming drive cache: write through
[98044.715253] sd 3:0:0:0: [sdb] Attached SCSI removable disk
[98050.159500] kjournald starting. Commit interval 5 seconds
[98050.441397] EXT3 FS on sdb2, internal journal
[98050.451048] ext3_orphan_cleanup: truncating inode 114468 to 0 bytes
[98050.463773] EXT3-fs: sdb2: 1 truncate cleaned up
[98050.463824] EXT3-fs: recovery complete.
[98050.950728] EXT3-fs: mounted filesystem with ordered data mode.
$

※以降では仮にmicroSDのデバイス名を /dev/sdb として進めます。


次にmkmmc-android.shを実行します。
mkmmc-android.shは事前にビルドされたAndroidイメージをmicroSD上にコピーするスクリプトです。

$ export LANG=C
$ sudo ./mkmmc-android.sh /dev/sdb
Assuming Default Locations for Prebuilt Images
All data on /dev/sdb now will be destroyed! Continue? [y/n]
y (yと入力します)
[Unmounting all existing partitions on the device ]
umount: /dev/sdb: not mounted
[Partitioning /dev/sdb...]
Disk /dev/sdb doesn't contain a valid partition table
DISK SIZE - 4013948928 bytes
CYLINDERS - 488
[Making filesystems...]
[Copying files...]
[Copying START_HERE floder to boot partition]
[Copying all clips to data partition]
[Done]
$


ではAndroidのイメージが正しくmicroSDに書きこまれたか確認してみましょう。
一旦microSDをPCに挿し直して以下のコマンドを実行してください。

$ ls /media/boot
MLO START_HERE boot.scr u-boot.bin uImage
$ ls /media/rootfs
data dev init.goldfish.rc initlogo.rle.bak proc sys ueventd.goldfish.rc
default.prop init init.rc lost+found sbin system ueventd.rc
$ ls /media/data
Audio Images Video
$ sudo umount /media/*


上記で確認できない場合は、マウントディレクトリを作成し、microSDの各パーティションをマウントしてみてください。

(適当なディレクトリを作り、各パーティションをマウント)
$ sudo mkdir /mnt/sd1 /mnt/sd2 /mnt/sd3
$ sudo mount /dev/sdb1 /dev/sd1
$ sudo mount /dev/sdb2 /dev/sd2
$ sudo mount /dev/sdb3 /dev/sd3
(中身確認)
$ ls /mnt/sd1
MLO START_HERE boot.scr u-boot.bin uImage
$ ls /mnt/sd2
data dev init.goldfish.rc initlogo.rle.bak proc sys ueventd.goldfish.rc
default.prop init init.rc lost+found sbin system ueventd.rc
$ ls /mnt/sd3
Audio Images Video


イメージファイルが書きこまれていますね。
では、microSDをPCから抜きますが、抜く前にアンマウントしましょう。

$ sudo umount /mnt/sd*

これで、beagleboard-xMでAndroidを起動させるためのmicroSDができました。
次は、このmicroSDをPCからBeagleboard-xMへ挿し変え、起動確認しましょう。


Step 1-2. Androidが起動するかチェック


Beagleboard-xMへ電源を入れて起動確認しますが
その前にBeagleboard-xMに以下のものが接続されているか確認してください。

  • microSDBeagleboard-xMに挿さっているか?
  • USBマウスがBeagleboard-xMのUSBポートに挿さっているか?
  • HDMI-DVIケーブルでBeagleboard-xMとディスプレイが繋がっているか?
  • USB-シリアル変換ケーブルでPCとbeagleboard-xMが繋がっているか?


では準備が整ったらBeagleboard-xMに電源を入れましょう。


しばらく経った後にAndroidが起動しましたか?
Androidの画面が出てくれば成功です!
マウスでいろいろ操作することができます。


これで第一ステップはクリアです。


さてここで、もしAndroidが起動されない場合や、Androidの状態を知りたいときのために
カーネルログ情報を見れるようにしておきましょう。
beagleboard-xMに電源を入れた直後から出力されるカーネルログ情報は
非常に重要なメッセージが含まれています。
この情報はbeagleboard-xMのDsub9pinからシリアル信号で出力されているため
USB-シリアル変換ケーブルで読み取りましょう。


Linux上でこの情報を見るにはminicomというターミナルソフトを使います。
Windowsで言うTeraTermのようなターミナルソフトです)
minicomの設定について以下説明します。
(Windows上のターミナルソフトを使う場合は以下のminicomの操作は必要ありません)
ボーレートは115200bps、フロー制御なしです。

                                                                                                                                • -

minicom(シリアルターミナル)の設定

                                                                                                                                • -

USB-シリアル変換ケーブルをPCへ繋いでdmesgしてみましょう。

$ dmesg
...
[1249746.782966] usb 1-2.4: pl2303 converter now attached to ttyUSB0
...

このttyUSB?の数字は、後のminicomの設定に使うので覚えておいてください。


ではminicomを起動します。

$ export LANG=C;minicom -s


まずはシリアル設定をします。

"A"をタイプ→Serial Deviceへカーソル移動→"/dev/ttyUSB?"を入力
→"F"をタイプ→Hardware Flow ControlがNo
→Enterキーで戻る


Exitを選択することでターミナルが始まります。

                                                                                                                                • -

minicom の説明ここまで

                                                                                                                                • -

さて、ここで試しにUSBカメラをbeagleboard-xMに挿してみましょう。
カーネルログを見ると、USBとしては認識されてはいるようです。

usb 1-2.4: new high speed USB device using ehci-omap and address 5
usb 1-2.4: New USB device found, idVendor=1871, idProduct=0d01
usb 1-2.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-2.4: Product: USB2.0 Camera
usb 1-2.4: Manufacturer: AVEO Technology Corp.
(カメラ情報ここまで)


しかし、カメラとして認識された場合は以下のようなメッセージが出ます。
UVCというのはUSB Video Classの略で、USBカメラ共通のドライバです。

usb 1-2.4: new high speed USB device using ehci-omap and address 4
usb 1-2.4: New USB device found, idVendor=1871, idProduct=0d01
usb 1-2.4: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-2.4: Product: USB2.0 Camera
usb 1-2.4: Manufacturer: AVEO Technology Corp.
uvcvideo: Found UVC 1.00 device USB2.0 Camera (1871:0d01)
input: USB2.0 Camera as /devices/platform/ehci-omap.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input2


UVCとして認識されないのはLinuxカーネルにドライバモジュールが組み込まれていないためです。
Linuxカーネルにこのドライバモジュールを組み込むためには、
Linuxカーネルのコンフィグレーション作業の後、ビルド作業が必要です。
次はLinuxカーネルのビルド作業に移りましょう。


Step 2. USBカメラを使うためKernelのコンフィグを変更しリビルド


※実習では必要なし---------------------------------------------------------------
PC上の作業へ戻ります。
さきほどダウンロードしてきた TI_Android_GingerBread_2_3_4Sources.tar.gz を作業ディレクトリへ展開します。
また、展開後のディレクトリにはリポジトリしかないので、リポジトリからソースコードをsyncします。

$ cd ~/Workspace/Android
$ tar zxvf TI_Android_GingerBread_2_3_4Sources.tar.gz
$ cd TI_Android_GingerBread_2_3_4Sources
$ ./.repo/repo/repo sync --local-only

※実習では必要なしここまで---------------------------------------------------------------


ツールチェインのパス通してmakeでdefconfigを指定して実行しましょう。
(defconfigはターゲット(ここではbeagleboard)のカーネルコンフィグ情報のデフォルト値が保存されているファイルです。
kernel/arch/arm/config以下にあります。)

$ export PATH=$PATH:`pwd`/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin
$ arm-eabi-gcc -v (パスが通っているかの確認)
Using built-in specs.
Target: arm-eabi
...
gcc version 4.4.3 (GCC)
$ cd kernel
$ make ARCH=arm CROSS_COMPILE=arm-eabi- distclean
$ make ARCH=arm CROSS_COMPILE=arm-eabi- omap3_beagle_android_defconfig


このdefconfigという作業をすると、kernelディレクトリに.configファイルが生成されます。
この.configファイルにはカーネルコンフィグ情報が書かれています。
.configにはこの後ビルドするときに、各ドライバを

といった情報が含まれています。


この時点で.configのUVCに関わるカーネルコンフィグは「組み込まない」設定となっているので
「組み込む」設定へ変更する必要があります。
.config

...
# CONFIG_USB_VIDEO_CLASS is not set
# CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV is not set
...


ということで次に、Linuxカーネルのコンフィグレーション変更作業をしましょう。
(.configを直接変更することは避けてください)
make menuconfigコマンドを使うとKernelコンフィグレーションをグラフィカルに変更できます。

$ make ARCH=arm CROSS_COMPILE=arm-eabi- menuconfig

Device Drivers -> Multimedia Support -> Video capture adapters -> V4L USB devices
にある

  • USB Video Class
    • UVC input events device support

の2つにチェックします。
このとき、チェック欄はではなく<*>となるようにしてください。
チェックを付ける/はずすにはスペースキーを使います。


チェックができたらKernel Configurationから抜けます。
ESCキーを2回押すことでひとつ上の階層へ戻ることができます。
最上位階層でさらに戻るとKernel Configurationから抜けることができます。
そのとき、現状態を保存するかと聞かれるのでYesと応えてください。


さて、これでカーネルビルドの準備ができました。
次はいよいよビルド作業に移ります。


カーネルをビルドするには以下のコマンドを実行します。

(基本的なコマンド)
$ make ARCH=arm CROSS_COMPILE=arm-eabi- uImage

(拡張されたコマンド)
$ time make -j4 ARCH=arm CROSS_COMPILE=arm-eabi- uImage 2>&1 |tee make.log

この作業は重要なので、以下のようなオプションやコマンドと組み合わせてビルドコマンドを拡張させてみましょう。

  • -j オプションを付けることで、カーネルビルドがより早く完了します。-jで指定した数値分スレッドが生成され並列処理されます。スレッド数の目安はコア数の2倍です。
  • timeコマンドを使うことで、ビルド完了時にビルドにかかった時間がわかります。
  • リダイレクションとteeコマンドを使うことでカーネルビルドのログが残ります。


ではビルドコマンドを実行し、終了するのを待ちましょう。
終了すると以下のようなメッセージ後、プロンプトがもどってきます。

...
LD arch/arm/boot/compressed/vmlinux
OBJCOPY arch/arm/boot/zImage
Kernel: arch/arm/boot/zImage is ready
UIMAGE arch/arm/boot/uImage
Image Name: Linux-2.6.37-g06ebbba
Created: Fri Feb 10 10:52:14 2012
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 2770356 Bytes = 2705.43 kB = 2.64 MB
Load Address: 80008000
Entry Point: 80008000
Image arch/arm/boot/uImage is ready
$

メッセージ通り arch/arm/boot に uImage ができているはずです。
実際に見てみましょう。

$ ls arch/arm/boot
Image Makefile bootp compressed install.sh uImage zImage

では、作成したuImageをmicroSDへコピーしましょう。
Beagleboard-xMからmicroSDを抜いて
PCへ挿しなおしてください。


Step 2-2 KernelをmicroSDへコピーして起動


できたKernelをmicroSDへコピーします。

$ sudo mount /dev/sdb1 /mnt/sd1
$ sudo cp arch/arm/boot/uImage /mnt/sd1/uImage
$ sync
$ sudo umount /mnt
$ sync

PCからmicroSDを抜いて
Beagleboard-xMへ挿しなおします。


USBカメラはBeagleboard-xMに挿したままの状態でOKです。
Beagleboard-xMに電源を入れてAndroidを起動させましょう。


起動完了後、Androidプリインストールのカメラアプリを起動してみてください。
USBカメラの映像が映しだされましたか?
映しだされたら成功です!これでカメラの準備ができました。


では、カーネルがどのようなメッセージを出しているか、確認しましょう。
minicomのカーネルログメッセージを見ながら、USBを抜き挿ししてみましょう。
以下のようなログが見れるはずです。

...
usb 1-2.4: new high speed USB device using ehci-omap and address 4
usb 1-2.4: New USB device found, idVendor=046d, idProduct=0990
usb 1-2.4: New USB device strings: Mfr=0, Product=0, SerialNumber=2
usb 1-2.4: SerialNumber: C4D3B54E
uvcvideo: Found UVC 1.00 device (046d:0990)
input: UVC Camera (046d:0990) as /devices/platform/ehci-omap.0/usb1/1-2/1-2.4/1-2.4:1.0/input/input2
...


Step 3. OpenCVデモ実行
さて、いよいよOpenCVライブラリの登場です。
これからOpenCVのサンプルデモを動かして行きますが
実はこれから先の説明はBeagleboard-xMでなくてもカメラの付いているAndroid端末であれば
ほとんどの機種で試せます。
ですので、お手持ちのスマートフォンOpenCVプログラミングを楽しむこともできます。


では、まずはOpenCVライブラリをダウンロードしましょう。

※実習では準備できています-----------------------------
http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.3.1/
にある
OpenCV-2.3.1-android-bin.tar.bz2
をダウンロードして作業ディレクトリで展開しましょう。

$ cd
$ mkdir -p Workspace/OpenCV
$ cd Workspace/OpenCV
$ mv ~/Download/OpenCV-2.3.1-android-bin.tar.bz2 .
$ tar jxvf OpenCV-2.3.1-android-bin.tar.bz2
$ ls

※実習では準備できています(ここまで)-----------------------------


PCのUSBとBeagleboard-xMのmini-B USBを繋いでください。
PC側でBeagleboard-xM上のAndroidが認識されましたか?
確認するためにはadb devicesコマンドを使います。


※認識されていない場合

$ adb devices

$

※認識された場合

$ adb devices
20100720 device

$


では、eclipseを起動してください。
※実習用にandroideclipseを用意しています。
andeclipseで起動させてください。

$ andeclipse &


eclipseが起動したら

  • OpenCV-2.3.1
  • samples/tutorial-1-addopencv

を開きます。


そのためには、まずeclipse
File->importから
Existing Projects into Workspace
を選択して、
OpenCV-2.3.1ディレクトリを選択してください。
同様に
samples/tutorial-1-addopencv
を選択して開きます。


では、プロジェクトの「Tutorial 1 Basic」を選択した状態で
実行してみてください。


Android側でサンプルアプリが立ち上がりましたか?

マウスの中クリックでメニューを出すことができます。
OpenCVに組み込まれている画像処理のサンプルを試すことができます。


では、eclipseに戻ってソースコードを見てみましょう。
このサンプルは非常にシンプルなソースコードになっており
メニューの追加や、画像処理の仕方がわかりやすくなっています。
Tutorial 1 Basicのソースコードを書き換えていろいろと画像処理を試してみましょう。


以上で
組込みAndroidの環境構築からOpenCVのリアルタイム画像処理までの
解説を終わります。
以下、参考になるサイトなどの情報です。


参考サイト:

  • Android Development Kit for Sitara Microprocessors

http://www.ti.com/tool/androidsdk-sitara



参考書籍:

基礎から学ぶ 組み込みAndroid

組み込みAndroid本と言えばコレ。Beagleboard-xM rev.B を使用。



OpenCV 2 Computer Vision Application Programming Cookbook: Over 50 Recipes to Master This Library of Programming Functions for Real-time Computer Vision [ペーパーバック]

サンプルコードが直感的でわかりやすい。