Hatena::ブログ(Diary)

遙かへのスピードランナー RSSフィード

Firefoxを簡単に携帯シミュレータにするアドオン「FireMobileSimulator」公開中です!
PHP×携帯サイト デベロッパーズバイブル
モバイル開発者必携!
Firefox利用者必携!
Firefox 3 Hacks Mozillaテクノロジ徹底活用テクニック

2011-06-19

Windows VistaでKinect SDKを動かす方法

先日ついにMicrosoft公式のKinectSDKが発表されましたね!

さっそく試してみたかったのですが、KinectSDKはWindows7のみサポート、そして僕の持っているのはWindowsVistaのみ・・・。

ということで何とかWindowsVistaで動かせないものかと頑張ってみました。

で、結論から言うと、

  • 深度センサー・モーションセンサーの部分はVistaでも動かすことが可能
  • 音声入力認識の部分はVistaでは動かせなかった

という結果になります

サンプルプログラムで言うと、SkeletalViewerはまったく問題なく動きます。ShapeGameは音声入力の機能以外は動きます

もうちょっと頑張れば音声の部分も動かせるかもしれませんが、セットアップにそこまで時間をかける気力もなく、僕は諦めてWindows7を買ってしまいましたが、一応記録として方法を記しておきます。以下32ビット版での手順ですので、64ビット場合ファイル名を読み替えてください。

手順1:msiファイルを展開する

KinectSDKのインストーラーKinectSDK32.msiを好きな場所にダウンロードします

http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/download.aspx

そのあとコマンドプロンプトを立ち上げて、ダウンロードした場所まで移動し、以下のコマンドを発行します

C:\Kinect\SDK\Directory> msiexec /a KinectSDK32.msi targetdir="C:\temp"

ここでtargetdirには展開したい場所を指定します。どこでもいいのですが、ここではC:\tempを指定しています

このコマンドを実行すると以下のように5つのファイル・フォルダがtargetdirに展開されます

f:id:thorikawa:20110619185808j:image

手順2:フォルダの移動とパスの設定

手順1でできたPFilesX86フォルダを、C:\Program Files\Microsoft Research KinectSDKのパス名前を変えて移動します

移動が完了したら、環境変数のPathに「C:\Program Files\Microsoft Research KinectSDK」を追加します

f:id:thorikawa:20110619190001j:image

手順3:ドライバのインストール

Kinectを接続するとドライバのインストールが求められますので、「ドライバの場所を指定する」を選択して、「C:\Program Files\Microsoft Research KinectSDK\Drivers」を指定します自動的に必要なドライバがインストールされます

ドライバのインストール後、再起動が必要です。

完了

これだけで完了です!

C:\Program Files\Microsoft Research KinectSDK\SkeletalViewer.exe

C:\Program Files\Microsoft Research KinectSDK\ShapeGame.exe

クリックすると以下のように動くことが確認できると思います

f:id:thorikawa:20110619190133p:image

追伸

音声入力認識部分をVistaで動かすことができた方はご連絡下さいませ。

2011-06-12

AndroidとOpenCVで試す特定物体認識

6月2日に開催されたDevLOVEさんと弊社の共同開催勉強会で、「Android×ComputerVision」というお題で発表してきました。

要はOpenCVをAndroidアプリに組み込んで特定物体認識を試そう、というもの。

資料は以下です。

ソースはgithubで公開してます

https://github.com/thorikawa/AndroidObjectRecognition/

概要

資料にも記載していますが、カメラのプレビュー画像からSURFの特徴点を検出して、LSHで再近傍検索→特定物体認識というのを毎フレーム行っています

「物体」はCDのジャケット画像を5枚の内から認識して、それぞれの画像にあった音を鳴らす、というデモを行い、うまく認識することができました。

構成・ビルド方法

チェックアウト後のソースは

  1. OpenCVをAndroidから利用しやすくするためのOpenCVプロジェクト(android-jni以下)
  2. アプリのプロジェクト(apps/ObjectRecognition以下)
  3. 検出対象の画像から特徴点を検出しておくユーティリティ(dump_keypoints.cpp)

の3つから構成されています

上記1番はAndroidライブラリプロジェクトとなっており、2番から参照されているため、Eclipseでビルドする場合は、両プロジェクトをimportしておく必要があります

また、検出対象となる物体の特徴ベクトルはapps/ObjectRecognition/assets/keypoints以下にテキストファイルが配置されています。追加したい場合は、dump_keypointsでダンプした結果をここに追加し、2番のJavaソースで読み込んでいる箇所を修正してみてください。

チェックアウト後のソースには、ビルド後のバイナリも含まれていますが、自分でビルドしたい場合

apps/ObjectRecognition

に移動してantコマンドを実行することでAndroidアプリをビルドすることができます

$ cd ${checkoutdir}/apps/ObjectRecognition
$ ant debug

改変方法

ソースを自分でいじりたい場合、アプリ側のJavaソースだけならチェックアウト後のソースをそのまま変更することができます

c++部分のソースをいじりたい場合は、AndroidをターゲットにしてOpenCVをビルドできる環境が必要です。

まだ環境を構築していない人は、

http://opencv.willowgarage.com/wiki/Android

を参考に環境構築してみてください。

課題考察

SURFの特徴点検出がとにかく遅いです。濃淡の差が細かく激しい画像だと、1回の検出処理に約3sec程かかります

OpenCVは、他にもデフォルトでSTARやFASTなどの特徴点検出アルゴリズムを搭載しており、これらの方がSURFよりも速いのですが、精度のチューニングが間に合わなかったため、SURFで実装しています

実用化に向けては、速度と精度のバランスを取ったチューニングを行う必要があります。(←そりゃそうだ)

また、今回は毎回LSHに突っ込む特徴ベクトルを毎回読み込んでいるため、

  • 特徴ベクトルのデータが膨大
  • 特徴ベクトルの読み込みに時間がかかる

という問題があります

原理的には計算されたハッシュ値だけをデータとして持たせておけば再近傍の計算はできるはずなので、その部分も課題となります

2011-05-23

MacとNexus OneでAndroid Oepn Accessoryを試してみる

先日サンフランシスコで行われたGoogle I/OのKeynoteでは様々な発表がありましたが、その中で、僕が特に面白いと思ったのが「Android Open Accessory」です。

簡単に言うと、Androidデバイスに接続するUSB周辺機器を、誰でも簡単に作ることができる仕組みです。

Google I/Oではこの仕組みを試すための開発ボード「ADK」が無償で配られたり、日本のメーカーからも発売されたりしていますが、電子工作ということで敷居が高いと感じている人も多いんじゃないかと思います

しかし、Android Open Accessoryが適用できるのは、別に電子工作に限った話ではありません。PCとAndroid端末さえあれば、今すぐに試してみることができます。というわけで、早速デモ作ってみたので簡単に解説していきます

用意するもの

  • AndroidOS 2.3.4にアップデートしたNexus One(テストしてないけど、多分Nexus Sでも問題なし)
  • libusb-1.0インストール済みのMac OS搭載PC (テストしてないけど、その他のUNIX系OSでも動く可能性あり)

今回作るものの概要

Mac PCにUSBで接続されたNexus One上のAndroidアプリと、Mac PC上の実行ファイルとの間で、USBポートを介してデータの通信を行います

ただ単にデータ通信するだけでは面白くないので、KeyNoteのデモのように、端末の動きをゲームに反映させてみます

アーキテクチャは以下の図のような感じで、Androidの傾きセンサーやボタンクリックを検出して、その値をUSBを介して通信し、最終的にJavaScriptで作ったゲームに端末の傾きの値を反映させたり、アプリのボタンクリックするとボールが追加されるようにします

JavaScriptのゲームはBox2DJSデモをちょこっと改造した力学演算系のゲームです。

f:id:thorikawa:20110522211016p:image

実際に動かしてみるとこんな感じになります

f:id:thorikawa:20110522211739j:image:w280:left

f:id:thorikawa:20110522211723j:image:w280

ソース全体

github: https://github.com/thorikawa/android-openaccessory-with-pc-sample

にアップロードしています

アプリ側のソース

android-app-usbフォルダがアプリ側のソースとなっています

基本的には、USB Accessory | Android Developersに記載されている内容に準拠します

AndroidManifestの記述

USB周辺機器(今回はPC)が端末に接続されたイベントを捕捉できるように、AndroidManifestにIntent-Filterを記述ます

<activity android:name=".Top" android:label="@string/app_name"
  <intent-filter>
    <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
  </intent-filter>
  <meta-data android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" android:resource="@xml/accessory_filter" />
</activity>

meta-dataのresourceにxmlファイルを指定していますが、これは別途作成ます

filtering用のxmlファイル作成

/res/xml以下に、上記Intent-Filterのmeta-dataに指定したaccessory_filter.xmlを作成ます

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <usb-accessory manufacturer="Poly's Factory" model="Android Oepn Accessory Demo" version="1.0" />
</resources>

ここで指定するManufacturer・Model・Versionによって、Activityが扱えるUSB Accessoryがフィルタリングされます。後で解説するPC側のプログラムでも、同じ値を指定します

Activity作成

Activity側では、接続されたUSB Accessoryと通信するために、2通りの方法でUSB Accessoryオブジェクトを取得できます

1.Intentから取得する場合

USB機器接続時のIntentからActivityが呼び出された場合、IntentからUSB Accessoryoオブジェクトを取得することができます

  Intent intent = getIntent();
  if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(intent.getAction())) {
    mUsbAccessory = UsbManager.getAccessory(intent);
  }

2.任意のタイミングで取得する場合

USB機器接続後に、任意のタイミングでUSB Accessoryオブジェクトを取得することもできます

  mUsbManager = UsbManager.getInstance(this);
  UsbAccessory[] accessoryList = mUsbManager.getAccessoryList();
  for (UsbAccessory usbAccessory : accessoryList) {
    // 条件に合致するusbAccessoryを選択
    ....
  }

USB Accessory取得後はUsbManager.openAccessory()で、ParcelFileDescriptorを取得することで、普通ファイルストリームと同じように扱うことができます

  ParcelFileDescriptor pfd = mUsbManager.openAccessory(mUsbAccessory);
  FileDescriptor fd = pfd.getFileDescriptor();
  FileInputStream fis = new FileInputStream(fd);
  FileOutputStream fos = new FileOutputStream(fd);
  fos.write(....);

実際のデモプログラムの中では、傾きセンサーで取得された値と、ボール追加ボタンが押されたかどうかを、バイト列にしてFileOutputStreamに出力しています

PC側のソース

pc-usb.cがPC側のソースになっています。libusbとリンクする必要があるので "gcc -lusb-1.0 pc-usb.c" などでビルドして下さい。

PC側では、Android Open Accessory専用のプロトコルである、Android accessory protocolで通信を行う必要があります

プロトコルの内容は、Android Open Accessory Development Kit | Android Developersを見ればわかりますが、Using Android in Industrial Automation » Turn your Linux computer into a huge Android USB Accessoryの記事で、Cとlibusbを使ったサンプルソースを公開している方がいらっしゃるので、ここではそれを参考にしてプログラムを書いてみます

Android端末との接続

まず、USBで繋がっているAndroid端末の接続ハンドルを取得します

#define VID 0x18D1
#define PID 0x4E12

libusb_init(NULL);
libusb_device_handle* handle = libusb_open_device_with_vid_pid(NULL, VID, PID);

ここでVendorIDとProductIDを指定して、ハンドルオープンしていますが、このIDは機種ごとに異なり、また同じ端末でも、USBデバッグモードとそうでない時で異なるので注意してください。

上記のIDはNexus Oneのデバッグモードで指定するIDです。

VendorID・ProductIDは、Mac OSであれば

/Developer/Applications/Utilities/USB Prober.app/Contents/MacOS/USB Prober

などを使って簡単に調べることができます

Accessory Modeのset up

次に、Android端末はそのままではAccessoryと通信を行うモードになっていないので、モードを変更します

Attempt to start the device in accessory modeに記載されている通信を、libusbを介して行います

手順は、(1)端末がAndroid accessory protocolに対応しているかどうかの判定 (2)Accessory Identificationの送信 (3)端末をAccessory modeに変更 です。

(1)端末がAndroid accessory protocolに対応しているかどうかの判定

libusb_control_transfer(handle,0xC0,51,0,0,ioBuffer,2,0);

ioBufferにサポートするaccessory protocolのバージョンが返り、この値が0以外ならば端末がaccessory protocolをサポートしていると判断します。(現在サポートしている場合のバージョンは"1"のみ存在する)

(2)Accessory Identificationの送信

libusb_control_transfer(handle,0x40,52,0,0,(char*)manufacturer,strlen(manufacturer),0);
libusb_control_transfer(handle,0x40,52,0,1,(char*)modelName,strlen(modelName)+1,0);
libusb_control_transfer(handle,0x40,52,0,2,(char*)description,strlen(description)+1,0);
libusb_control_transfer(handle,0x40,52,0,3,(char*)version,strlen(version)+1,0);
libusb_control_transfer(handle,0x40,52,0,4,(char*)uri,strlen(uri)+1,0);
libusb_control_transfer(handle,0x40,52,0,5,(char*)serialNumber,strlen(serialNumber)+1,0);

この命令によって、USB機器を識別するためのManifactorer・Model・Versionなどの情報が端末に送信されます。accessory_filter.xmlに記載されたフィルタリング情報は、ここで送信された値と一致するかで判定します

(3)端末をAccessory modeに変更

libusb_control_transfer(handle,0x40,53,0,0,NULL,0,0);
Accessory Modeでのデータ送受信

以上で端末がAccessory Modeに変更されました。

このタイミングで端末のProduct IDが変更されるので

libusb_close(handle);

によって、Accessory Mode変更前の接続ハンドルをクローズし、

#define ACCESSORY_PID 0x2D01
handle = libusb_open_device_with_vid_pid(NULL, VID, ACCESSORY_PID)

によって、新しいAccessory ModeのPIDで接続ハンドルを作り直します

ここまで行えば、後はlibusb_bulk_transfer関数を通じて、端末とバイトストリームをやりとりすることができます

#define IN 0x83
#define OUT 0x03
#define BUFFER 1024

unsigned char buffer[BUFFER];
static int transferred;
while (libusb_bulk_transfer(handle, IN, buffer, BUFFER, &transferred, 0) == 0) {
  ...
}

ここで定数INとOUTは、それぞれAndroid側のUSBインターフェースを識別する値で、これも端末ごとに異なっています。今回はNexusOneの値を採用しています

他の端末の場合、ProductIDと同じようにUSB Proberなどで確認してください。

PCプログラムではここで読み込んだ値を、JavaScriptからも読み込めるように、一旦テキストファイルに書きだしています

JavaScriptゲーム側

box2d-with-usbフォルダ以下が、ブラウザで実行するJavaScriptゲームのソースになっています

詳細は省きますが、PCプログラムテキストファイルに書きだした取得された傾きセンサーの値と、ボールが追加されたかどうかのフラグを参照して、それに応じた力学アニメーションを行うようになっています

まとめ

Android Open Accessoryは「オリジナルな周辺機器自分で作れる」という面に目が行きがちですが、PCとAndroid端末でも簡単に通信できるよ!ということでサンプルの解説をしてみました。

電子工作が苦手な人でも、USB通信の中身を完全に自作できる、と考えると夢が広がるのではないでしょうか!

2011-02-19

CV最先端ガイド勉強会でSVMについて発表してきました

本日開催された第9回「コンピュータビジョン最先端ガイド」勉強会@関東でSVMの章を発表してきました。

SVMはPRML読書会でも発表しているので、資料は半分くらい流用です。悪しからず。

SVMをちゃんと勉強しようと思うと、双対定理から二次計画問題、カーネル法などかなり幅広い知識が必要で、2回目の発表でも、自分自身勉強不足を痛感させられます。今回は特に、ラグランジュ未定定数法と双対定理については、内容を諳んじれるように頭に叩き込むようにしました。未だに参考書がないと内容が出てこないので。またlibsvmなどのライブラリを自分でも使い始めたので、パラメータとSVMの汎化性能については身を持って知ることができた点は良かったと思っています

勉強会では、特にカーネルの選び方について、参加者の間でも熱い議論が交わされました。僕は資料に「ガウスカーネルだけで問題ないでしょ?」的なことを書いていたんですが、僕の前の発表でその説は叩きのめされ、僕も考えを改めることになりました。

たとえば、第3章6節には、畳み込みカーネルという(実数ベクトル以外の)構造データに対するカーネルの例が上げられています。このような例を見たのは初めてで、なるほどガウスカーネル以外のカーネル重要なのだなあと実感することができました。

また、実数ベクトルではガウスカーネルが使われることが多いと思うのですが、多項式カーネルの方が綺麗に線形分離できるケースもあるだろうという意見もありました。まあそういうケースもあるかもしれない、とは思うのですが、いまいち実例が思いつきません。例えば、スイスロールを例に上げると、ちょうどスイスロール上の境界線で線形分離できるようなカーネルを見つける、みたいなイメージでしょうか。このあたりも今後実践経験で学んでいければよいな、と思います

2010-11-30

Androidアプリで使える便利なUIライブラリ

Androidアプリと言えばUI命!、ということでギークな方々が作られている便利なUIライブラリを見つけられる限り、スクリーンショット付きでまとめてみます

皆様いずれもソースと一部サンプルアプリを公開されているのですぐにでも試してみることができます

(作者の方々、載せることに問題があるようでしたらお手数ですがご一報くださいませ)

Quick Action

  • 公式Twitterアプリ風にタッチした箇所に吹き出しを表示できる
  • レイアウトもカスタマイズ可能

Y.A.M の 雑記帳: Android Quick Action の Android ライブラリプロジェクトを作ってみた

f:id:thorikawa:20101130005022p:image

Drag and Drop ListView

  • ドラッグアンドドロップで並び替え可能なリストビュー
  • 似たようなのは色々あるけどこれが一番使いやすかった!

ユーザがソート可能なListViewをすこしリッチにしてみた - 明日の鍵

f:id:thorikawa:20101130005750p:image

Calendar

  • ビュー上で祝日を判定・表示可能なカレンダービュー
  • 上下左右のフリックで月を切り替えることもできるので、フリック操作を実現したい人はその部分だけでも参考になるかも

CalendarView 公開しました - Kazzzの日記

f:id:Kazzz:20101112133610p:image

3D ListView

  • 3Dで回転しながらスクロールするリストビュー
  • 個人的には大好きなんですが、使い所が思いつかないw

Android Tutorial: Making your own 3D list – Part 3 (final part) | Developer World

f:id:thorikawa:20101130005020p:image

CoverFlow

Interfuser: Android Coverflow Widget V2

f:id:thorikawa:20101130005019p:image

ChartLibrary

afreechart - Project Hosting on Google Code

f:id:thorikawa:20101130005446p:image:left

f:id:thorikawa:20101130005447p:image:left

f:id:thorikawa:20101130005540p:image

Zoomable ImageView

  • 長押しすると、タッチでズームイン・ズームアウトできるようになるImageView
  • 画像が画面より大きくなると表示箇所を移動できるようになる
  • 移動時に淵までいくとバウンドするアニメーション付き

Android one finger zoom tutorial – Part 4 | Developer World

Drag and Drop ImageView

  • 画像ドラッグアンドドロップしてボタンをたたく
  • 下のスクリーンショットだと分からないですが、画像をドロップしたときに回転するのです。そのアニメーションが素敵

Androidでドラッグ・アンド・ドロップ - hidecheckの日記

f:id:thorikawa:20101130010017p:image

NumberPicker

  • インクリメント・デクリメントの間隔を調整可能な数値ピッカー

カスタムNumberPickerの作成 - にゃんだふる日記

f:id:thorikawa:20101130084357p:image

Color Picker

Androidでカラーピッカーを作ろう - 明日の鍵

f:id:thorikawa:20101130005917p:image


Color Picker(11/30追記)

Y.A.M の 雑記帳: Android ColorPickerDialog を作った

f:id:thorikawa:20101130233733p:image

Vertical Slider(11/30追記)

Vertical Seekbar - Android Developers | Google グループ

f:id:thorikawa:20101130233734p:image

他にも

こんな便利なのあるよ!っていうのがあったら教えてください!