涙目ブログ

アクセスカウンタ

zoom RSS androidでカメラを制御。なんか変だよGoogleさん

<<   作成日時 : 2009/07/17 20:54   >>

なるほど(納得、参考になった、ヘー) ブログ気持玉 28 / トラックバック 1 / コメント 0

Android ネタです。
ドリ系とかそっち系ではなく、Google が提供している携帯電話プラットフォームの話です。
今回Javaでできる部分を使用して、カメラを制御し、あわよくばARなど考えていましたが、
出来上がったものは重すぎて動かず(T_T)
それにしても、Googleのこの仕様は首をかしげざるをえません。

端末:HTC-magic( Google Developer Day 2009で配られた試作品。 HTC-03Aと同型)
開発環境:Eclipse Version: 3.4.2 Build id: M20090211-1700 + android-sdk-windows-1.5_r2
開発OS:Windows Vista sp1

まずはカメラを使って画像を表示させようと、以下のサンプルを実行。
http://developer.android.com/guide/samples/ApiDemos/src/com/example/android/apis/graphics/CameraPreview.html

いきなり落ちる(T_T)
色々調べると、マニフェストにカメラの使用許可を書かなければいけないらしい。
なので、AndroidManifest.xmlに<uses-permission android:name="android.permission.CAMERA" />を追記。
確かにカメラを使うことはユーザーに知らせないとね。
正しいですよGoogleさん。

そして再度実行すると、確かに動いた。
でもなんか変(T_T)
なんか潰れてる。縦と横が逆になっている感じ。
色々調べてみると、横向けのアプリしか対応していないらしい。
なので、AndroidManifest.xmlのactivityにandroid:screenOrientation="landscape"を追記。
横向き専用ですか。まぁ、仕様ですからしようがないですよね、Googleさん。

さらに以下のコード追加して、全画面表示を行う。
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
これでまともになりましたよ、Googleさん。

動いたところで、コピペしたソースを見返す。
んっ!描画のコードがない。
startPreview()後に勝手に描画処理がされている。
これって・・・プロブラマの知らないところで別スレッド作って勝手に描画処理ですか。
Googleさん、ちょっとやりすぎじゃないですか。
OpenCvみたいに、1フレームごとにキャプチャ画像を取得して、文字や画像の合わせこみを
すると思っていたのでショックでした。
データはどうやって取るの?

調べてみると、onPreviewFrameのインターフェイスに画像データがバイト列で
コールバックされるようです。
流石ですねGoogleさん。

落ちが分かるようですが、このバイト列は役に立ちません。
↓を参照。
http://code.google.com/p/android/issues/detail?id=823

画像を描画する時はBitmapクラスのインスタンスを
バイト列から作る必要がありますが、そのインスタンスを作成する
BitmapFactoryのdecodeByteArray(byte[] data, int offset, int length) で
インスタンスが生成できません。
要するに、描画するのに非対応な形式でバイトデータがコールバックされます。
なので、自力で変換します。
なんか変じゃないですか、Googleさん。
自力変換のサンプルはアウトプットがint の配列です。
これはBitmapのインスタンスをあらかじめ作成しておき、
Bitmap#setPixels( rgb, 0, getWidth(), 0, 0, getWidth(), getHeight() )で
値を設定します。

でも、API仕様書には、Camera.ParametersのsetPreviewFormatというメソッドがあり、
そこで、RGB_565やJpeg形式でプレビューができると書いてあります。
それでもコールバックされるプレビューの画像形式は例の使えないやつです。
これは「バグ」ですよね、Googleさん。
仕様書と異なる動作をバグというのですよ、Googleさん。

それでも画像が取れたので良しとします。
今度は描画です。
SurfaceViewは描画時にSurfaceHolderのlockCanvasを使用します。
そして、落ちます(T_T)

API仕様書に書いてありますが、サンプルソースでSurfaceHolderのsetTypeを使って
タイプをSURFACE_TYPE_PUSH_BUFFERSにしてますが、このタイプでは
lockCanvasは成功しません。
完全にカメラのプレビュー専用のタイプです。

いまどき、カメラからプレビューが表示されるだけで喜ぶ人はいねーよ。
ARが目的だよ、ARがよ。
もしかしてARを知らないのGoogleさん。
それとも知ってて嫌がらせか?

というわけで、SURFACE_TYPE_PUSH_BUFFERSをSURFACE_TYPE_NORMALへ。
lockCanvasが失敗することはAPI仕様書に書いてあるけど、
カメラから画像を取得するのは、ARのためだよ。
なんでこんなに苦労するんだい、Googleさん。

SURFACE_TYPE_NORMAL( SURFACE_TYPE_PUSH_BUFFERS以外のタイプ )にしたら、
lockCanvasで描画に必要なCanvasクラスのインスタンスが手に入ります。
これで、カメラで取得した画像をまず描画し、その後ARしたい画像を重ねれば
即席のARのできあがり・・・のはずだった。

実行してみると、重い。
最初に1〜2フレーム画像を取得したらフリーズします。
これは試作機だからかい、Googleさん。
使えないよGoogleさん。

Youtubeとかにあるデモ画像はネイティブいじってるんですかね。
とりあえず、今回自分が試した実装は以下の通りです。

1.デモのサンプルをコピペ
2.AndroidManifest.xmlに必要事項を記載。
3.全画面表示を設定。
4.SURFACE_TYPE_PUSH_BUFFERSを廃止、代わりにSURFACE_TYPE_NORMALを使用。
5.onPreviewFrameのバイト列はIssue 823を参考に自力変換。
6.lockCanvasとunlockCanvasAndPostを使用して、画像を描画。

自分の実装が間違っているきもするけど、
なんか変だよGoogleさん。


テーマ

関連テーマ 一覧


月別リンク

ブログ気持玉

クリックして気持ちを伝えよう!
ログインしてクリックすれば、自分のブログへのリンクが付きます。
→ログインへ
気持玉数 : 28
なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー) なるほど(納得、参考になった、ヘー)
ナイス ナイス ナイス ナイス ナイス
面白い 面白い 面白い 面白い
かわいい かわいい かわいい かわいい
驚いた 驚いた
ガッツ(がんばれ!)

トラックバック(1件)

タイトル (本文) ブログ名/日時
AndroidでOpenCV 後編 ネイティブを使ってAR
AndroidでOpenCVの後編です。 やってみましたが、OpenCVどころではありません。 そもそものAndroidのカメラ制御が悪すぎて手の施しようがありません(T_T) ...続きを見る
涙目ブログ
2010/03/04 22:23

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文
androidでカメラを制御。なんか変だよGoogleさん 涙目ブログ/BIGLOBEウェブリブログ
文字サイズ:       閉じる