ノンプログラマー・プログラミング・ガイド

ほぼ独学。もはやおっさんになりかかってからプログラミングの勉強開始。HTML、CSS、JavaScript、SQL、PHP、Javaがなんとなく解る。Joomla!とandroidで書いたプログラムを配布中。iPhoneアプリ作りたいからMacくれ(下さい)。

2013年07月

この記事では、OpenCVを使った結果だけをしりてーんだよ。C++とかいらねーんだ。javaだけでいいんだ。って人向けの記事です。OpenCV自体の開発をどうこうしようって人向けではありません。僕は、そんなところを理解すらしてません。


OpenCVは、画像を解析してくるオープンソースのライブラリーです。画像の中から顔を検出してくれたり、口や目を検出してくれたり、素敵ライブラリーみたいです。もともとは、Cで書かれた言語らしいんですけど、他の言語にも対応してくれてるみたいっす。


1. OpenCVのAndroid向けのファイルを入手

OpenCVのAndroid SDKを入手して、インストールしてみてくだせい。この記事を書いている時点での最新版は、2.4.6です。サンプルにもそれを使ってます。


2. 解凍してEclipseでインポート

zipファイルなんで解凍してEclipseにインポートします。「ファイル→インポート→Existing Android Code Into WorkSpace(既存のAndroidコードをワークスペースへ)」を選択します。解凍したフォルダーは、さらにフォルダー別けされているんですが、Eclipseでインポートするときに解凍したフォルダーのルートあたりを参照すれば、.EclipseさんがAndroidのファイルを探してくれて、サンプルとライブラリー全てを見つけ出してくれます。サンプルは、好きな奴だけインポートすればいいんですけど、opencv/sdk/javaにあるライブラリーだけは、必ずインポートするようにしてください。


3. 環境構築完了

終わりです!他のブログなんかには、C++を変換するAndroid NDKがどうとか書かれているんですけど、OpenCVの結果だけを知りたい場合やC++で開発しねーしってな場合は、Android NDKの設定とか必要ありません。



4. サンプルにエラーが表示される

以下の理由が考えられます。

  • ライブラリーが正しく参照されていない。
  • Android NDKの設定が必要

OpenCVのライブラリーが正しく参照されていない
それぞれのサンプルは、OpenCV Library 2.x.xなるライブラリーを参照する必要があります。ライブラリーが正しく参照されているか確認するには、パッケージエクスプローラで対象のサンプルアプリの上で右クリックして、プロパティ→Android→ライブラリーの部分を確認しください。エラーの場合は、バツ印が表示されているはず。追加でOpenCV Libraryを選択すればオッケーなはず。


Android NDKの設定が必要
 srcやresのならびに、jniのフォルダーがあるサンプルアプリの場合は、Android NDKの設定が必要です。C++の変換を行うんですが、C++なんてしらねーし。って事で諦めましょう。




5. Javaだけで顔の認識をさせてみる

サンプルの中に、顔認識のアプリであるOpenCV Sample face-detectionなるアプリがあるのですが、なんでか、C++のコードとまぜまぜに書かれています。なので、Android NDKの設定が必要で、上の手順どおりだとエラーが表示されるはず。これをJavaの部分だけをピックアップしてみたのがこのコード。NDK無しで動くはずです。

 https://www.dropbox.com/s/2pf7l3t00ibb3ly/OpencvDetectionJavaOnly.zip

コードの中にも書いてるんですけど、読み込むxmlファイルを変えれば、検出する部位も変えれるっぽいです。







 

 

Androidさんで、文字列を取得するときは、ローカライズされたstrings.xmlを使うわけですが、この中でHTMLのタグを使えるっぽいです。使えるHTMLのタグは、限定的で文字の装飾だけだと思われます。たぶん。

文字列のスタイルで使えるタグ
  • <b> : 強調文字
  • <i> : 斜体文字
  • <u> : 下線文字

AndroidでHTMLのタグを使う


使い方は、HTMLのタグを打ち込むときと一緒。strings.xmlでこんな感じに書きます
<string name="styledText"><i>斜体文字</i><b>強調文字</b><u>下線文字</u></string>

 

タグの使い方

layoutの中から、呼び出すこともできるし、
 
        <TextView
            android:id="@+id/test"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/styledText" />

プログラムのActivity上からも呼び出せます。
getText(  R.string.styledText );
getTextと似たメソッドにgetStringがあるんですけど、getStringで呼び出した場合は、タグは、無視される模様。



 

Androidは、多言語化を前提としてフレームワークが組まれています。で、文字列のファイルは、言語毎にres/values/strings.xmlに入ってます。このstrings.xmlで定義した文字列を取得する方法は、Activity内であれば

 getString(int)
 もしくは、

 getText(int)
 
で、呼び出せます(Activity外で使いたい場合は、その外のクラスにactivityのContextを渡してやって、context.getString()で呼び出せます。)。intの部分は、strings.xmlで指定したnameの値を、R.string.STRING_NAMEで指定してやります。たとえば、strings.xmlで下記の一文を指定したばあい

<string name="unko">Big Unko</string>

getText(R.string.unko);
で、Big Unkoが呼び出されます。


多分、getStringとgetTextに違いはそんなに無いんんじゃないのかと思うんですけど、あえて、違いをあげるならば、

getString()のいいところ


getStringでは、 文字列の置き換えができます。たとえば、笑顔を評価するゲームアプリを作ってて、「あなたの評価は、10点でした」と表示させたい場合、10の部分は、それぞれの笑顔によって左右されると思います。で、そんな場合は、strings.xmlで

<string name="score">あなたの笑顔は、%1$s点でした</string>

まんまなんですけど、%1$sの部分が置き換えられる文字列です。getString()で呼び出すときに、引数に置き換えたい文字列を入れます。

getString(R.string.score, "10");

%1$sは、第一引数の文字列を指定してます。複数個の文字列を置き換えたい場合は、%2$sみたいに、%1の部分を%2にすればいいのかと。きっと引数は、何個でも大丈夫です。

たとえば、こんな感じでstrings.xmlを指定して
<string name="score2">%2$sさんの%3$sは、%1$s点でした</string>

引数にそれぞれの文字列を指定してやります
getString(R.string.score2, "10", "はやと", "ニヒルな笑み");

すると、きっと、「はやとさんのニヒルな笑みは、10点でした」って文字列が取得されるはず。


getText()のいいところ

これ、知らなかったんですけど、strings.xml内で<i>斜体文字</i>とかが使えるみたい。未検証(書いた→Androidの文字のスタイルにHTMLのタグを利用する)。






 

Androidで、アニメーションがあるgifをImageViewで表示させることはできません。で、アニメーションを含むgifを表示させるには、以下の方法があるみたいです。
  • android.graphics.Movieを使う
  • gifからBitmapを抜き出して表示させる
  • webViewを使って表示する

で、一番簡単そうなWebViewを使って、gifを表示させたいと思います!WebViewは重たいとか言ってるブログも見かけたので、アプリのスピードを気にする人にはお勧めしません。だけど、超簡単。

webviewを拡張したviewクラスを作成

public class GifWebView extends WebView {

	public GifWebView(Context context, String path) {
		super(context);
		loadUrl(path);
	}
}
これだけ!あとは、GifWebViewを作成するときに、表示したいgifのパスを渡してやればいいだけ!

きっとだいたいこんな感じ

LinearLayout target = (LinearLayout)findViewById(R.id.insertTarget);

//.gifが無いと表示してくれないみたいです
String path = "somewhere.gif";

//端末内のファイルを読み込む場合は、file:///をつけないといけないみたい
GifWebView gif = new GifWebView(this,  "file:///" + path);

//gifをインサート
target.addView(gif);

Activity内から呼び出しています。また、このActivityで使うレイアウトにidがinsertTargetのLinearLayoutを設置しています。


pathでは、gifが保存されている場所を指定してください。また、拡張子がついてないとgifとして読み込んでくれないみたいです。あと、Android端末内のファイルを指定する場合は、file:///をつけないといけないみたいです。gifがウェブ上のどこかにある場合は、http://でいいのではないかと勝手に思ってます。







 

画像をAndroidの内部に保存する方法です。ひっかかったのがAndroidさんは、pngやjpgなんかは、Bitmapとして扱えるんですけど、gifは、bitmapとして扱えないみたい・・・。

pngやjpgを保存する

public String saveBitmap(Bitmap image, Context cx){
	String fileName = "filename"; 
	
	//保存先のファイル
	File file = new File(cx.getExternalCacheDir (), fileName);
	FileOutputStream outputStream;
	try {
		//change image scale
		// Bitmap resized =  Bitmap.createScaledBitmap(bmp, 100, 100, false);
	 
	  outputStream = new FileOutputStream(file);
	  image.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
	  
	  outputStream.close();
	} catch (Exception e) {
	  e.printStackTrace();
	}	
	
	return fileName;
}
今書いてるコードから抜き出して、なんとなく書き換えただけなので、凄い適当なメソッドです。外部の一時フォルダーに保存するためにContextを渡してます。

肝となるのは、
image.compress(Bitmap.CompressFormat.PNG, 90, outputStream);
このcompressじゃないのかと。第一引数で画像の拡張子を指定して、第二引数で画質の指定、第三引数に出力するオブジェクトを渡します。また、PNGを指定した場合は、第二引数は意味がありません。





 

このページのトップヘ