「ゴッホのひまわりを検出して、しゃべらせてみる」の姉妹編。

日本語・英語・フランス語・オランダ語の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





トップページ| サイトマップ|