Ingress 「Agent Stats」がデータアップ時サーバエラーで使えないので。。 tesseract-ocrのビルド

Ingress用のAndroidの「Agent Stats」ですが、Ingressのprofileのスクリーンショットを共有でサーバサイトに送信するとOCRで読み取ってくれて、実績を管理してくれるのですが、
人気なのかサーバ過負荷だと思いますが、エラーで全然認識してくれません。><

(本記事は、一般向けではありませんので、「Agent Stats」で検索して来られた方は、
お役に立ちません。すみません。アプリが完成すれば別ですが。)

そこで、自分で作ってみることにしました。「Agent Stats」はサーバサイドでOCRで読み取って
いますが、今回はAndroid端末側でOCR機能を入れて読み取れないかまず試してみました。

第一ステップ:Android端末の方でOCR認識して、データを文字列に置き換えてできるか。
まず、AndroidでOCRライブラリーを探したところ、
https://github.com/rmtheis/tess-two
があり、ネイティブコード(C/C++)で作られています。jniですので、Android NDKが必要になります。
NDKは、Windowsでは面倒くさいので、Linux(CentOS7)上でコンパイル環境を構築することにします。

【ndk-build環境の構築】CentOS7

1.Android NDKのインストール
 1) wget http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin
 2) chmod +x android-ndk-r10e-linux-x86_64.bin
 3) android-ndk-r10e-linux-x86_64.bin
 4) mv android-ndk-r10e /usr/local/
 5) echo ‘export PATH=$PATH:/usr/local/android-ndk-r10e’ >> .bashrc
 6) echo ‘export NDKROOT=/usr/local/android-ndk-r10e’ >> .bashrc

2.Android SDKのインストール
 1) wget http://dl.google.com/android/android-sdk_r24.2-linux.tgz
 2) tar zxvf android-sdk_r24.2-linux.tgz
 3) mv android-sdk-linux /usr/local/
 4) echo ‘export PATH=$PATH:/usr/local/android-sdk-linux/tools/’ >> .bashrc
 5) echo ‘export PATH=$PATH:/usr/local/android-sdk-linux/platforms’ >> .bashrc

3.その他必要モジュール
 ビルド時、/usr/local/android-sdk-linux/build-tools/22.0.1/aapt実行時に必要
 モジュールがなくエラーが出る場合は、必要なモジュールをインストールすること。
 私の環境では、以下3つが必要でした。

  1) yum install ld-linux.so.2
  2) yum install libz.so.1
  3) yum install libstdc++.so.6

【tesseract-ocrのビルド】 作者に感謝。

 1) git clone git://github.com/rmtheis/tess-two tess
 2) cd tess
 3) cd tess-two
 4) ndk-build
 5) android update project –path .
 6) ant release

 成功すると以下にオブジェクトが出来ます。
 ./bin/classes.jar
 ./libs/armeabi-v7a/liblept.so
                           /libtess.so
       /mips/liblept.so
               /libtess.so
       /x86/liblept.so
              /libtess.so

 以上をEclipsプロジェクトのlibsフォルダーにコピーすればもうOCR読み取り
 関数が使えます。

【OCR読み取りツール】EclipsはWindows上で開発しています。
  とりあえずこんな感じで、まずは文字が読めるかみました。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;

Bitmap bitmap = BitmapFactory.decodeFile(“/sdcard/Pictures/ingress/profile_20150507_202910_0.png”, options);
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);

Log.v(TAG, “– START”);

TessBaseAPI baseApi = new TessBaseAPI();
baseApi.setDebug(true);
baseApi.init(DATA_PATH, lang);
baseApi.setImage(bitmap);

String recognizedText = baseApi.getUTF8Text();

baseApi.end();

Log.v(TAG, “– END);

読み取り画像 テストアプリで読み取り後

すばらしい。読み取れてる!。読み取り時間は、ネイティブコードにしても8秒程度かかります。

(金色のグラディエーションが係ってるタグ欄は文字化けしているけどこれは読み取れなくともいいので)

使えることが分かったので、第二ステップ以降は時間のある時に作成します。
とりあえず、CSVにしてデータをメール転送ならさくっとできそうです。
OCR読み取りの作成部分は今後、仕事にも生かせそうです。

台風来る? シンガポールまで約5,000km 現地晴れ。 Ingress

シンガポールまで約5,000km 現地晴れ。今日の夜、シンガポールに旅行予定ですが、台風の影響で飛行機は飛ぶの?。現地ではIngressミッション予定。

未知の土地を歩くにはピッタリのアプリ、3D行先コンパスです。(作成者は私です。。)

Ingressで知らない道を、スキャナー上のポータルを頼りにぐるぐる回って歩いていると、方角を見失います。
方角に弱い(方向音痴ともいいますが;;)私としては、ingressのスキャナー上にコンパスが表示されていますが、いまいち現実の空間で北を認識できない時に、この3D行先コンパスを使うと、AR表示していますので、迷うことがありません。正にingressをする自分に最適です。!

「白と金」「青と黒」のドレス CrenaCamでイメージ色判定して見る。

このドレスは「白と金」? それとも「青と黒」
話題の画像は↓。私には、「白と金」にしか見えないのですが、
奥さんと娘は、「青と黒」と言っています。まじで?!「白(白系の青と金」じゃないの?
オリジナルのドレスは「青と黒」らしいです。


ということで、ここは自作のCrenaCam(Androidアプリ)でイメージ色を取得してみましょう?

[黄土色、こはく色なので金]

[あいねず、サックスブルー:イメージカラー青なので青]

ということで、青色と金色が妥当かな。

GooglePlayに登録するアプリで,タブレット版で、three dots「・・・」をナビゲーションバーの3つの仮想ボタンの右側に表示したい。

GooglePlayに登録するアプリで,タブレット版で、three dots「・・・」をナビゲーションバーの3つの仮想ボタンの右側に表示したい。
何を言っているのか良くわからないと思いますので実例を。

タブレットNexus 7 でパズドラのオープンイング画面ですが、一番下のナビゲーションバー
の一番右に縦のドット3つ(three dots)あります。Android 2.xまであるのですが、Android 3.0でUIが変わり、
タブレットでは、Honeycombより前をターゲットにしたアプリにしないと表示されまません。
具体的には、
AndroidManifest.xml
<uses-sdk android:minSdkVersion=”8″ android:targetSdkVersion=”10″/>
であればこのように表示されるのですが、これだとGooglePlayに登録した場合、タブレット版には
アプリが表示されません。(検索しても出てきません。)

GooglePlayにUPされたタブレット可能アプリで、three dots「・・・」をActionBarでなく、
ナビゲーションバーに表示するにはどうすれば良いのか。
(注:googleでは、今後ActionBarを使ってちゃんとしなさいと言っています。
http://www.itmedia.co.jp/news/articles/1201/27/news059.html

パズドラアプリはどうやってこれを表示しているのか?
プログラムで表示可能なのか(検索しても回答見つからなかった。)

これを実装したいのは、自アプリCrenaCamで、全画面使っておりどうしても昔の画面外のナビゲーションバーに表示したくいろいろ試行錯誤した結果できました。
(注:GooglePlayではなく野良アプリなら全然問題なく
<uses-sdk android:minSdkVersion=”8″ android:targetSdkVersion=”10″/>
の設定だけで表示されます。)
Android:Menuボタンの廃止とActionBarの詳解は↓で、分かりやすいです。
ただ、GooglePlayでの対応は記載されておりません。
http://yuki312.blogspot.jp/2012/07/androidmenuactionbar.html

GooglePlayにUPされたタブレット可能アプリで、three dots「・・・」をActionBarでなく、
ナビゲーションバーに表示する方法は、すごく簡単で、
AndroidManifest.xml
<uses-sdk android:minSdkVersion=”x″ android:targetSdkVersion=”x″/>
一切書かない。(この方法が正しいかどうかは不明です。自己責任でお願いします。)
これだと、あらゆる端末で対応ダウンロード可能になります。^^

Google developer console APKの詳解を見るとAPIレベル0+となってる。
また相変わらず、最適化のヒントで「製品版 APK は次の条件を満たす必要があります:
Android の最小バージョンとターゲット バージョンがタブレットをサポートしていること
(targetSdkVersion と minSdkVersion をご確認ください)。」が表示されますが、
GooglePlayにはタブレットでも表示されます。
OverflowButton(three dots)が表示されて、設定メニューが使えます。^^

実際は、Android 2.3.3(API 10)以上でないと動作しないので、
プログラム中にバージョンチェックを入れています。
       if(Build.VERSION.SDK_INT < 10){
            //APIレベル10より前の機種の場合終了
      String sMsg = “rnAndroid 2.3.3rn以上でお使いくださいrn”;
      Toast toast = Toast.makeText(getApplicationContext(),sMsg, Toast.LENGTH_LONG);
      View v = toast.getView();
      v.setBackgroundColor(Color.rgb(255,20,147));
      toast.setGravity(Gravity.CENTER,0,0);
      toast.show();
      finish();
       }

Google Nexus 5にストラップを!

会社支給の携帯(Xperia)からGoogleのリードデバイスであるNexus 5 LG-D821 SIMフリー7に替えました。
(Nexus 6はよりハイエンドモデルですが大きすぎるのでパス)
リードデバイスとは、実装参照デバイス(リファレンスモデル)で、通信キャリアや端末メーカーの影響を受けない純粋なAndroid環境の提供するためのデバイスの位置づけで、お世話なアプリは搭載されていません。

現在、Google play版のNexus 5はずっと在庫無しで、今後いつ入ってくるのかわからないので、AmazonからEmobile版のNexus 5を購入しました。Google play版と差異はありません。
尚、Google play版の初期ロットの一部の個体はドコモのspモードで繋がります。今回のロットはspモードでは繋がりませんので、ドコモで使う場合はmoperaの契約が必要です。

Nexus 5を開発仕様にいろいろ設定して、root化もしています。
(デバイスを直接いじりたい時とか、その他いろいろあるので。)

で、問題はストラップが付けられないということです。
すべり落下防止の為、私はストラップをいつも小指と薬指のはさんで使用しています。
見たところ下底面のスピーカー穴にテグスを通すことができれば良さそうです。

ネットで調べてみると、
http://www.gcd.org/blog/2013/11/1008/
の方が同様のコンセプトでテグスを付けられています。

裏面のカバーを空けるのに、ケースオープナーが無いと、どうにも開けられません。
家にあるもので、何か代替できるものはないかと探した結果、車のダッシュボードを外す時のパネルはがしで挑戦することに。
(ケースオープナーよりは強引な作業になりますので、真似はお勧めできません。)

  ↑フックの部分を上手く外せばOKです。最初は手加減がわからないので不安です。
  ↑結び目は、瞬間接着剤で解けないように。下にLG-D820の刻印が・・
  LG-D821を買ったのですが部品共通?
  ↑完成!。お気に入りのストラップ(北海道おみやげのクリオネストラップ)
  

Android でのスクリーンキャプチャー

前回の宿題で、Androidでアプリからスクリーンキャプチャーを取る方法です。

Androidでアプリからスクリーンキャプチャーを取るにはroot権限がないとだめです。(一部機種でrootを取らなくてもできるものもあります。)

Android 4.0以降では、root化してあればscreencap,screenshotコマンドで簡単にとれるのですが、Android バージョン2.3では使えません。
フレームバッファー /dev/graphics/fb0から直接取得することになります。
(このデバイスは,rootでないとアクアセスできません。)

Android 4.0以降では、電源ボタン+ボリューム(↓)同時押しで取れますが、アプリでこのキーのエミュレートをしても、「電源ボタン」押下は、やはりrootでないと反応しません。

今回、自分使用している機種:SONY Xperia SO-01C 480×854 Android バージョン2.3.2では、Google Playにアップされているツールはどれも正常にとれないのです。赤みがかかった画像になる。RBGAの配列が違うようです。しかたがないので作ることにした。

自分のスマホはrootを取っているので、今回はうまくいけば、アプリにする予定
(公開は今のところ考えていません。)

1) フレームバッファーから生データを取得
#cp /dev/graphics/fb0 /sdcard/fb0

fbのファイルサイズは、3,410,432で、480×854で1ピクセル4バイトとすると
+,-,x,/を思考錯誤して以下の式にたどりついた。

(3410432-(65536 x 2))/2 = 480 x 854 x 4

で、元サイズから65536×2バイト余分引いて、ダブルバッファリングしているので1/2すると、ちょうど480 x 854 x 4になります。

2) 無理やりBMPにしてみる。

fb0にヘッダー54バイトを加えます。
unsigned char header[54] = {
    0x42, 0x4d, 0x36, 0x05, 0x19, 0x00, 0x00, 0x00,0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
  0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x56, 0x03,0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x05, 0x19, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

一応、画像になってますが、上下反転して、色も少しおかしいです。RとBが入れ替わってる。

3) データ変換する。行単位で上下を変換し、BGRA -> RGBAにする。

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>

#define BMP_SIZE (3410432-(65536*2))/2

unsigned char srcdata[BMP_SIZE];
unsigned char outdata[BMP_SIZE];

unsigned char header[54] = {
    0x42, 0x4d, 0x36, 0x05, 0x19, 0x00, 0x00, 0x00,0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
    0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x56, 0x03,0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x05, 0x19, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

int main(int argc, char *argv[]){

int fd,fd_out;
long i,j;

unsigned char c;
unsigned char *p;

fd = _open(“fb0”,O_RDONLY | O_BINARY );
if(fd == (-1)){
return(-1);
}

p = srcdata;

//_read(fd,srcdata , 3410432 – (65536 * 2));
for(i = 0 ; i < BMP_SIZE ; i+= 53760){
_read(fd,p,53760);
p += 53760;
printf(“%in”,i);
}

fd_out = _open(“fb0-001.bmp”,O_CREAT | O_WRONLY | O_TRUNC | O_BINARY,S_IREAD | S_IWRITE );
if(fd_out == (-1)){
return(-1);
}

//これだと、上下逆さ&色抜け(R<->B)
//_write(fd_out,header,54);
//_write(fd_out,srcdata,(3410432 – (65536 * 2))/2);

//————————————

unsigned int width = 480;
unsigned int height = BMP_SIZE  / 480 / 4;

        //上下反転
for(i = 0; i < height; i++){
for(j = 0; j < width * 4; j++){
outdata[(height – 1 – i) * width * 4 + j] = srcdata[i * width * 4 + j];
}
}
//R,B入れ替え
int cnv = 0;
for(i = 0 ; i < BMP_SIZE ; i += 2){
if(cnv == 0){
p = &outdata[i];
c = outdata[i];
cnv++;
}else{
*p = outdata[i];
outdata[i] = c;
cnv = 0;
}
}

_write(fd_out,header,54);
_write(fd_out,outdata,BMP_SIZE);

_close(fd);
_close(fd_out);
}

こうすると、正常な画面になります。これで、スクリーンキャプチャーツールが作れます。(要root)

*root化状態でパズドラを動かすとデータが初期化されますので注意が必要です。といっても/system/bin/su,/system/xbin/su,/sbin/suのようにsuがなければ大丈夫です。

参考:
ビットマップフォーマット
http://www.kuwalab.net/technics/bitmap/
RGB565の時は、16bit のデータフォーマットなので
少し調整が必要です。
http://android-dev-log.ldblog.jp/archives/11346611.html

パズドラ: Pazdof パズドフ for Android / Xperia arc (SO-01C) 2.3.2

Pazdof パズドフは、hiehieさんが作られているパズドラのコンボ解析アプリです。

Androi4.0以上だと、「パズドラCombo」があり解析に必要なスクリーンショットもroot権限なしで、電源ボタン+ボリューム(↓)同時押しで取れるのですが、自分の持ってるXperia arc (SO-01C) は、スクリーンショットはroot権限がないととれません。
しかもAndroid 2.3.2でそもそも「パズドラCombo」が使えません。

ここぞという時に使いたいので、Pazdof パズドフを使って見ることにしました。

<必要なツール>
■PCツール
・Android-SDK (adb)
 http://developer.android.com/sdk/index.html
・ffmpeg.exe
  http://blog.k-tai-douga.com/category/359294-1.html
  にコンパイル済みのものが配布されていました。

 *スクリーンショットを取るには、USBでPCと接続してPC上で取る必要があります。
  他のスマホ機種だとroot化していれば、アンドロイドアプリで取れるのですが、  Xperia arc 2.3.2だと全体的に赤みがかかってしまいます。
  Xperia arcはRGBXで、どのアプリもXRGBフォーマットで変換しているようで、使えません。

■Androidアプリ
・Pazdof パズドフ for Android
  https://play.google.com/store/apps/details?id=jp.hiehie.pazdof

<設定>
●PCとXperiaをUSBで繋げておく。
DOS窓で、以下を実行。-pix_fmtは、rgbaです。rgb32だと赤が抜けて青みになります。
フレームバッファから直接rawファイルをPULLして、ffmpegでpngに変換します。

1) adb pull /dev/graphics/fb0 fb0
2) ffmpeg  -vcodec rawvideo -f rawvideo -pix_fmt rgba -s 480×854 -i fb0 -f image2 -vcodec png c:tempimage001.png

3) adb push C:tempimage001.png /mnt/sdcard/Pictures/Screenshots/

●XperiaでPazdof パズドフ起動(Android 2.3.3以上ですが、2.3.2でも動作しました。)

1) [開始]ボタンを押します。
 ・スクリーンショット保存場所:デフォルト設定でOK。
 ・右90度回転はチェックを外す。
 ・ドロップ位置の調整(Y座標) -16でフィットしました。
  正しい位置にくると、解析結果が自動で表示されます。
 ・ルートの表示位置の調整(Y座標) -27ぐらい。

以上で、パズドラを起動すればPCでスクリーンショットを取ってAndroidに転送すれば自動で解析ルートが表示されます。
(*PCからのコマンド実行は、BATファイル作成してファイル名も時間を含むようにすると良い。)

[追記]
Xperia arc 2.3.2 でのスクリーンショットが赤色な謎がこの機会で分かった。
これで、自力でスクリーンショットアプリ作れます。(root化必要ですが)
/dev/graphics/fb0のフレームバッファーをRBGに変換すれば良いだけですので、
以前、カメラアプリを作った時のコンバートが利用できるかと。
https://play.google.com/store/apps/details?id=jp.picolix.camera.controll
http://dip.picolix.jp/disp9.html

Nexus 7 root化したらパズル&ドラゴンズが動かなくなってしまった。

Nexus 7にパズドラ(パズル&ドラゴンズ)入れて遊んで見たんですが、その後root化したらパズドラが動かなくなってしまった。

どうも、
/system/app/Superuser.apk
/system/xbin/su
この2つがあるとだめなようで、/system/app/Superuser.apkは、
/data/app/Superuser.apkに移動して、/system/xbin/suはとりあえず、suuにrenameして、
動作するようになった。

*書き換えメモ:/system フォルダを書き込み可能にする
$ adb shell 
$ su
# mount -o rw,remount -t yaffs2 /dev/block/mtdblock3 /system

AndroidでICカード NFCタグを読み込み

会社で、開発用にNexus7を買ったのは実は、NFCタグを読み込みたかったのです。
(他の理由もありますが。)

http://www.atmarkit.co.jp/ait/articles/1211/27/news072.html

からサンプルコードを頂き、コンパイル&GOとしてみたところ、
[2013-04-24 00:46:27 – NfcDiscover] No Launcher activity found!
[2013-04-24 00:46:27 – NfcDiscover] The launch will only sync the application package on the device!
え?どういうこと?しばし悩むこと小一時間。
通常は、
<intent-filter>
       <action android:name=”android.intent.action.MAIN” />
       <category android:name=”android.intent.category.LAUNCHER” />
</intent-filter>
ですが、これがなくてactivityが見つからないし、アイコンも登録されない。ただし設定-アプリのリスト中には存在している。

The launch will only sync the application package on the device!
=> ランチャーは、デバイスの同期で起動って書いてある。英文を読めば良かったのですね。
もう、一行目のNo Launcher で全て読み飛ばしてた!
そういうことです。これで問題なかったのです。

ということで、ICOCAカードをNexus7の背面上部に合わせると反応しました。

手持ちのICカードを調べてみると。
  1. ICOCA                       NfcF
  2. 京都ぷらすOSAKA PiTaPa NfcF
  3. JAL MILEAGE BANK        NfcF
  4. 運転免許証                 IsoDep/NfcB
となっていました。運転免許証 は3月に更新したばかりでICカードになってました。^^

Android Nexus7 で CrenaCam起動しない。

会社で、開発用にNexus7を入手したのでまず、CrenaCamを入れようとしたけど、Google Playで検索してもCrenaCam検索しても出てこないし、直接、URLで野良アプリ風でダウンロードしても、Androidで「お使いの端末はこのバージョンに対応していません。」のメッセージ。

デバッグしてみたところ、
Camera.open();
で落ちる。
http://stackoverflow.com/questions/16039670/android-camera-preview-code-not-working-with-nexus7-surfaceview-error
を見ると。

1)The problem is that Camera.open() will return null if there is no rear camera:
とのことで、フロントカメラは、Camera.open(0);にしろと記載があった。
で、Android 2.1だと、このパラメータは使えません。
Android 2.3.3だと、Camera.open(0);が使えた。

2)オートフォーカス設定で、
camera.setParametersを使ってセットしていますが、ここでも落ちる。
try{}chatch{}で逃げる。

以上でとりあえず、CrenaCamが起動しました。
ん~。Google本家のハードなのにいろいろと面倒です。