2010年12月25日土曜日

[Kinectハック] SD_KinectIO とりあえず公開



[Kinectハック]OpenNI+Flashでマルチユーザー・マルチタッチ」で使っていた
OpenNI解析アプリがexe化できたので、「SD_KinectIO」として公開します
手の情報だけじゃなく、すべてのスケルトン情報を送るように改良しました。
ソケットサーバーの知識さえあれば、これを使って誰でもKinectで遊べますよ。

SD_KinectIO:SD_KinectIO_v0_1.zip
ソケット通信でクライアントにスケルトン情報を送ります。
対応:Window XP 32bitのみ動作確認
[2011/1/6追記]
OpenNIのライセンスがLGPLなので、exeではなくソースを公開します。
OpenNIをインストールして、OpenNI/Samples/に下記のファイルを展開してください。

■ソケット通信仕様
クライアントからは下記に接続します。
IP: 127.0.0.1
TCP Port: 3000


■通信内容
内容はカンマ区切りで送っています。
デリミタはFlashの通信仕様に合わせてNull文字にしています。

"ユーザーID","部位ID","状態","x座標","y座標","z座標" (Null)

(例)
1,1,add,100.223,600.032,1534,302
1,1,update,140.344,632.323,1523,324
1,1,remove,0,0,0

ユーザーID:1~10
部位ID:1~24
状態:add,update,remove

部位の対応リストはこんな感じ。
HEAD   = 1
NECK   = 2
TORSO   = 3
WAIST   = 4
LEFT_COLLAR  = 5
LEFT_SHOULDER  = 6
LEFT_ELBOW  = 7
LEFT_WRIST  = 8
LEFT_HAND  = 9
LEFT_FINGERTIP  =10
RIGHT_COLLAR  =11
RIGHT_SHOULDER  =12
RIGHT_ELBOW  =13
RIGHT_WRIST  =14
RIGHT_HAND  =15
RIGHT_FINGERTIP  =16
LEFT_HIP  =17
LEFT_KNEE  =18
LEFT_ANKLE  =19
LEFT_FOOT  =20
RIGHT_HIP  =21
RIGHT_KNEE  =22
RIGHT_ANKLE  =23
RIGHT_FOOT  =24
 

ただ、OpenNIから値が来ていない部位もあり、
有効な部位だけをまとめるとこんな感じ。


■使い方
[注意] KinectドライバとOpenNIが必要です。
KinectドライバとOpenNIをインストールして下さい。

ダウンロードしたファイルから「SD_KinectIO_.exe」を起動します。

起動すると「クライアント接続」待機状態になります。

ファイアーウォールを有効にしている場合は、セキュリティ警告がでるので、
「ブロックを解除する」を選択します。

クライアント側からSocket通信で上記のIP/ポートに接続します。
接続テストだけならSocketDebuggerがオススメです。

クライアント接続後、しばらくするとカメラウィンドウが開きます。
Kinectの前に立って、手を90度に曲げながら上に上げるとキャリブレーションが始まります。

キャリブレーションが終わるとクライアントへスケルトン情報が送られます。


Flash側の解説はまた今度。

-> [Kinectハック] SD_KinectIOをFlashで受ける

2010年12月21日火曜日

SDLibrary公開しました

Google Codeにて、ブログ編集メンバーで作ったライブラリを公開中です。

SDLibrary
http://code.google.com/p/sd-tech-blog-as3-library/

asdocも書き出していて、リポジトリ上のファイルがそのまま閲覧出来ます。
http://sd-tech-blog-as3-library.googlecode.com/svn/trunk/doc/index.html

今回は2つパッケージを公開していて、

■「osc」パッケージ

oscを用いてCCVやReactivisionとの通信を受け持つライブラリです。
以前のエントリ「自作マルチタッチシステムを作ってみた」でもこのパッケージを使用しています。

■「pointer」パッケージ

Flash上でマルチユーザーマルチタッチを実装するライブラリです。
このライブラリも、「自作マルチタッチシステムを作ってみた」「Kinectハック」で使用しています。

今後も、公開出来そうな物ができたら更新していこうと思います。

[Kinectハック]OpenNI+Flashでマルチユーザー・マルチタッチ Flashで実装編



[Kinectハック]OpenNI+Flashでマルチユーザー・マルチタッチ OpenNI解析編 の続き。


fukusinさんがopenNIのサンプルを解析/改造してくれたおかげで、Kinectの信号をXMLSocketを利用してFlashでも受け取れるようになりました。現時点では各ユーザーの両手のみの検出になっていますが、信号的には頭、首、肩…と、ボーンを表示するのに必要な頂点は全て取れているようです。

さて、今回は「Flashで実装編」として、Kinectから送られてきた信号を解析してFlashに組み込んでいきます。今回のデモでは、各ユーザーの両手が識別できるためマルチタッチのような操作が可能になりますが、正確には「マルチ」ですが「タッチ」ではないですね。空中操作になりますから。「マルチポインタ」と言った所でしょうか。重箱の隅をつつくみたいですが、これ、重要なんです。



この場合、UI的にマルチタッチと全く同じ作法にするのは問題があるのです。タッチ操作であれば画面上のオブジェクトに触れる前にどこに触れるか分かりますが、空中操作、しかもKinectのように画面から離れて操作するものの場合は、実際に手を出してみないとどこにカーソルが表示されるか分かりにくいですよね。

普通タッチパネルでは触った=マウスダウンと同じ操作になり、ロールオーバーとダウン操作を共存させる事が出来ないのですが、前述の理由からKinectの場合はそれが必要になってきます。本家Microsoftは長押しの様な動作で決定(ダウン)操作としていますが、幸いにしてKinectは各ポイントのz値も取れるので、今回は各ポイントのz値がある閾値を下回ったら(手が前に突き出されたら)ダウン状態、閾値を越えたら(手が引っ込んだら)アップ状態として扱う事にします。

今回のデモでは、自前の汎用マルチポインタライブラリを使用しています。ポインタが「認識」「ダウン」「移動」「アップ」「消失」した状態をそれぞれ持つ事が出来、さらにポインタの下にある各DisplayObjectがイベントを発行するように設計したため、MouseEventと同じ様に使う事が出来ます。また、Kinectのような特殊なシステムでない、普通のマルチタッチにも対応できるようになっています。以前のエントリにある「自作マルチタッチシステムを作ってみた」でも、このクラスを使用してマルチタッチを実装しました。

まず、コンストラクタでマルチタッチの用意をし、XMLSocketコネクトのための準備をします。

//==========================
//コンストラクタ
//==========================
public function Main():void{
//
mp=new MultiPointer(-1 , false);
mp.simulate=true;
mp.registerDefaultCursor(HandCursor);
addChild(mp);
//
connect_btn.addEventListener(MouseEvent.CLICK , connectStart);
//
}


マルチタッチに用いるクラスは「MultiPointer」クラスです。汎用クラスとして色々出来るように作ってあるのですが、ここでは詳しい説明は割愛します。
詳細はGoogle Codeにアップしたドキュメントをご覧下さい。

//==========================
//接続開始
//==========================
private function connectStart(e:MouseEvent):void{
//
socket=new XMLSocket();
socket.addEventListener(Event.CONNECT , connectComplete);
socket.addEventListener(DataEvent.DATA , receiveData);
socket.connect(ip.text , int(port.text));
//
}
//
//
//==========================
//接続完了
//==========================
private function connectComplete(e:Event):void{
//接続のためダミーデータを送信(サーバー仕様による)
socket.send("test");
}


ステージ上にあるボタンを押したら接続を開始し、接続が完了したらサーバーにデータを送信します。これは今回作成したサーバー側の仕様で、一旦双方向に通信しないと接続が確立出来ないようになっているためです。

//==========================
//データ受信
//==========================
private function receiveData(e:DataEvent):void{
//
//データ解析
var data:Array=e.data.split(",");
var id:int=data[0];
var parts:int=int(data[1]);
var x:Number=Number(data[2]);
var y:Number=Number(data[3]);
var z:Number=Number(data[4]);
//
//一意のIDを作成
var pointer_id:int=int(parts.toString()+id.toString());
//
//ポインタ認識
mp.detect(x,y,pointer_id);
//ポインタを動かす
mp.move(x,y,pointer_id);
if(z<1500){
mp.down(x,y,pointer_id);
}else{
mp.up(x,y,pointer_id);
}
//
}


データを受信したら、受信したデータを解析してMultiPointerクラスに渡します。 今回、データは「,」区切りの文字列として送信されてくるので、splitで分割し、それぞれの変数に入れていきます。 サーバーから送られてくるデータの中身は

ユーザーID , パーツ名(左手9/右手15) , x座標 , y座標 , z座標

というフォーマットになっています。
このデータを受け、ポインタ生成部分は以下のようになっています。

//一意のIDを作成
var pointer_id:int=int(parts.toString()+id.toString());
//
//ポインタ認識
mp.detect(x,y,pointer_id);
//ポインタを動かす
mp.move(x,y,pointer_id);
if(z<1500){
mp.down(x,y,pointer_id);
}else{
mp.up(x,y,pointer_id);
}


MultiPointer内に以下のメソッドがあり、それぞれ

・ポインタ認識 - detect()
・ポインタ移動 - move()
・ポインタ押下 - down()
・ポインタ押上 - up()

そしてここでは出てきていないですが、

・ポインタ消失 - lost()

となっています。

各関数にはx , y , idの引数を渡す必要があり、ここではマルチユーザーに対応するためパーツのIDとユーザーIDを一旦String形式で結合し、intに変換する事で一意のIDを生成しています。

押下/押上の判定については、z値を使用しています。暫定的に閾値を1500と設定し、手の前後操作でdown/upをそれぞれ実行するようにしています。
肝心のマルチタッチを受けてオブジェクトを操作する部分ですが、これは良く使う操作ですので、基本クラスとして用意しました。 ステージ上のオブジェクトの基本クラスに「PointerHandlingObject」というクラスを設定しています。このクラスは、マルチポイントによる操作と言えば王道な移動、拡縮、回転をサポートしています。

これで、Kinectと接続してFlash上のオブジェクトを操作する簡単なデモが出来ました。
Flashのソース: KinectFlash_sdtech.zip

今回使用した「MultiPointer」クラスは「自作マルチタッチシステムを作ってみた」でも使用しているのですが、その解説はまた今度ということで。

2010年12月20日月曜日

[Kinectハック]OpenNI+Flashでマルチユーザー・マルチタッチ OpenNI解析編



少し乗り遅れ気味ですが、Kinectネタを。
OpenNIの登場でKinectのユーザーのスケルトン情報が一通り取れるようになったので、
それをFlashへの橋渡しをして、マルチユーザー・マルチタッチな環境を作りました。

これでFlashでもNaturalInterfaceコンテンツを作れるんダゼ!

今回は「OpenNI解析編」ということで、
Kinectを購入してから、OpenNIを解析、Flashへ信号を投げるまでの解説です。


■開発環境
kinect制御端末 : WinXP VisualC++ Express2010
コンテンツ端末:MacOSX FlashCS4
ソケット通信で Win→Macへユーザーの手の位置を送ります。


Kinectハックの手順は先人たちをお手本に。

WindowでKinectを繋ぐまでの手順:
OpenNI: WindowsでKinectを使う

OpenNIをビルドするまでの手順
OpenNIをVisual C++ 2010 Expressでビルド&デバックするまでの手順。


上記サイトを参考にOpenNIを改変できるようにしたら、
OpenNIと一緒にインストールされたサンプルから改変しやすそうなのを探します。
NiUserTracker.exeはスケルトン表示までできているので、
今回はこれにソケット通信を追加しました。

C++は初めてなので、ここから、かなり試行錯誤してます…。
【C++】ソケット通信」を参考にして、SocketServerクラスを作りました。
クラスファイル間のアクセス方法がわからなかったんですが、
ハッシュファイルというのを作るんですね。ちょっと面倒です…。
SocketServerクラスにconnectとsend関数を作り、
send関数に送りたい信号を投げるとソケットで通信するようになりました。 

#include 
#include 

SOCKET s, s1;         //ソケット
//
//connect
int connect(){
  int result;          //戻り値
  //接続を許可するクライアント端末の情報
  struct sockaddr_in source;
  char buffer[1024];  //受信データのバッファ領域
  char ans[] = "送信成功";

  memset(&buffer, '\0', sizeof(buffer));
  //送信元の端末情報を登録する
  memset(&source, 0, sizeof(source));
  source.sin_family = AF_INET;
  //ポート番号はクライアントプログラムと共通
  source.sin_port = htons(3000);
  source.sin_addr.s_addr = htonl(INADDR_ANY);

  //ソケット通信の開始準備
  WSADATA data;
  result = WSAStartup(MAKEWORD(2, 0), &data);
  if (result < 0){
    printf("%d\n", GetLastError());
    printf("ソケット通信準備エラー\n");
  }
  //ソケットの生成
  s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (s < 0){
    printf("%d\n", GetLastError());
    printf("ソケット生成エラー\n");
  }
  //ソケットのバインド
  result = bind(s, (struct sockaddr *)&source, sizeof(source));
  if (result < 0){
    printf("%d\n", GetLastError());
    printf("バインドエラー\n");
  }
  //接続の許可
  result = listen(s, 1);
  if (result < 0){
    printf("接続許可エラー\n");
  }
  printf("接続開始\n");
  s1 = s;
  //クライアントから通信があるまで待機
 s1 = accept(s, NULL, NULL);
  if (s1 < 0){
    printf("待機エラー\n");
  }
  //クライアントから送信されたデータの受信
  result = recv(s1, buffer, 10, 0);
  if (result < 0){
    printf("受信エラー\n");
  }
  printf("%sを受信しました\n", buffer);
  return 0;
}
//
//send
int send(char id[],char part[] ,char px[],char py[],char pz[]){
 int result;          //戻り値
 char str[50]= "";
 //
 sprintf_s(str,"%s,%s,%s,%s,%s",id,part,px,py,pz);
 //
 result = send(s1, str, strlen(str)+1, 0);
 return result;
}


Flashには、ユーザーの手の情報を送りたいので、 スケルトンを描画しているクラスを解析します。
SceneDrawer.cppの中のDrawLimb()がそれです。

void DrawLimb(XnUserID player, XnSkeletonJoint eJoint1, XnSkeletonJoint eJoint2)
{
 if (!g_UserGenerator.GetSkeletonCap().IsTracking(player))
 {
  printf("not tracked!\n");
  return;
 }

 XnSkeletonJointPosition joint1, joint2;
 g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, eJoint1, joint1);
 g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, eJoint2, joint2);

 if (joint1.fConfidence < 0.5 || joint2.fConfidence < 0.5)
 {
  return;
 }

 XnPoint3D pt[2];
 pt[0] = joint1.position;
 pt[1] = joint2.position;

 g_DepthGenerator.ConvertRealWorldToProjective(2, pt, pt);
 glVertex3i(pt[0].X, pt[0].Y, 0);
 glVertex3i(pt[1].X, pt[1].Y, 0);
}

このコードからGetSkeletonJointPosition()がユーザーの部位の位置を返す関数だとわかります。
ユーザーIDと体の部位を指定するとx,y,z座標を返してくれます。
DrawLimb()を改変した関数SendPosition()を作り、SocketServerのsendに送ります。

void SendPosition(XnUserID player,int id, XnSkeletonJoint part,char _part[2])
{
 if (!g_UserGenerator.GetSkeletonCap().IsTracking(player))
 {
  printf("not tracked!\n");
  return;
 }
 XnSkeletonJointPosition joint1;
 g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(player, part, joint1);
 XnPoint3D pt[1];
 pt[0] = joint1.position;
 g_DepthGenerator.ConvertRealWorldToProjective(1, pt, pt);
 //
 char _id[2] = "";
 sprintf( _id, "%d", id);
 //
 char _px[10] = "";
 sprintf( _px, "%.3f", pt[0].X);
 //
 char _py[10] = "";
 sprintf( _py, "%.3f", pt[0].Y);
 //
 char _pz[10] = "";
 sprintf( _pz, "%.3f", pt[0].Z);
 //
 send(_id,_part,_px,_py,_pz);
}

以上で、OpenNIにソケット通信を追加できました。
今回は手の位置だけですが、顔や胴、足の位置も同じ仕組みで取得できます。

ここまでのソース: NiUserTracker_sdtech.zip

※VS上のデバックビルドでは動きますが、exeだとソケット通信開始時に落ちてしまいます。
いいところまで出来ているのに、なぜ…。
[追記 2010.12.22]
exeでも動くようになりました。
OpenNI/Data内の「SamplesConfig.xml」を読み込んでいたのですが、
開発環境とexeではパスが変わってしまうので、読めなくなっていたようです。


main.cppの
#define SAMPLE_XML_PATH "../../Data/SamplesConfig.xml"

#define SAMPLE_XML_PATH "SamplesConfig.xml"として、
exeと同じディレクトリにSamplesConfig.xmlをコピーすれば、
落ちなくになります。


 続きはFlash編へ。


Xbox 360 Kinect センサー
定価:¥ 14,800
新品最安価格:¥ 17,300 (2店出品)
売上ランク:62位
レビュー平均:4.54.5点 (127人がレビュー投稿)
by amazon通販最速検索 at 2010/12/21

Android(Galaxy Sのみ)でどの画面からでも画面の明るさを変更する方法 (追記あり)

何となく携帯(Galaxy S)をいじっていたら、設定等開かずに画面の明るさを変更する方法を発見したのでご紹介します。



Androidにはウィジェットがあるので、Galaxy Sであれば「消費電力の調整」というウィジェットを配置すればホーム画面から直接画面の変更する事が可能です。
画像の右端のアイコンがそうで、off(ユーザー設定のまま)、on(明るさ中)、on(明るさ大)、autoが順番に切り替わります。
ただ、この方法だといちいちホームに戻って来なければいけません。設定まで行かなくて済む、という点では便利ですが…


しかし、実はステータスバーを操作する事でどの画面からでも画面の輝度を変更可能です。操作方法は

1.ステータスバーを長押し
2.通知領域が消えたら左右にドラッグ


です。



明るさは絶対値指定のようで、ステータスバーの左側に行くほど暗くなり、右側に行くほど明るくなります。

今までも、何もしていないのに何故か突然画面の明るさが変わってしまうことがあって不思議に思っていたのですが、恐らくこの操作を行っていたのでしょう。

説明書に書いてあるのかもしれませんが、買ってから一切読んでいないので見落としていたのかも…

2011/1/6追記
店頭で試した所、どうやらこのワザはGalaxy Sでしか使えないようです。
Galaxy S / Xperia / HTC Desire HD / IS03で確認しましたが、Galaxy Sでのみ動作しました。

2011/1/10追記
ヨドバシとドコモショップにて店頭に展示してある複数の端末(4台)で試した所、Galaxy Sでも使える物と使えない物があるようです…
ヨドバシにあった3台中2台、ドコモにあった1台では成功しました。
OSのバージョン等見てみたが、どれも一緒でした。ただ、使えなかった端末は通知領域の「Bluetooth」の文字が入りきっておらず、最後の「h」が改行されていました。



使えなかった端末は今回触った端末の中で1つだけだったので要確認ですが、この表示と挙動の違いに因果関係があるかは不明です…

2011/1/10追記2
このブログを見てくれた友達が、自分の端末では出来なくて、Bluetoothの文字も全部入ってると教えてくれました。
ちょっと思い当たる所を探してみたのですが、「自動明るさ調整」が有効になっているとこのワザは無効になってしまうようです。なので、上の画像は見当違いな事言ってます(笑)でもまぁ、現に店頭でそういう端末個体差があったので、画像はこのままにしておきます。
自動調整とは共存できないですが、バッテリーの節約のため手動で!という方は

「設定」->「画面設定」->「明るさ」->「自動明るさ調整」のチェック

を外す事でこのワザが使えるようになります。

2010年12月16日木曜日

自作マルチタッチシステムを作ってみた

いまさら感がありますが、「5分で作れるマルチタッチパネルシステム」を参考に
マルチタッチシステムを作ってみました。
上記のシステムは「Touchlib」を使っていますが、
今回は「Community Core Vision v1.4 (CCV)」を使って、Flashと連携させました。
少し前まで「tbata」という名前だったんですが、いつの間にか「CCV」に変わってますね。


この記事を書いた時点でのCCV最新版は1.3ですが、
プロジェクトページではv1.4βが配布されています。
v1.4βではReacTable等で使われるFiducialsマーカーを認識できるようになっています。


作る際に用意したものは、
-----------------------------------
・スチレンボードで作ったテーブル
・トレーシングペーパーで作ったテーブル天板
・赤外線カメラ
・赤外線ライト
-----------------------------------

赤外線カメラはフレームレートの高いものを用意すると認識精度が上がります。
100fps出るモーションキャプチャ用のOptiTrack FLEX:V100R2カメラを用意できるのが理想ですが、
PlayStationEyeでも十分精度が高いです。
実はPSeye値段に似つかわしくない程ハイスペックで、なんと640x480の解像度で75fps出ます。
数万円してもおかしくないのに3000円でお釣りがきちゃいます。
このコストパフォーマンスの高さからなのか画像認識まわりではPSeyeを使うのが常套手段になっていますねー。

今なら、PSeyeとMOVEコントローラがセットになった「PlayStationMOVE スターターパック」を
買うのが賢いかも。
MOVEコントローラみたいな赤外線ペンライトがあるとキャリブレーションがすごく楽です。


PSeyeの赤外線カメラ化はここここを参考にしました。
可視光をカットするIRフィルターは富士フイルムの「IR 86」を使いました。
ただ、このフィルターだと蛍光管の光も少し拾ってしまうので、
どなたか最適なIRフィルターがあれば教えて下さい。


PSeyeのドライバはCode Laboratoriesの「CL Eye Platform DriverCL Eye Platform Driver」を使います。
このドライバにはノーマルモードとアドバンスモードがあって、
「640x480/75fps」で使用するにはまずアドバンスモードにする必要があります。

アドバンスモードにするには、下のコードをメモ帳にコピペして、「cleye.config」として保存します。

    
    

このファイルを「Community Core Vision.exe」と同じディレクトリに配置すると「640x480/75fps」が選べるようになります。


立ち上げる度に設定するのは面倒なので、
CCVの「data/config.xml」の一部を下のように書き換えて、自動的で「640x480/75fps」にします。


        1
        0
        640
        480
        75


これで運用時に楽になります。


赤外線ライトはなんでもいいのですが、ケイヨーの「K-Light」あたりがオススメです。

あとは、CCVを起動してFlash XMLにチェックを入れておくとCCV-Flash間でソケット通信してくれます。


タイムラインにMCを置いてgotoAndStopでフレームを移動するときの注意

タイムライン上に画像等を配置して、フレームを動かす事によってMCの内容を切り替えるという手法、まだまだよく使います。しかし、フレームに配置されている要素がMCだった場合、少し注意が必要です。

例えばA.asというクラスを持ったMCを1〜3フレームに配置します。
各フレームにはキーフレームを切ってあり、MCの座標は各フレームで違い、各MCには60フレーム程のアニメーションが設定されているとします。

public function A():void{
addEventListener(Event.ADDED_TO_STAGE , init);
addEventListener(Event.REMOVED_FROM_STAGE , init);
trace("construct");
}

private function init(e:Event):void{
if(e.type==Event.ADDED_TO_STAGE){
trace("added");
gotoAndPlay(2);
}else{
trace("removed");
gotoAndStop(1);
}
}


のようにコードを書きます。
すると、下記のような挙動になります。
(マウスクリックで次のフレームに進みます)



各フレームに別のインスタンスを生成したつもりなのに、あたかも一つのインスタンスの座標が変わったかのようにアニメーション状態を引き継いでしまいます。
これを回避するには、各MCに名前を付けると良いようです。
下記は、各MCに名前を付けたものです。
(マウスクリックで次のフレームに進みます)



タイムラインにMCを並べてレイアウト等を管理する時は、少しこの点に注意して作成した方が良いかもしれません。

.svnファイルを削除するドロップレット

fukusinです。
バージョン管理にsubversionを使ってるんですが、
スクリプト使うグループワークでは必須ですね。
で、subversionは何かと便利なんですが、
データを人に渡す時にsubversionの管理ファイルが邪魔になります。
隠しファイルになっている「.svnファイル」ですね。結構、容量が大きい。


そこで、フォルダ内の.svnファイルをすべて削除してくれるドロップレットを作りました。
winだとTortoiseSVNのexportで同じことができますが、
このドロップレットの方が手軽に使えると思います。
mac/win両方あります。



■使い方





フォルダをアイコンにドロップするだけです。
ドック、もしくはタスクバーに置いて使って下さい。


■注意点
macは.svnファイルを削除してもチェックマークが残ります。
Finderを一旦終了させるとチェックマークが消えます。
ローカル以外のフォルダは失敗します。(いつか直したい…。)


■対応OS
mac:Tiger/Leopardのみ動作確認済
win:XPのみ動作確認済
mac版はAppleScript、win版はC#とバッチファイルで作ってます。

2010年12月5日日曜日

iPhotoとAndroid (調査中)

2011.2.8追記
以下の症状、陥る条件が分かりました。以下にまとめましたので、どうぞ。(解決にはなっていませんが…)
Mac OS 10.6とiPhotoとAndroid


Android(Galaxy S)の写真をiPhotoに読み込ませようと思ったのですが、なぜかiPhoto上に表示されません。先代のフューチャーフォンで使っていたSDカードをそのまま使用していて、そちらで撮影した写真も入っているのですが、そちらの写真は表示されます。
いずれもSDカード直下にある「DCIM」フォルダ内にファイルがあり、それぞれ「100ANDRO」「100SHARP」というフォルダに写真が入っています。

原因を色々調べてみた結果、どうやら画像ファイルの文字数とファイル名に含まれている文字に原因があるようです。
ファイル名を色々変更して何度か読み込み直してみた所、iPhotoは「ファイル名が8文字ジャスト」「ファイル名に"."や"-"を含まない」画像ファイルのみ読み込むようです。先頭の文字は数字でもOKで、あまり調べてないですがとりあえずファイル名に"_"は使用できました。

ちなみにAndroid純正カメラだとファイル名は
「2010-10-28 13.01.25.jpg」

Vignetteでは
「2010-12-05-02-17-14-936.jpg」

Camera360では
「C360_2010-11-23 10-19-37.jpg」

…どれもアウト。

他に良いカメラアプリがあるのかもしれないですが、メジャーどころはこんな所でしょうか。

仕方ないので、写真管理にはiPhotoを使用しつつ、Androidの写真の取り込みにはPicasaを使用しています。

PicasaはiPhotoのライブラリを読み込んで独自UIで一覧できるようになる上、顔認識機能があって、さらにそれをGoogleコンタクトと同期し、Picasaから顔写真を登録する事ができるのが魅力ですね。写真整理ついでにGoogleコンタクトが充実するのはスバラシイ。しかもタダ。

ただ、この手順だとPicasaで取り込んだ後、D&DでiPhotoに取り込んで、それをさらにPicasaが読み込みにいくという手順になるので、大分回りくどいんですが…

iPhoto側でもストレージから写真だけをピックアップする必要があり、試行錯誤があってこういう制約になっているのだとは思いますが、もっとうまい方法で写真をピックアップしてくれると嬉しいですね。

現状では、Picasa等を経由するか、上記条件に当てはまるファイル名で出力するカメラアプリを探すのが良さそうです。


2010.12.9追記
…と思ったら、会社のMac(iLife 09)では全部表示されました…(家のMacは11、アップグレード前の08でも不具合を確認)
端末固有の不具合なのかな?それともOSの違い等に左右されるのか…少し探ってみたいと思います。