ゴッホのひまわりを検出して、4ヵ国語で解説してみましょう
「ゴッホのひまわりを検出して、しゃべらせてみる」の姉妹編。
日本語・英語・フランス語・オランダ語の4ヵ国語です。
ご注意!
個人所蔵の「3本の向日葵」は、検出に手間がかかります。
データ作成のための元絵の解像度が低かったのが原因....だと思います。
こんな画像でデータを作りました。
TOP
【継承クラス】
TOP
起動
初回起動時には以下のようなメッセージが出ますが、気にしないでください。「はい」でも「いいえ」でも、どちらでもいいです。
起動後、7~8秒、真っ暗ですが問題ないです。
デフォルトは英語です。
メニュを開いて、ボタンをタップするとその国の言語で表示。
カメラを絵に向けて、その絵を認識すると、文字を表示します。
絵のサイズはある程度大きなものにしてください。あまりに小さいと検出に失敗します。
TOP
トップページ| サイトマップ|
日本語・英語・フランス語・オランダ語の4ヵ国語です。
対象作品
検出対象は、現存する以下の6点。
(Wikipediaから引用)
1888年8月に制作されたとされる3点
15本の向日葵(ナショナル・ギャラリー)
3本の向日葵(個人所蔵)
1889年1月に制作されたとされる3点
15本の向日葵(ゴッホ美術館)
15本の向日葵(損保ジャパン東郷青児美術館)
12本の向日葵(フィラデルフィア美術館)
こんな感じです。
TOP
SATCHシナリオ作成
SATCHでのシナリオのつくり方は以下を参照。
SATCHを使ってArt_ProjectでAR(マルチ・トラッキング)
ご注意!
個人所蔵の「3本の向日葵」は、検出に手間がかかります。
データ作成のための元絵の解像度が低かったのが原因....だと思います。
こんな画像でデータを作りました。
TOP
Eclipseでアプリ作成
Eclipse側の基本コードはこのページを参照
Eclipse側のコードはこんな感じ。
vvvv,xxxx,yyyy,zzzzは適当に読み替えてください。
【抽象クラス】
package com.kddi.satch.xxxx; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.Handler; import android.view.KeyEvent; import android.view.View; import android.widget.FrameLayout; import com.kddi.satch.LoadScenarioStatus; import com.kddi.satch.ARViewer; import android.util.Log; import java.util.Locale; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.TextView.BufferType; import android.view.WindowManager.LayoutParams; import android.os.Handler; public abstract class xxxx_simple extends Activity { protected abstract String getSampleScenarioName(); protected abstract String getSampleLogTag(); public TextView Text_View; public LinearLayout textLayout; private Handler mHandler; private String textview_content = ""; public String disp_lang = "en"; public String str_content = ""; protected boolean _isInitializedCorrectly; protected ARViewer _kddiComponent; protected FrameLayout _frameLayout; public void resetMembers(){ _isInitializedCorrectly = false; _frameLayout = null; _kddiComponent = null; } private static final int DIALOG_EXIT = 0; public void initComponent(){ _isInitializedCorrectly = false; _kddiComponent = new ARViewer(this); // This FrameLayout must be empty (but initialized) when you pass it to the kddiComponent.initialize() method. _frameLayout = new FrameLayout(this); _kddiComponent.initialize(_frameLayout); _isInitializedCorrectly = true; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Add null to AR Viewer Library compornent's reference. resetMembers(); mHandler = new Handler(); } @Override public void onRestart() { super.onRestart(); } @Override public void onStart() { super.onStart(); // Create AR Viewer Library compornent. initComponent(); postInitComponent(); initContentView(); if (_isInitializedCorrectly) { // Do authorize and madia is loaded. // You must call loadScenario() method. loadScenario(); } } @Override public void onResume(){ super.onResume(); if (_isInitializedCorrectly) { // GL context is recreated and media is reloaded. _kddiComponent.onResume(); reservePlayScenario(); } } @Override public void onPause() { // When the activity is paused the GL context is destroyed, so all media is unloaded. if (_isInitializedCorrectly) { cancelReservePlayScenario(); if (_kddiComponent.checkLoadScenarioStatus() == LoadScenarioStatus.COMPLETE) { _kddiComponent.pauseScenario(); } _kddiComponent.onPause(); } super.onPause(); } @Override public void onStop() { releaseContentView(); // Destroy AR Viewer Library Objects. if (_isInitializedCorrectly){ _kddiComponent.terminate(); _kddiComponent = null; _frameLayout = null; } super.onStop(); } @Override public void onDestroy() { // Destroy AR Viewer Library Objects. if (_isInitializedCorrectly){ _frameLayout = null; _kddiComponent = null; } super.onDestroy(); resetMembers(); // forced clean } @Override public boolean onKeyDown(int keyCode, KeyEvent msg){ switch(keyCode){ case android.view.KeyEvent.KEYCODE_BACK : showDialog( DIALOG_EXIT ); return true; } return false; } public void postInitComponent(){ // override this if you need to do some special handling on the component after standard initialization if (_isInitializedCorrectly) { _kddiComponent.activateAutoFocusOnDownEvent(true); } } public void initContentView(){ // override this if you need to do some special handling on the component after standard initialization if (_isInitializedCorrectly) { // you'll probably use some other UI object as the content view that itself will embed the component's frame layout -- here you can change all this // by default, the frame layout containing DFusion will be the activity content view setContentView(_frameLayout); } // textLayout = new LinearLayout(this); Text_View = new TextView(this); Text_View.setText(""); textLayout.addView(Text_View, new LinearLayout.LayoutParams(200,200)); //textLayout.setVisibility(View.VISIBLE); addContentView(textLayout, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); } public void set_text(){ if (str_content.equals("private")) { if (disp_lang.equals("ja")) { textview_content = "3本の向日葵" + "\n" + "油彩・キャンヴァス" + "\n" + " 73 ×58cm" + "\n" + "個人所蔵"; }else if (disp_lang.equals("en")) { textview_content = "First version" + "\n" + "Oil on canvas" + "\n" + " 73 ×58cm" + "\n" + "Private collection"; }else if (disp_lang.equals("fr")) { textview_content = "Vase avec trois tournesols" + "\n" + "Peinture à l'huile,toile" + "\n" + " 73 ×58cm" + "\n" + "Collection privée"; }else if (disp_lang.equals("nl")) { textview_content = "Vaas met drie zonnebloemen" + "\n" + "Olieverf op doek" + "\n" + " 73 ×58cm" + "\n" + "Privé collectie"; } }else if (str_content.equals("gogh")){ if (disp_lang.equals("ja")) { textview_content = "15本の向日葵" + "\n" + "油彩・キャンヴァス" + "\n" + " 95 ×73cm" + "\n" + "ゴッホ美術館所蔵"; }else if (disp_lang.equals("en")) { textview_content = "Repetition of the 4th version" + "\n" + "Oil on canvas" + "\n" + " 95 ×73cm" + "\n" + "Van Gogh Museum"; }else if (disp_lang.equals("fr")) { textview_content = "Vase avec quinze tournesols" + "\n" + "Peinture à l'huile,toile" + "\n" + " 95 ×73cm" + "\n" + "Musée van Gogh"; }else if (disp_lang.equals("nl")) { textview_content = "Vaas met vijftien zonnebloemen" + "\n" + "Olieverf op doek" + "\n" + " 95 ×73cm" + "\n" + "Van Gogh Museum"; } }else if (str_content.equals("sompo")){ if (disp_lang.equals("ja")) { textview_content = "15本の向日葵" + "\n" + "油彩・キャンヴァス" + "\n" + " 100.5 ×76.5cm" + "\n" + "損保ジャパン東郷青児美術館所蔵"; }else if (disp_lang.equals("en")) { textview_content = "Replica of the 4th version" + "\n" + "Oil on canvas" + "\n" + " 100.5 ×76.5cm" + "\n" + "Sompo Japan Museum of Art"; }else if (disp_lang.equals("fr")) { textview_content = "Vase avec quinze tournesols" + "\n" + "Peinture à l'huile,toile" + "\n" + " 100.5 ×76.5cm" + "\n" + "Musée d'art Sompo"; }else if (disp_lang.equals("nl")) { textview_content = "Vaas met vijftien zonnebloemen" + "\n" + "Olieverf op doek" + "\n" + " 100.5 ×76.5cm" + "\n" + "Sompo Japan Museum of Art"; } }else if (str_content.equals("national")){ if (disp_lang.equals("ja")) { textview_content = "15本の向日葵" + "\n" + "油彩・キャンヴァス" + "\n" + " 92.1 ×73cm" + "\n" + "ナショナルギャラリー所蔵"; }else if (disp_lang.equals("en")) { textview_content = "Fourth version" + "\n" + "Oil on canvas" + "\n" + " 92.1 ×73cm" + "\n" + "National Gallery"; }else if (disp_lang.equals("fr")) { textview_content = "Vase avec quinze tournesols" + "\n" + "Peinture à l'huile,toile" + "\n" + " 92.1 ×73cm" + "\n" + "National Gallery"; }else if (disp_lang.equals("nl")) { textview_content = "Vaas met vijftien zonnebloemen" + "\n" + "Olieverf op doek" + "\n" + " 92.1 ×73cm" + "\n" + "National Gallery"; } }else if (str_content.equals("neue")){ if (disp_lang.equals("ja")) { textview_content = "12本の向日葵" + "\n" + "油彩・キャンヴァス" + "\n" + " 91 ×72cm" + "\n" + "ノイエ・ピナコテーク所蔵"; }else if (disp_lang.equals("en")) { textview_content = "Third version" + "\n" + "Oil on canvas" + "\n" + " 91 ×72cm" + "\n" + "Neue Pinakothek"; }else if (disp_lang.equals("fr")) { textview_content = "Vase avec douze tournesols" + "\n" + "Peinture à l'huile,toile" + "\n" + " 91 ×72cm" + "\n" + "Neue Pinakothek"; }else if (disp_lang.equals("nl")) { textview_content = "Vaas met twaalf zonnebloemen " + "\n" + "Olieverf op doek" + "\n" + " 91 ×72cm" + "\n" + "Neue Pinakothek"; } }else if (str_content.equals("philadelphia")){ if (disp_lang.equals("ja")) { textview_content = "12本の向日葵" + "\n" + "油彩・キャンヴァス" + "\n" + " 91 ×72cm" + "\n" + "フィラディルフィア美術館所蔵"; }else if (disp_lang.equals("en")) { textview_content = "Repetition of the 3rd version" + "\n" + "Oil on canvas" + "\n" + " 91 ×72cm" + "\n" + "Philadelphia Museum of Art"; }else if (disp_lang.equals("fr")) { textview_content = "Vase avec douze tournesols" + "\n" + "Peinture à l'huile,toile" + "\n" + " 91 ×72cm" + "\n" + "Musée d'art de Philadelphie"; }else if (disp_lang.equals("nl")) { textview_content = "Vaas met twaalf zonnebloemen" + "\n" + "Olieverf op doek" + "\n" + " 91 ×72cm" + "\n" + "Philadelphia Museum of Art"; } }else{ textview_content = ""; } (new Thread(new Runnable() { @Override public void run() { mHandler.post(new Runnable() { @Override public void run() { // Text_View.setText(textview_content); } }); } })).start(); } public void releaseContentView(){ // override this if you need to do some special handling on the component after standard initialization if (_isInitializedCorrectly) { // do here the release of the your UI instances (if customized) } } public void loadScenario(){ ApplicationInfo appInfo = null; PackageManager packMgmr = getApplicationContext().getPackageManager(); try { appInfo = packMgmr.getApplicationInfo(getPackageName(), 0); } catch (NameNotFoundException e) { e.printStackTrace(); throw new RuntimeException("Unable to locate assets, aborting..."); } String dpdfile = appInfo.sourceDir + getSampleScenarioName(); _kddiComponent.loadScenario(dpdfile); } // Set polling rate for loading the media. private final int REPEAT_INTERVAL = 100; private Handler handler = new Handler(); private Runnable runnable = null; // private void reservePlayScenario(){ if (runnable == null){ runnable = new Runnable(){ @Override public void run(){ LoadScenarioStatus status = _kddiComponent.checkLoadScenarioStatus(); if (status == LoadScenarioStatus.CANCEL){ // cancel(appli suspend) }else if (status == LoadScenarioStatus.COMPLETE){ // Ready to play scenario _frameLayout.setVisibility(View.VISIBLE); _kddiComponent.playScenario(); }else if ( status == LoadScenarioStatus.ERROR_NETWORK_UNUSABLE || // faild to load a media becase of no network connection. status == LoadScenarioStatus.ERROR_NETWORK || // faild to load a media becase of network error. status == LoadScenarioStatus.ERROR_SOFTWAREKEY || // faild to load a media becase software key has not be found on server. status == LoadScenarioStatus.ERROR_CONTENT_STOPPED || // faild to load a media becase content has stopped. status == LoadScenarioStatus.ERROR_SERVER || // faild to load a media becase of server error. status == LoadScenarioStatus.ERROR_ETC // faild to load a media becase of another error. ){ // error }else{ handler.postDelayed(this, REPEAT_INTERVAL); } } }; handler.postDelayed(runnable, REPEAT_INTERVAL); } } // private void cancelReservePlayScenario(){ if (handler != null && runnable != null){ handler.removeCallbacks(runnable); runnable = null; } } protected Dialog onCreateDialog(int id) { Dialog dialog; switch(id) { case DIALOG_EXIT: { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage( "Really want to quit the application?" ) .setCancelable(true) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { finish(); }}) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); }}); dialog = builder.create(); break; } default: dialog = null; } return dialog; } }
【継承クラス】
package com.kddi.satch.yyyy; import com.kddi.satch.xxxx.xxxx_simple; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; public class zzzz extends xxxx_simple { private static final String THIS_CLASS_SHORT_NAME = zzzz.class.getName().replace("com.kddi.satch.yyyy.", ""); private static final String THIS_LOGTAG = THIS_CLASS_SHORT_NAME; // Set AR scenario file path. private static final String SCENARIO_NAME = "/assets/Scenario/Scenario_sunflower/vvvv.dpd"; protected String getSampleScenarioName() { return SCENARIO_NAME; } protected String getSampleLogTag() { return THIS_LOGTAG; } private String prev_val = ""; //menu private static final int MENU_JA = 0; private static final int MENU_EN = 1; private static final int MENU_FR = 2; private static final int MENU_NL = 3; @Override public void postInitComponent(){ super.postInitComponent(); // if (_isInitializedCorrectly) { _kddiComponent.activateAutoFocusOnDownEvent(true); _kddiComponent.registerCommunicationCallback("setTrackingStatus", this, "setTrackingStatus"); } } // @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } // public void onInit(int status) { // } //add public void setTrackingStatus(String[] arrayOfString) { Log.i("STAT",arrayOfString[0]); if (arrayOfString[0].equals(prev_val)) { Log.i("STAT","repeat"); return; } if (arrayOfString[0].equals("out")) { prev_val = ""; str_content = ""; set_text(); return; } str_content = arrayOfString[0]; set_text(); prev_val = arrayOfString[0]; } // public boolean onCreateOptionsMenu(Menu menu) { menu.add(0, MENU_JA,0, "日本語").setIcon(R.drawable.ja); menu.add(0, MENU_EN,0, "English").setIcon(R.drawable.en); menu.add(0, MENU_FR,0, "Français").setIcon(R.drawable.fr); menu.add(0, MENU_NL,0, "Nederland").setIcon(R.drawable.nl); return true; } public boolean onOptionsItemSelected(MenuItem item) { switch ( item.getItemId() ) { case MENU_JA: disp_lang = "ja"; set_text(); return true; case MENU_EN: disp_lang = "en"; set_text(); return true; case MENU_FR: disp_lang = "fr"; set_text(); return true; case MENU_NL: disp_lang = "nl"; set_text(); return true; } return false; } // }
TOP
インストールと起動
アプリ(apk)をインストール
ダウンロード後、通知パネルを開いて、完了メッセージの項をタップ。
起動
初回起動時には以下のようなメッセージが出ますが、気にしないでください。「はい」でも「いいえ」でも、どちらでもいいです。
起動後、7~8秒、真っ暗ですが問題ないです。
デフォルトは英語です。
メニュを開いて、ボタンをタップするとその国の言語で表示。
カメラを絵に向けて、その絵を認識すると、文字を表示します。
絵のサイズはある程度大きなものにしてください。あまりに小さいと検出に失敗します。
TOP
トップページ| サイトマップ|