SATCHのViewFlipperを使ってみます。

絵画を検出したら、情報表示サイトを開いて、その絵を所蔵している美術館をGoogle Mapsで見てみましょう。

こんな感じです

絵画の検出には、SATCHを使ってArt_ProjectでAR(マルチ・トラッキング)で使ったやり方を使用。

絵画は、The Starry Night、Ophelia、The Cathedralの3つを使います。

絵画を検出していない場合





メニュの「Map View」をタップすると、GPSで取得した現在地を表示。





GPSでの位置情報が取得できていない場合、とりあえず「富士山」にロケーションされています。





「Web View」をタップすると、ただのGoogleの検索画面を表示。





絵画を検出した場合

黄色い文字が表示されれば、検出OKです。

黄色い文字が表示された状態のままで、以下を実行。





メニュの「Map View」をタップすると、この絵画を所蔵する美術館の場所を表示。





「Web View」をタップすると、絵画についての情報を表示。





以上

TOP

SATCHのtracking.luaのコード

絵画の検出については、SATCHを使ってArt_ProjectでAR(マルチ・トラッキング)を参照。



【tracking.lua】

local text = Text2D(getCurrentScene():getObjectByName("text"))

local componentInterface = getComponentInterface()

-- GLOBAL VARIABLES
-- tracking statuts: if 1 : tracking, if 0 : no tracking
gtrackingStatus = 0


-- get the keyframe index from a tracked object with auto-initialization
gtrackingKeyFrameIndex = -1



-- scene
local scene = getCurrentScene()
-- get the virtual camera, will be used to send to the MLT
local camera = Camera(scene:getCurrentCamera())
-- get the videocapture, will be used to send to the MLT
local videoCapture_live = VideoCapture(scene:getObjectByName("videocapture_live"))

-- Tracking
local MLTPlugin = getMLTPluginManager()
-- Error status
local errorStatus = eOk
-- tracking index : the index of the tracker.xml (because we can open more than 1 tracking.xml file).
local trackingIndex = -1
-- the fps of the Tracking engine
local trackingRate = 0
-- vector to put the tracking position
local trackingPosition = Vector3()
-- quaternion to put the tracking orientation
local trackingOrientation = Quaternion()
-- 3D object receiving tracking pose
--local trackingObject = Object3D(scene:getObjectByName("Tracking_Object"))
-- object index from the tracking scenario (0 : first object, 1 : second object...) (this is the index in the "Objects" panel of the CV GUI)
local trackingObjectIndex = 0

--検出時やロスト時にメッセージを1回だけ出すためのフラグ
local found_sendflag = false
local lost_sendflag = false

-- this is how to start a tracking. the function needs the path to the tracker.xml file, the videocapture id and the camera object.
errorStatus, trackingIndex = MLTPlugin:startTracking("tracker/tracker.xml", videoCapture_live:getVidCapID(), camera)

-- if the tracking has correctly started, we can proceed to an infinite loop
if errorStatus == eOk then
    
    
    
    repeat
        
        
        errorStatus, gtrackingStatus = MLTPlugin:getTargetStatus(trackingIndex, trackingObjectIndex)
        
        errorStatus, gtrackingKeyFrameIndex = MLTPlugin:getRecognizedKeyFrameIndex(trackingIndex, trackingObjectIndex)
        
        -- if our object is detected...
        if (gtrackingStatus == 1) then
            if found_sendflag == false then
                if gtrackingKeyFrameIndex == 0 then
                    text:setText("The Starry Night(Vincent van Gogh)")
                    
                    componentInterface:executeAppFunc("setTrackingStatus","StarryNight")
                    
                elseif gtrackingKeyFrameIndex == 1 then
                    text:setText("Ophelia(Sir John Everett Millais)")
                    
                    componentInterface:executeAppFunc("setTrackingStatus","Ophelia")
                    
                elseif gtrackingKeyFrameIndex == 2 then
                    text:setText("The Cathedral(Frantisek Kupka)")
                    
                    componentInterface:executeAppFunc("setTrackingStatus","Cathedral")
                    
                end
                
                found_sendflag = true
                lost_sendflag = false
            end
            text:setVisible(true)
        -- if the tracking is lost
        else
            if lost_sendflag == false then
                text:setVisible(false)
                
                componentInterface:executeAppFunc("setTrackingStatus","lost")
                
                found_sendflag = false
                lost_sendflag = true
            end
        end
        
        
        
    until coroutine.yield()
end


SATCHのシナリオを「com.kddi.satch.xxxxxx」で保存。

xxxxxxのところは、ご自分で適当に設定してください。

このアプリケーションIDは、EclipseのAndroidManifest.xmlのパッケージ名と一致させます。

でないと、アプリをデプロイする際に、ライセンスエラーになります。

TOP

Eclipseのプロジェクト

ソースはSATCHのViewFlipperを参照。

ダウンロードできるようにしておきましたので、なんかの参考にしていただければ...。

ViewFlipper

このままでは、素直に使えません(^^)。

これをベースにして、プロジェクトを再作成してください。

その際必要なのは、

com.kddi.satch.sampleviewflipperのプロジェクト名をSATCHのシナリオ作成で使ったものに変更。
res/layout/map.xmlのGoogleのキーを自分のものに変更(この辺はSATCHのDevelopers siteのViewFlipperを参照)

GPSを使うので、AndroidManifest.xmlに以下を追加。

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />


javaファイルで基本的に変更がかかるのは、SampleViewFlipper.javaだけです。

参考になるかどうか分かりませんが例です。SATCHのオリジナルと異なるのは、GPSの位置情報取得用のコードを入れています。

Mapsのオーバーレイを表示する部分は、参考にならないかも(^^)。


package com.kddi.satch.artdetectmultiviewflipper;

import java.util.List;

import com.google.android.maps.*;
import android.location.*;


import com.kddi.satch.artdetectactivity.ArtdetectActivity_simpleMap;

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ViewFlipper;

public class ArtDetectionMultiActivity extends ArtdetectActivity_simpleMap{
    private static final String       THIS_CLASS_SHORT_NAME = ArtDetectionMultiActivity.class.getName().replace("com.kddi.satch.artdetectmultiviewflipper.", "");
    private static final String     THIS_LOGTAG           = THIS_CLASS_SHORT_NAME;
    private static final String     SCENARIO_NAME         = "/assets/Scenario/Scenario_a/artDetection_multi.dpd";
    
    protected String   getSampleScenarioName() { return SCENARIO_NAME; }
    protected String   getSampleLogTag()     { return THIS_LOGTAG;   }
        
    
    private ViewFlipper               _viewFlipper; 

    private MapView                  _mapView;
    private GoogleMapsItemizedOverlay _itemizedoverlay1;
    private GoogleMapsItemizedOverlay _itemizedoverlay2;
    private   OverlayItem             _overlayitem1;
    private   OverlayItem             _overlayitem2;
    private GeoPoint                    _point1;
    private GeoPoint                    _point2;
    
    private WebView                  _webView;

    
    private String    _urlTargetPlace;
    private boolean _trackingStatus;
    
    private LocationManager mLocationManager;
    
    
    private static final int    MENU_VIEW_DFUSION    = 0;
    private static final int    MENU_VIEW_WEB       = 1;
    private static final int    MENU_VIEW_MAP      = 2;
    private static final int            MENU_STREET_VIEW    = 3;
    


    private void resetMembers()
    {
        _viewFlipper = null; 

        _mapView = null;
        _itemizedoverlay1 = null;
        _itemizedoverlay2 = null;
        _overlayitem1 = null;
        _overlayitem2 = null;
        _point1 = null;
        _point2 = null;
        
        _webView = null;

        //_trackingX = _trackingY = _trackingZ  = 0;
        
        //prev_lat1 = prev_lat1 = 0;
        
        _trackingStatus = false;
        _urlTargetPlace = "http://www.google.com";
    }
   
    
    @Override
    protected boolean isRouteDisplayed()
    { // from MapActivity
        return false;
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        //Log.i( getSampleLogTag(),       ".... onCreate" );    
        
        super.onCreate(savedInstanceState);
        
        // initialize values 
        resetMembers();
        
        // initialize inflated views
        {// Web view
            LayoutInflater li = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            _webView = (WebView) li.inflate(R.layout.web, null);
            initWebView();
        }
        {// Map view
            LayoutInflater li = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            _mapView = (MapView) li.inflate(R.layout.map, null);
            initMapView();
            
             
        }
        
        mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
        Criteria criteria = new Criteria();   
        criteria.setAccuracy(Criteria.ACCURACY_FINE);  
        criteria.setAltitudeRequired(false);
        criteria.setBearingRequired(false);
        criteria.setCostAllowed(false);
        criteria.setPowerRequirement(Criteria.POWER_LOW);
        criteria.setSpeedRequired(false);
        String provider = mLocationManager.getBestProvider(criteria, true);
        mLocationManager.requestLocationUpdates(provider,    
                1000,
                1,
                locationListener);
        //
    }
    
    
    @Override
    public void onDestroy() {
        //Log.i( getSampleLogTag(),       ".... onDestroy" ); 
        
        // release what we inflated
         _mapView = null;
         _webView = null;

        super.onDestroy();
        
        // final clean-up
        resetMembers();       
        
        
    }
    
    @Override
    public void postInitComponent()
    {
        //Log.i( getSampleLogTag(),       "postInitComponent" );    

        _kddiComponent.activateAutoFocusOnDownEvent(true);
        
        _kddiComponent.registerCommunicationCallback("setTrackingStatus", this, "setTrackingStatus");
        
        
    }
    
    @Override
    public void initContentView()
    { 
        //Log.i( getSampleLogTag(),       "initContentView" );

        if (_isInitializedCorrectly)
        {
            _viewFlipper = new ViewFlipper(this);
            
            // Child 0 : Detect Artworks 
            _viewFlipper.addView(_frameLayout);
        
            // Child 1 : Web View
            _viewFlipper.addView(_webView);
            
            // Child 2 : Map View
            _viewFlipper.addView(_mapView);
            
            // Activity content view will be the view flipper
            setContentView(_viewFlipper);
            
            new Handler().postDelayed(new Runnable() {
                        public void run() {
                            openOptionsMenu();
                        }
                    }, 1000
                );
        }
    }
    
    @Override
    public void releaseContentView() {
        //Log.i( getSampleLogTag(),       "releaseContentView" );

        if (_isInitializedCorrectly)
        {
            if (_viewFlipper != null) {
                _viewFlipper.removeAllViews();
            }
            _viewFlipper = null;
        }
    }    
    
    
    public void setTrackingStatus(String [] arrayOfString)
    {
        //Log.i("STATUS",arrayOfString[0]);
        
        if(arrayOfString.length ==1){
            if(arrayOfString[0].equals("StarryNight")){
                _trackingStatus = true;
                setMuseumPosition(40.761484, -73.977664);
                //_urlTargetPlace = "http://wisteriahill.sakura.ne.jp/jqm_viewflipper/index.html";
                _urlTargetPlace = "http://ja.wikipedia.org/wiki/%E6%98%9F%E6%9C%88%E5%A4%9C";
                
            }else if(arrayOfString[0].equals("Ophelia")){
                _trackingStatus = true;
                setMuseumPosition(51.490833, -0.127222);
                _urlTargetPlace = "http://en.wikipedia.org/wiki/Ophelia_(painting)";
                
            }else if(arrayOfString[0].equals("Cathedral")){
                _trackingStatus = true;
                setMuseumPosition(50.087222, 14.408611);
                _urlTargetPlace = "http://wisteriahill.sakura.ne.jp/jqm_viewflipper/cathedral.html";
                
            }else if(arrayOfString[0].equals("lost")){
                _trackingStatus = false;
                _urlTargetPlace = "http://www.google.fr";
                _point2 = null;
                
            }
        }
    }
    
    
    public void setMuseumPosition(double latitude,double longitude)
    {
            int lat2 = (int)(latitude*1E6);
            int lon2 = (int)(longitude*1E6);
            _point2 = new GeoPoint(lat2,lon2);
    }
    
    
    public void setTrackingStatus(boolean trackingStatus)
    {
        _trackingStatus = trackingStatus;
    }  
    
    
    public void setUrlTargetPlace(int target_num)
    {
        
        MapController ctrl = _mapView.getController();
        if(ctrl != null){
            List<Overlay> mapOverlays = _mapView.getOverlays();
            
            mapOverlays.clear();   
            
            initMapView();

            
            
            if(target_num == 1){
                ctrl.setCenter(_point1);
                
                
            }else if(target_num == 2){
                ctrl.setCenter(_point2);

            }
        }
        _webView.loadUrl(_urlTargetPlace);
    }
    
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        
        
        menu.add(0, MENU_VIEW_DFUSION,  0, "Detect Artworks").setIcon(R.drawable.sunflowers);
        menu.add(0, MENU_VIEW_WEB,    0, "Web view").setIcon(R.drawable.web);
        menu.add(0, MENU_VIEW_MAP,    0, "Map view").setIcon(R.drawable.map);
        //menu.add(0, MENU_STREET_VIEW,   0, "StreetView").setIcon(R.drawable.pegman);
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) 
    {
        switch ( item.getItemId() )
        {
            case MENU_VIEW_DFUSION:
                _viewFlipper.setDisplayedChild(0);
                return true;
            case MENU_VIEW_WEB:
                _viewFlipper.setDisplayedChild(1);
                return true;
            case MENU_VIEW_MAP:
                
                
                _viewFlipper.setDisplayedChild(2);
                
                if (_trackingStatus == true){
                    setUrlTargetPlace(2);
                } else{
                    setUrlTargetPlace(1);
                }
                return true;
            case MENU_STREET_VIEW:
                
                
                return true;
        }
        return false;
    }
    
    private class MyWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    } 
    
    public void initMapView()
    {
        _mapView.setBuiltInZoomControls(true);
        
        
        
        List<Overlay> mapOverlays = _mapView.getOverlays();
        
        //overlay2
        Drawable drawableMuseum = this.getResources().getDrawable(R.drawable.museum);
        _itemizedoverlay1 = new GoogleMapsItemizedOverlay(drawableMuseum, this.getApplicationContext());
        
        if (_point2 == null){
            double latitude2 = 0;//dummy
            double longitude2 = 0;//dummy
            
            int lat2 = (int)(latitude2*1E6);
            int lon2 = (int)(longitude2*1E6);
            _point2 = new GeoPoint(lat2,lon2);
            _overlayitem2 = new OverlayItem(_point2, "Hello!", "I'm 2");
            _itemizedoverlay1.addOverlay(_overlayitem2);
        }else{
            _overlayitem2 = new OverlayItem(_point2, "Hello!", "I'm 2");
            _itemizedoverlay1.addOverlay(_overlayitem2);
            mapOverlays.add(_itemizedoverlay1);
        }
        
        
        // overlay1
        Drawable drawableMyloc = this.getResources().getDrawable(R.drawable.person);
        _itemizedoverlay2 = new GoogleMapsItemizedOverlay(drawableMyloc, this.getApplicationContext());
        
        if (_point1 == null) {
            double latitude1 = 35.36286726458948;
            double longitude1 = 138.73157501220703;
            int lat1 = (int)(latitude1*1E6);
            int lon1 = (int)(longitude1*1E6);
            _point1 = new GeoPoint(lat1,lon1);
        }
        
        _overlayitem1 = new OverlayItem(_point1, "Hello!", "I'm 1");
        
        _itemizedoverlay2.addOverlay(_overlayitem1);
        mapOverlays.add(_itemizedoverlay2);
        
        
    }
    
    public void initWebView()
    {
        _webView.getSettings().setJavaScriptEnabled(true);
        _webView.getSettings().setBuiltInZoomControls(true);
        _webView.getSettings().setSupportZoom(true);
        
        final ArtDetectionMultiActivity activity = this;
        _webView.setWebChromeClient(new WebChromeClient() {
            public void onProgressChanged(WebView view, int progress) {
                // Activities and WebViews measure progress with different scales.
                // The progress meter will automatically disappear when we reach 100%
                ((Activity) activity).setProgress(progress * 1000);
            }
        });

        // to handle its own URL requests : 
        _webView.setWebViewClient(new MyWebViewClient());
        _webView.loadUrl("http://www.google.fr");
    }
    
    //------------------------------------
    
    private LocationListener locationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            double latitude = location.getLatitude();
            double longitude = location.getLongitude();
            int lat = (int)(latitude*1E6);
            int lon = (int)(longitude*1E6);
            _point1 = new GeoPoint(lat,lon);
            
            
        }
    
        @Override
        public void onProviderDisabled(String provider) {
        }
    
        @Override
        public void onProviderEnabled(String provider) {
        }
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            switch (status) {
                case LocationProvider.AVAILABLE:
                    //Log.v("Status", "AVAILABLE");
                    break;
                case LocationProvider.OUT_OF_SERVICE:
                    //Log.v("Status", "OUT_OF_SERVICE");
                    break;
                case LocationProvider.TEMPORARILY_UNAVAILABLE:
                    //Log.v("Status", "TEMPORARILY_UNAVAILABLE");
                    break;
            }
        }
    };
}




コード内のパッケージ名やファイル名、SCENARIO_NAMEのパスは修正してください。





TOP

公開用Google ApiKey取得

ViewFlipperサンプルでは、MapViewを使ってGoogle Mapsを表示しています。

このサンプルを使って新しくプロジェクトを作成し  apkを公開する場合、公開用のGoogle Apiキーを取得する必要があります。  

New
以下は、Google Maps Android API v1用のキーについての記述です。
Google Maps Android API v2では、キー取得の方法が変わっていますので、ご注意ください。  

 ここでは、既にキーストアが作成されているものとします。  

 キーストアの作成やデジタル署名したapkの作成方法は、
PhoneGapでネイティブアプリ の、「ネイティブアプリを作って、ダウンロード・インストール」の項を参照。

まず、DOS窓を開きます。

以下のコマンドを発行。

keytool -list -v -keystore <作成したキーストアのフルパス>

New
keytoolコマンドのオプションに-vを追加しました。

vオプションが無い場合は、SHA1のフィンガープリントしか表示してくれないようです。

vオプションをつけることで、MD5/SHA1/SHA256の3つのフィンガープリントを表示してくれます。

Google Maps Android API v1では、MD5を使います。

パスワードを聞いてきますので、これもキーストア作成時のパスワードを使用。

証明書のフィンガープリントが表示されます。


Sign Up for the Android Maps API のページを開きます。

ページの下の、I have read and agree ...にチェックを入れ、My certificate's MD5 fingerprint:の欄に先ほどのフィンガープリントを入力して、Generate API Keyのボタンをクリック。

表示されたキーが公開用のキーになります。

これを、res->layout->map.xmlのandroid:apiKeyにセットします。

これで、MapViewでGoogle Mapsが表示されるようになります。

TOP





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