JCV AR SDK Android統合ドキュメント

目次

1.統合の準備

  • 1.1 リソースファイルの使用

  • 1.2 Android Studio ランタイム環境の設定

  • 1.3 JNI の難読化

2.SDK のアクティベーション

  • 2.1 ライセンスファイルを使用したアルゴリズムライブラリの認証

  • 2.2 モデルファイルの使用

  • 2.3 スタンプファイルの使用

3.シングルおよびダブル入力モード

  • 3.1 シングル入力モード

  • 3.2 ダブル入力モード

  • 3.3 最適化されたシングル入力モード

  • 3.4 最適化されたダブル入力モード

  • 3.5 入力モードの切り替え

4.SDK の API の使用

  • 4.1 SDK ハンドルの初期化

  • 4.2 カメラプレビューのテクスチャとデータの取得

  • 4.3 カメラプレビューのテクスチャとデータの処理

  • 4.4 フレーム処理フロー

  • 4.5 SDK ハンドルの解放

5.JNI API の概要

  • 5.1 STMobileCommon

  • 5.2 STMobileHumanActionNative

  • 5.3 STMobileFaceAttributeNative

  • 5.4 STBeautifyNative

  • 5.5 STMobileStickerNative

  • 5.6 STSoundPlay

  • 5.7 STMobileStreamFilterNative

  • 5.8 STMobileFilterNative

  • 5.9 STMobileObjectTrackNative

  • 5.10 STHumanAction

6.回転と方向に関する手順

  • 6.1 カメラの方向

  • 6.2 HumanAction API の方向

※一部コードが資料の都合上途切れている部分があります。サンプルコードと同じ内容が記載されておりますので、該当のサンプルコードにてご確認お願い致します。

1 統合の準備

1.1 リソースファイルの使用

  • Android Studio プロジェクトを開きます。ライセンスファイル、モデルファイル、スタンプなどのファイルを JCV AR SDK ディレクトリからプロジェクトのアセットフォルダーにコピーします。

  • ライセンスファイルの名前を「SenseME.lic」に変更し、アセットフォルダーにコピーします。

  • face_attribute_x.x.x.model や M_SenseME_Action_x.x.x.model を含むモデルファイルをアセットフォルダーにコピーします。

  • スタンプパッケージを "2D"、"3D"、"hand_action"、"deformation"、"segment" に分類し、アセットフォルダーにサブフォルダーを作成します。スタンプを分類し、名前が同じアイコンと一緒に、それぞれサブフォルダーにコピーします。アイコンがない場合は "なし" と表示されます。分類方法はカスタマイズできます詳細はサンプルの FileUtils ファイルをご参照ください。

  • アセットフォルダーに "filter_xx" という名前のフィルターカテゴリフォルダーを作成し、後で使用できるようにカスタム分類フィルターモデルを適切なフォルダーにコピーします。

1.2 Android Studio ランタイム環境の設定

  • 初めてサンプルプロジェクトを開くと、"NDK が見つかりません" というメッセージが表示される可能性があります。[プロジェクト] を右クリックし、[モジュール設定を開く]、[SDK の場所]、[Android NDK の場所] の順にクリックして、NDK のパスを設定します。

  • サンプルの JNI の部分をプロジェクトに統合するには、build.gradle プロジェクトに JNI の部分の依存関係を追加します。

dependencies {

    ... ...

    ////STMobileJNI の依存関係を追加します

    compile project(':STMobileJNI')

    ... ...

}

1.3 JNI の難読化

  • プロジェクトで STMobileJNI を引用するには、次のようにプロジェクトの proguard-rules.pro ファイルに JNI の難読化を追加します。

-keep class com.stmobile.* { *;}

-keep class com.stmobile.model.* { *;}

2 SDK のアクティベーション

2.1 ライセンスファイルを使用したアルゴリズムライブラリの認証

  • SDK は、アルゴリズムライブラリの権限をライセンスファイルと照合します。 認証された後にのみ、SDK の機能を使用できます。

  • SenseME.lic ファイルをアセットフォルダーにコピーした後、統合するために、次のように STLicenseUtils ユーティリティクラスの checkLicense() 関数のみを呼び出すことができます。

  1. まずlicenseファイルの内容を読み込みます。

  2. ローカルに保存されているアクティブコードを取得します。

  3. 利用可能なアクティベーションコードがない場合は、生成します。

  4. checkActiveCode* コマンドを直接実行して、アクティベーションコードが有効であるかどうか確認します。

  5. 確認に失敗した場合は、別のアクティベーションコードを生成します。

  6. 生成に失敗した場合は、エラーメッセージが表示されます。成功すると、新しいアクティベーションコードが保存され、成功したことを示すメッセージが表示されます。

private final static String PREF_ACTIVATE_CODE_FILE = "activate_code_file";

private final static String PREF_ACTIVATE_CODE = "activate_code";

private static final String LICENSE_NAME = "SenseME.lic";

/**

* 既存のアクティベーションコードが有効か確認します

* @return 成功した場合は true を、失敗した場合は false を返します

*/

public static boolean checkLicense(Context context) {

    StringBuilder sb = new StringBuilder();

    InputStreamReader isr = null;

    BufferedReader br = null;

    //ライセンスファイルの内容を確認します

    try {

        isr = new InputStreamReader(
            context.getResources().getAssets().open(LICENSE_NAME)
        );

        br = new BufferedReader(isr);

        String line = null;

        while((line=br.readLine()) != null) {

            sb.append(line).append("\n");

        }

    }

    ... ...



    //ライセンスファイルが空の場合、エラーメッセージが返されます

    if (sb.toString().length() == 0) {

        LogUtils.e(TAG, "read license data error");

        return false;

    }



    String licenseBuffer = sb.toString();

    SharedPreferences sp = context.getApplicationContext()
            .getSharedPreferences(
                PREF_ACTIVATE_CODE_FILE, 
                Context.MODE_PRIVATE
            );


    String activateCode = sp.getString(PREF_ACTIVATE_CODE, null);

    Integer error = new Integer(-1);

    if (activateCode == null || 
        (STMobileAuthentificationNative.checkActiveCodeFromBuffer(    
            context, 
            licenseBuffer, 
            licenseBuffer.length(), 
            activateCode, 
            activateCode.length()
        ) != 0)) {

        activateCode = STMobileAuthentificationNative
                .generateActiveCodeFromBuffer(
                    context, 
                    licenseBuffer, 
                    licenseBuffer.length()
                );



        if (activateCode != null && activateCode.length() >0) {

            SharedPreferences.Editor editor = sp.edit();

            editor.putString(PREF_ACTIVATE_CODE, activateCode);

            editor.commit();

            return true;

        }

        return false;

    }

    return true;

}

2.2 モデルファイルの使用

  • FileUtils ファイルを使用して、サンプルのモデルファイルを管理します。AssetsManager を使用してモデルファイルにアクセスできます。モデルファイルの使用方法については、サンプルをご参照ください。

public static final String MODEL_NAME_ACTION = 
    "M_SenseME_Action_5.5.1.model";

public static final String MODEL_NAME_FACE_ATTRIBUTE = 
    "M_SenseME_Attribute_1.0.1.model";

public static final String MODEL_NAME_EYEBALL_CENTER = 
    "M_Eyeball_Center.model";

public static final String MODEL_NAME_EYEBALL_CONTOUR = 
    "M_SenseME_Iris_1.11.1.model";

public static final String MODEL_NAME_FACE_EXTRA = 
    "M_SenseME_Face_Extra_5.6.0.model";

public static final String MODEL_NAME_BODY_FOURTEEN = 
    "M_SenseME_Body_Fourteen_1.2.0.model";

public static final String MODEL_NAME_HAND = 
    "M_SenseME_Hand_5.0.0.model";

public static final String MODEL_NAME_AVATAR_CORE = 
    "M_SenseME_Avatar_Core_1.0.0.model";

......

2.3 スタンプファイルの使用

  • 制御下のスタンプファイルを SD カードにコピーし、パスを取得します。スタンプの変更時は、SDK の API にパスを割り当てます。

  • FileUtils ツールクラスの copyStickerZipFiless() 関数を使用して、スタンプをコピーできます。

//スタンプファイルを、スタンプファイルごとに返されるパスと一緒にコピーします

public static ArrayList<String> copyStickerZipFiles(Context context) {

    String files[] = null;

    ArrayList<String> zipfiles = new ArrayList<String>();



    try {

        files = context.getAssets().list("");

    } catch (IOException e) {

        e.printStackTrace();

    }

    ... ...



    return zipfiles;

}
  • FileUtils ツールクラスの getStickerFiles() 関数を実行して、レンダリング用にスタンプのパスを取得します

  • サブフォルダーでファイルをコピーするには、サンプルのメソッドをご参照ください。必要に応じて、メソッドをカスタマイズすることも可能です。

3 シングルおよびダブル入力モード

3.1 シングル入力モード

  • シングル入力モードでは、カメラはテクスチャをコールバックすることによってのみデータを取得します。HumanAction を含む特定の API では、検知用のバッファーデータを入力する必要があります。そのため、glReadPixel() 関数を使用して、ARGB 形式でバッファーデータを取得する必要があります。

  • メリット: バッファーをコールバックする必要がありません。統合およびデータ処理が簡単です。

  • デメリット: glReadPixel() 関数は、ローエンドのマシンでは時間が掛かります。画像形式は ARGB です。顔検知で必要な場合は、グレースケールに変換する必要があります。

3.2 ダブル入力モード

  • ダブル入力モードでは、カメラはテクスチャとデータバッファーを同時にコールバックします。

  • メリット: シングル入力モードと比較すると、ダブル入力モードでは glReadPixel() を必要としません。画像形式は NV21 です。直接、グレースケース画像を取得できます。

  • デメリット: データバッファーのコールバックを使用して、HumanAction を計算します。他の API で使用するために回転およびミラーリングされるため、統合が複雑になります。ARGB 形式を使用する場合は、変換する必要があります。スレッド同期問題もあります。

  • 注記: ダブル入力モードでは、スレッド同期問題、および mGlSurfaceView.requestRender() のタイミングに特に注意してください。

3.3 最適化されたシングル入力モード

  • シングル入力最適化モードは、シングル入力モードに基づいて glReadPixel() を介してバッファーを取得します。取得したバッファーを使用して複数のスレッドでレンダリングおよび検知処理を行います。

  • メリット: シングル入力モードよりフレームレートが高くなり、時間が掛かる検知処理ではパフォーマンスが大幅に向上します。

  • デメリット: 統合が複雑です。スレッドの同期化により、レンダリングが 1 フレーム遅れます。

3.4 最適化されたダブル入力モード

  • ダブル入力最適化モードは、ダブル入力モードに基づいてカメラのコールバックテクスチャを削除します。バッファーを使用したテクスチャのアップロードにより、テクスチャを取得し、そのバッファーを使用して複数のスレッドで検知処理を行います。

  • メリット: シングルおよびダブル入力モードと比べて、フレームレートが高くなり、時間が掛かる検知処理ではパフォーマンスが大幅に向上します。

  • デメリット: 統合が複雑です。テクスチャを手動でアップロードする必要があります。スレッドの同期化により、レンダリングが 1 フレーム遅れます。

3.5 入力モードの切り替え

  • サンプルでは、異なる入力モードを使用できます

  • 異なる入力モードに切り替えるには、サンプルの CameraActivity.java ファイルをご参照ください。

//ダブル入力モードを使用

private CameraDisplayDoubleInput mCameraDisplay;

//シングル入力モードを使用

private CameraDisplaySingleInput mCameraDisplay;

//シングル入力モードの最適化

private CameraDisplaySingleInputMultiThread mCameraDisplay;

//ダブル入力モードの最適化

private CameraDisplayDoubleInputMultithread mCameraDisplay;

//シングル入力モードを使用

mCameraDisplay = new CameraDisplaySingleInput(
    getApplicationContext(), 
    mSingleInputChangePreviewSizeListener, 
    glSurfaceView
);

//ダブル入力モードを使用

mCameraDisplay = new CameraDisplayDoubleInput(
    getApplicationContext(), 
    mDoubleInputChangePreviewSizeListener, 
    glSurfaceView
);

//ダブル入力モードを使用

mCameraDisplay = new CameraDisplayDoubleInput(
    getApplicationContext(), 
    mChangePreviewSizeListener, 
    glSurfaceView
);

//ダブル入力モードとマルチスレッド

mCameraDisplay = new CameraDisplayDoubleInputMultithread(
    getApplicationContext(), 
    mChangePreviewSizeListener, 
    glSurfaceView
);

4 SDK API の使用

4.1 SDK ハンドルの初期化

4.1.1 HumanAction API の初期化

  • HumanAction API を初期化するには loadModel を実行しますが、この処理は時間が掛かります。そのため、非同期に初期化してください。本バージョンでは、サブモデル追加用の API が提供されています。初期化に必要なmodelのみを使用し、後でさらにサブモデルを追加すれば、初期化にかかる時間を削減できます。

//HumanAction ハンドルの初期化は時間が掛かります。そのため、非同期操作を推奨します。

private void initHumanAction() {

    new Thread(new Runnable() {

        @Override

        public void run() {

            synchronized (mHumanActionHandleLock) {

                //モデルをアセットフォルダーからメモリに読み込み、
                //基になる st_mobile_human_action_create_from_buffer API を
                //使用して、ハンドルを作成します

                int result = mSTHumanActionNative
                        .createInstanceFromAssetFile(
                            FileUtils.getActionModelName(), 
                            mHumanActionCreateConfig, 
                            mContext.getAssets()
                        );

                LogUtils.i(
                    TAG, 
                    "the result for createInstance for human_action is %d", 
                    result
                );



                if (result == 0) {

                    mIsCreateHumanActionHandleSucceeded = true;

                    mSTHumanActionNative.setParam(
                        STHumanActionParamsType.ST_HUMAN_ACTION_PARAM_BACKGROUND_BLUR_STRENGTH, 
                        0.35f
                    );

                }

            }

        }

    }).start();

}
  • 初期化中に、シナリオに応じて画像またはビデオを設定するか、または必要に応じて修正します (詳細については STMobileHumanActionNative.java ファイルをご参照ください)。

//作成用にデフォルト設定された設定パラメーター

//マルチスレッドを実行して、速度を最大限に早め、遅れを減らします。必要に応じてデフォルトのパラメーターを変更します。

//ビデオを検知するためにマルチスレッドを実行します

public final static int ST_MOBILE_HUMAN_ACTION_DEFAULT_CONFIG_VIDEO =

    ST_MOBILE_TRACKING_MULTI_THREAD|

    ST_MOBILE_TRACKING_ENABLE_DEBOUNCE|

    ST_MOBILE_TRACKING_ENABLE_FACE_ACTION|

    ST_MOBILE_ENABLE_FACE_DETECT|

    ST_MOBILE_ENABLE_HAND_DETECT|

    ST_MOBILE_ENABLE_SEGMENT_DETECT|

    ST_MOBILE_DETECT_MODE_VIDEO;



//デフォルト設定を使用して画像を検知します

//画像の検知にはシングルスレッドのみ使用できます

public final static int ST_MOBILE_HUMAN_ACTION_DEFAULT_CONFIG_IMAGE =

    ST_MOBILE_TRACKING_SINGLE_THREAD|

    ST_MOBILE_ENABLE_FACE_DETECT|

    ST_MOBILE_ENABLE_SEGMENT_DETECT|

    ST_MOBILE_ENABLE_HAND_DETECT|

    ST_MOBILE_DETECT_MODE_IMAGE;
  • HumanAction API を使用して、モデルを動的に追加または削除し、リソースの割り当てを改善できます。非同期に呼び出すこともできます (詳細については、CameraDisplayDoubleInput.java ファイルをご参照してください)。

//動的にモデルを追加します

private void addSubModel(final String modelName){

    synchronized (mHumanActionHandleLock) {

        int result = mSTHumanActionNative.addSubModelFromAssetFile(
            modelName, 
            mContext.getAssets()
        );

        LogUtils.i(TAG, "add sub model result: %d", result);



        if(result == 0){

            if(modelName.equals(FileUtils.MODEL_NAME_BODY_FOURTEEN)){

                mDetectConfig |=
                    STMobileHumanActionNative.ST_MOBILE_BODY_KEYPOINTS;

                mSTHumanActionNative.setParam(
                    STHumanActionParamsType.ST_HUMAN_ACTION_PARAM_BODY_LIMIT,
                    3.0f
                );

            }else if(modelName.equals(FileUtils.MODEL_NAME_FACE_EXTRA)){

                mDetectConfig |= 
                    STMobileHumanActionNative.ST_MOBILE_DETECT_EXTRA_FACE_POINTS;

            }else if(modelName.equals(FileUtils.MODEL_NAME_EYEBALL_CONTOUR)){

                mDetectConfig |= STMobileHumanActionNative.ST_MOBILE_DETECT_EYEBALL_CONTOUR |

                                 STMobileHumanActionNative.ST_MOBILE_DETECT_EYEBALL_CENTER;

            }else if(modelName.equals(FileUtils.MODEL_NAME_HAND)){

                mDetectConfig |= STMobileHumanActionNative.ST_MOBILE_HAND_DETECT_FULL;

            }

        }

    }

}



//動的にモデルを削除します

private void removeSubModel(final int config){

    synchronized (mHumanActionHandleLock) {

        mSTHumanActionNative.removeSubModelByConfig(config);



        if(config == STMobileHumanActionNative.ST_MOBILE_ENABLE_BODY_KEYPOINTS){

            mDetectConfig &= ~STMobileHumanActionNative.ST_MOBILE_BODY_KEYPOINTS;

        }else if(config == STMobileHumanActionNative.ST_MOBILE_ENABLE_FACE_EXTRA_DETECT){

            mDetectConfig &= ~STMobileHumanActionNative.ST_MOBILE_DETECT_EXTRA_FACE_POINTS;

        }else if(config == STMobileHumanActionNative.ST_MOBILE_ENABLE_EYEBALL_CONTOUR_DETECT){

            mDetectConfig &= ~(STMobileHumanActionNative.ST_MOBILE_DETECT_EYEBALL_CONTOUR |

                    STMobileHumanActionNative.ST_MOBILE_DETECT_EYEBALL_CENTER);

        }else if(config == STMobileHumanActionNative.ST_MOBILE_ENABLE_HAND_DETECT){

            mDetectConfig &= ~STMobileHumanActionNative.ST_MOBILE_HAND_DETECT_FULL;

        }

    }

}

4.1.2 顔属性 API ハンドルの初期化

  • 顔属性 API ハンドルを初期化します。

//顔属性ハンドルを初期化します

private void initFaceAttribute() {

    int result = mSTFaceAttributeNative.createInstanceFromAssetFile(
        FileUtils.MODEL_NAME_FACE_ATTRIBUTE, 
        mContext.getAssets()
    );

    LogUtils.i(
        TAG, 
        "the result for createInstance for faceAttribute is %d", 
        result
    );

}

4.1.3 美化 API ハンドルの初期化

  • 美化 API ハンドルを初期化します。

//美化ハンドルを初期化します

private void initBeauty() {

    //美化およびプレビュー属性の幅と高さを初期化します

    int result = mStBeautifyNative.createInstance(
        mImageHeight, 
        mImageWidth
    );

    LogUtils.i(TAG, "the result is for initBeautify " + result);

    ... ...

}

4.1.4 スタンプ API ハンドルの初期化

  • スタンプ API ハンドルを初期化します。

//スタンプハンドルを初期化します

private void initSticker() {

    iint result = mStStickerNative.createInstance(mContext, null);



    if(mNeedSticker){

        mStStickerNative.changeSticker(mCurrentSticker);

    }



    setHumanActionDetectConfig(
        mNeedBeautify|mNeedFaceAttribute, 
        mStStickerNative.getTriggerAction()
    );

    LogUtils.i(
        TAG, "the result for createInstance for sticker is %d",
        result
    );

}

4.1.5 フィルター API ハンドルの初期化

  • フィルター API ハンドルを初期化します。

//フィルターハンドルを初期化します

private void initFilter(){

    mSTMobileStreamFilterNative.createInstance();

    LogUtils.i(TAG, "filter create instance result %d", result);



    mSTMobileStreamFilterNative.setStyle(mCurrentFilterStyle);



    mCurrentFilterStrength = mFilterStrength;

    //フィルターの強度を設定します。デフォルト値は 0.5f です。

    mSTMobileStreamFilterNative.setParam(
        STFilterParamsType.ST_FILTER_STRENGTH, 
        mCurrentFilterStrength
    );

}

4.1.6 一般的なオブジェクトのトラッキング API ハンドルの初期化

  • 一般的なオブジェクトのトラッキング API ハンドルを初期化します。

//一般的なオブジェクトのトラッキングハンドルの初期化

private void initObjectTrack(){

    int result = mSTMobileObjectTrackNative.createInstance();

}

4.2 カメラプレビューのテクスチャとデータの取得

  • AndroidManifest.xml ファイルを追加して、システムカメラの権限を有効にします。

<uses-permission android:name="android.permission.CAMERA" />
  • ダブル入力モードでは、2 つのコールバックメソッド (バッファーとテクスチャ) を使用するように Android カメラを設定します。シングル入力モードでは、テクスチャをコールバックするように設定します。

public void startPreview(
    SurfaceTexture surfaceTexture, 
    PreviewCallback previewcallback
){

    try {

        //テクスチャをコールバックするように設定します

        mCamera.setPreviewTexture(surfaceTexture);

        if (previewcallback != null) {

        //バッファーをコールバックするように設定します

            mCamera.setPreviewCallback(previewcallback);

        }

        mCamera.startPreview();

    } catch (IOException e) {

        e.printStackTrace();

    }

}
  • Android カメラからテクスチャを取得します (詳細については、サンプルの CameraDisplayDoubleInput.java ファイル、および CameraProxy.java ファイルをご参照ください)。

private void setUpCamera(){

    //カメラのプレビューで必要な表示領域を初期化します (mSurfaceTexture)

   if(mTextureId == OpenGLUtils.NO_TEXTURE){

       mTextureId = OpenGLUtils.getExternalOESTextureID();

       mSurfaceTexture = new SurfaceTexture(mTextureId);

    }

    ... ...

    //mSurfaceTexture にコールバック用のカメラを追加します (テクスチャとバッファー)

    mCameraProxy.startPreview(mSurfaceTexture,mPreviewCallback);

}
  • Android カメラからバッファーを取得します (詳細については、サンプルの CameraDisplayDoubleInput.java ファイル、および CameraProxy.java ファイルをご参照ください)。

private Camera.PreviewCallback mPreviewCallback = new Camera.PreviewCallback() {

    @Override

    public void onPreviewFrame(final byte[] data, Camera camera) {



        if (mCameraChanging || mCameraProxy.getCamera() == null) {

            return ;

        }

        ... ...

        //テクスチャを更新します

        mGlSurfaceView.requestRender();

    }

};

4.3 カメラプレビューのテクスチャとデータの処理

4.3.1 テクスチャの前処理 (シングル入力モードとダブル入力モードで同様の手順)

  • カメラコールバックテクスチャは水平で、通常は OES 形式です。これを GL_TEXTURE_2D 形式に変換し、回転とミラーリングを適用して、携帯電話の画面上でプレビュー画像が直立するようにします (つまり、システムのフロントカメラで撮った写真と同じ結果)。

  • 容易に統合また利用できるように、デモではテクスチャ前処理クラス GLRender の preProcess() 関数を提供して、効率性を向上します。カメラのコールバックバッファーを使用して HumanAction を検知する際は、preProcess() 関数で readPixel コマンドを実行しないでください。 preProcess() 関数の 2 番目のパラメーターを NULL に設定してください。

//テクスチャの前処理

int textureId = mGLRender.preProcess(mTextureId, null);
  • カメラからテクスチャを取得するには、デモで GLRender クラスの preProcess() 関数の使用に関する概要をご参照ください。入力テクスチャを処理した場合は、preProcess() 関数を呼び出さないでください。

  • 前処理済みのテクスチャは、美化、スタンプ、およびフィルター API で使用できます。

4.3.2 データ処理

  • ダブル入力モードでは、カメラのコールバックバッファーデータを使用して HumanActionDetect プロセスを実行して、HumanAction 結果を取得します。テクスチャが回転およびミラーリングされているため、バッファー内のデータは処理されていません。 HumanAction の方向とテクスチャは一致しないため、後で API で使用できるよう、HumanAction の回転およびミラーリング機能を使用して、データを処理し、HumanAction の方向とテクスチャの方向を合わせます。

//カメラ ID とカメラの方向を使用して、HumanAction を再計算します (ダブル入力モード用)

public static STHumanAction humanActionRotateAndMirror(
    STHumanAction humanAction, 
    int width, 
    int height, 
    int cameraId, 
    int cameraOrientation
){

    if(humanAction == null){

        return null;

    }

    if(cameraId != Camera.CameraInfo.CAMERA_FACING_FRONT && 
        cameraId != Camera.CameraInfo.CAMERA_FACING_BACK){

        return humanAction;

    }

    if(cameraOrientation != 90 && cameraOrientation != 270){

        return humanAction;

    }

    //humanAction の回転およびミラーリング

    if(cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT && 
        cameraOrientation == 90){

        humanAction = humanActionRotate(
            height, 
            width, 
            STRotateType.ST_CLOCKWISE_ROTATE_90, 
            false, 
            humanAction
        );

        humanAction = humanActionMirror(width, humanAction);

    }else if(cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT && 
        cameraOrientation == 270){

        humanAction = humanActionRotate(
            height, 
            width, 
            STRotateType.ST_CLOCKWISE_ROTATE_270, 
            false, 
            humanAction
        );

        humanAction = humanActionMirror(width, humanAction);

    }else if(cameraId == Camera.CameraInfo.CAMERA_FACING_BACK && 
        cameraOrientation == 270){

        humanAction = humanActionRotate(
            height, 
            width, 
            STRotateType.ST_CLOCKWISE_ROTATE_270, 
            false, 
            humanAction
        );

    }else if(cameraId == Camera.CameraInfo.CAMERA_FACING_BACK && 
        cameraOrientation == 90){

        humanAction = humanActionRotate(
            height, 
            width, 
            STRotateType.ST_CLOCKWISE_ROTATE_90, 
            false, 
            humanAction
        );

    }



    return humanAction;

}
  • シングル入力モードでは、処理済みテクスチャを使用して、glReadPixel コマンドでバッファーデータを取得します。バッファーを使用して、HumanAction API から結果を計算します。方向はテクスチャの方向と同じであり、データを回転およびミラーリングする必要はありません。

4.4 フレーム処理フロー

注記: 本セクションで説明する美化、スタンプ、フィルター API には、OpenGL 環境が必要です。OpenGL スレッドで実行する必要があります。

  • HumanAction API の使用

//顔特徴点、顔の動き、ジェスチャ、前景と背景のセグメンテーションを検知します

STHumanAction humanAction = mSTHumanActionNative.humanActionDetect(
        mRGBABuffer.array(),
        STCommon.ST_PIX_FMT_RGBA8888,
        mDetectConfig, 
        orientation, 
        mImageWidth, 
        mImageHeight
);

4.4.1 HumanAction API の使用

  • HumanActionDetect 設定は、デフォルトではすべてを検知します。必要に応じて設定をカスタマイズできます。たとえば、前景と背景をセグメント化するには、"|" で結合した ST_MOBILE_SEG_BACKGROUND を追加します。ジェスチャを検知するには、適切な設定を追加してください。

//HumanAction のデフォルト設定

//すべてを検知するのは、時間が掛かり、CPU 使用率が高くなるため、推奨されません。
//必要な動作を検知するようにしてください。

public final static long ST_MOBILE_HUMAN_ACTION_DEFAULT_CONFIG_DETECT =

    ST_MOBILE_FACE_DETECT | ST_MOBILE_EYE_BLINK |

    ST_MOBILE_MOUTH_AH | ST_MOBILE_HEAD_YAW |

    ST_MOBILE_HEAD_PITCH | ST_MOBILE_BROW_JUMP |

    ST_MOBILE_HAND_GOOD | ST_MOBILE_HAND_PALM |

    ST_MOBILE_HAND_LOVE | ST_MOBILE_HAND_HOLDUP |

    ST_MOBILE_HAND_CONGRATULATE | ST_MOBILE_HAND_FINGER_HEART |

    ST_MOBILE_DETECT_EYEBALL_CENTER|ST_MOBILE_DETECT_EYEBALL_CONTOUR;



//サポートされた顔検知設定

public final static long ST_MOBILE_FACE_DETECT = 0x00000001;    //////<顔検知



//顔の動作

public final static long ST_MOBILE_EYE_BLINK = 0x00000002;    ///<まばたきする

public final static long ST_MOBILE_MOUTH_AH = 0x00000004;    ///口を大きく開く

public final static long ST_MOBILE_HEAD_YAW = 0x00000008;    //////<頭を振る

public final static long ST_MOBILE_HEAD_PITCH = 0x00000010;    ///<うなずく

public final static long ST_MOBILE_BROW_JUMP = 0x00000020;    ///<眉を上げる



//ジェスチャ

public final static long ST_MOBILE_HAND_GOOD = 0x00000800;    ///<親指を立てる 2048

public final static long ST_MOBILE_HAND_PALM = 0x00001000;    ///<手のひら 4096

public final static long ST_MOBILE_HAND_LOVE = 0x00004000;    ///<ハートのジェスチャ (16384)

public final static long ST_MOBILE_HAND_HOLDUP = 0x00008000;    ///<手のひらを上に向ける 32768

public final static long ST_MOBILE_HAND_CONGRATULATE = 0x00020000;    ///< お祝い (拳を握る) 131072

public final static long ST_MOBILE_HAND_FINGER_HEART = 0x00040000;    //////< 片手でハートを作るジェスチャ (262144)

public final static long ST_MOBILE_HAND_TWO_INDEX_FINGER = 0x00080000;///< 並べた指 (524288)

public final static long ST_MOBILE_HAND_OK = 0x00000200;  ///<OK のジェスチャ

public final static long ST_MOBILE_HAND_SCISSOR = 0x00000400;  ///<勝利のポーズ

public final static long ST_MOBILE_HAND_PISTOL = 0x00002000;  ///<ピストルのジェスチャ

public final static long ST_MOBILE_HAND_FINGER_INDEX = 0x00100000;  ///<人差し指で指す



public final static long ST_MOBILE_HAND_FIST = 0x00200000; ///<拳のジェスチャ

public final static long ST_MOBILE_HAND_666 = 0x00400000; ///<ラッキー

public final static long ST_MOBILE_HAND_BLESS = 0x00800000; //////<禅のポーズ

public final static long ST_MOBILE_HAND_ILOVEYOU = 0x010000000000L; ///"愛している" のジェスチャ

public final static long ST_MOBILE_BODY_KEYPOINTS = 0x08000000;  ///< 体の特徴点を検知

public final static long ST_MOBILE_SEG_BACKGROUND = 0x00010000;    //////<前景と背景のセグメンテーション (65536)

public final static long ST_MOBILE_DETECT_EXTRA_FACE_POINTS = 0x01000000;  ///< 240 の顔特徴点を検知

public final static long ST_MOBILE_DETECT_EYEBALL_CENTER = 0x02000000;  ///< 眼球の中央点

public final static long ST_MOBILE_DETECT_EYEBALL_CONTOUR = 0x04000000;  ///< 眼球の輪郭点

public final static long ST_MOBILE_BODY_ACTION1 = (long)1 << 32;    ///龍拳

public final static long ST_MOBILE_BODY_ACTION2 = (long)1 << 33;    ///一休さんのジェスチャ

public final static long ST_MOBILE_BODY_ACTION3 = (long)1 << 34;    ///お手上げ

public final static long ST_MOBILE_BODY_ACTION4 = (long)1 << 35;    ///スパイダーマン

public final static long ST_MOBILE_BODY_ACTION5 = (long)1 << 36;    ///スーパーマン



//HumanAction 検知タイプの設定オプションを作成します

///サポートされている検知タイプ

public final static int ST_MOBILE_ENABLE_FACE_DETECT = 0x00000040;  ///< 顔を検知

public final static int ST_MOBILE_ENABLE_HAND_DETECT = 0x00000080;  ///< ジェスチャを検知

public final static int ST_MOBILE_ENABLE_SEGMENT_DETECT = 0x00000100;  ///< 背景のセグメンテーションを検知

public final static int ST_MOBILE_ENABLE_FACE_EXTRA_DETECT = 0x00000200;  ///< 240 の顔特徴点を検知

public final static int ST_MOBILE_ENABLE_EYEBALL_CENTER_DETECT = 0x00000400;  ///< 眼球の中心点を検知

public final static int ST_MOBILE_ENABLE_EYEBALL_CONTOUR_DETECT = 0x00000800;  ///< 眼球の輪郭を検知

public final static int ST_MOBILE_ENABLE_BODY_KEYPOINTS = 0x00001000;  ///< 体の特徴点と動作を検知

public final static int ST_MOBILE_FACE_DETECT_FULL = 0x0000003F;  ///< すべての顔の動きを検知

public final static int ST_MOBILE_HAND_DETECT_FULL = 0x001EFF00;  ///< すべてのジェスチャを検知

///検知モード

public final static int ST_MOBILE_DETECT_MODE_VIDEO = 0x00020000;  ///< ビデオの検知

public final static int ST_MOBILE_DETECT_MODE_IMAGE = 0x00040000;  ///< 画像の検知
  • HumanActionDetect API を以下のように使用します。

STHumanAction humanAction = mSTHumanActionNative.humanActionDetect(
    mNv21ImageData, 
    STCommon.ST_PIX_FMT_NV21,
    mDetectConfig, 
    getHumanActionOrientation(), 
    mImageHeight, 
    mImageWidth
);
  • 顔の表情に関しては、STMobileHumanActionNative API の STMobileExpression コマンドをご参照ください。検知 API は、HumanAction API の結果から入力を受け取り、表情をそれぞれ出力します。以下に示します。

if(humanAction != null && humanAction.faceCount > 0){

    mFaceExpressionResult = mSTHumanActionNative.getExpression(
        humanAction, 
        getHumanActionOrientation(), 
        mCameraID == Camera.CameraInfo.CAMERA_FACING_FRONT
    );

}

4.4.2 FaceAttribute API の使用

  • FaceAttribute API の入力パラメーターは、HumanAction パラメーターの出力をベースとします。そのため、顔属性を実行する前に HumanAction パラメーターを設定します。

STFaceAttribute[] arrayFaceAttribute = new STFaceAttribute[arrayFaces.length];

//年齢、性別、および顔スコアなどの顔属性を計算します

result = mSTFaceAttributeNative.detect(
    mRGBABuffer.array(),
    STCommon.ST_PIX_FMT_RGBA8888, 
    mImageWidth, 
    mImageHeight, 
    arrayFaces, 
    arrayFaceAttribute
);

4.4.3 美化 API の使用

  • 目の拡大や顔のスリム化などの美化 API 関数もまた、HumanAction をベースとしています。

//テクスチャを美化します

result = mStBeautifyNative.processTexture(
    textureId, 
    mImageWidth, 
    mImageHeight, 
    humanAction,
    mBeautifyTextureId[0], 
    mHumanActionBeautyOutput
);
  • 美化パラメーターの設定

//美化パラメーターを設定します

//赤みの強度: [0, 1.0]、赤みなしの場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_REDDEN_STRENGTH, 
    value
);

//補正の強度: [0, 1.0]、補正しない場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_SMOOTH_STRENGTH, 
    value
);

//美白の強度: [0, 1.0]、美白しない場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_WHITEN_STRENGTH, 
    value
);

//目の拡大率: [0, 1.0]、拡大しない場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_ENLARGE_EYE_RATIO, 
    value
);

//顔を細める割合: [0, 1.0]、細めない場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_SHRINK_FACE_RATIO, 
    value
);

//顎の縮小率: [0, 1.0]、縮小しない場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_SHRINK_JAW_RATIO, 
    value
);

//コントラスト: [0, 1.0]、なしの場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_CONSTRACT_STRENGTH, 
    value
);

//彩度: [0, 1.0]、なしの場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_SATURATION_STRENGTH, 
    value
);

//ハイライト除去の強度: [0, 1.0]、除去しない場合は 0.0

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_DEHIGHLIGHT_STRENGTH, 
    value
);

//顔の幅を狭める割合: [0, 1.0]、デフォルト値: 0.0 (狭めない)

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_NARROW_FACE_RATIO, 
    value
);


//鼻の縮小率: [0, 1.0]、デフォルト値: 0.0 (狭めない)

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_NARROW_NOSE_RATIO, 
    value
);

//鼻の長さの割合: [-1, 1]、デフォルト値: 0.0、短くする場合は [-1, 0]
//長くする場合は [0, 1]

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_LENGTH_NOSE_RATIO, 
    value
);

//顎の長さの割合: [-1, 1]、デフォルト値: 0.0、短くする場合は [-1, 0]
//長くする場合は [0, 1]

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_LENGTH_CHIN_RATIO , 
    value
);

//口の大きさの割合: [-1, 1]、デフォルト値: 0.0、拡大する場合は [-1, 0]
//縮小する場合は [0, 1]

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_SIZE_MOUTH_RATIO, 
    value
);

//人中の長さの割合: [-1, 1]、デフォルト値: 0.0、短くする場合は [-1, 0]
//長くする場合は [0, 1]

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_LENGTH_PHILTRUM_RATIO, 
    value
);

//生え際の高さの割合: [-1, 1]、デフォルト値: 0.0、高くする場合は [-1, 0]
//低くする場合は [0, 1]

mStBeautifyNative.setParam(
    STBeautyParamsType.ST_BEAUTIFY_LOW_HAIRLINE_RATIO, 
    value
);

4.4.4 スタンプ API の使用

  • スタンプ機能を有効にするには、顔データを利用できるようにします。そのため、事前に HumanAction API を実行してください。

//スタンプタイプごとにカスタムイベントを作成します。
//スカイサムスタンプの場合、センサーのクォータニオンに入力します。
//別のスタンプの場合は、デフォルトのクォータニオンを入力します。
STStickerInputParams inputEvent;
if((mParamType & STMobileStickerNative.ST_INPUT_PARAM_CAMERA_QUATERNION) == 
    STMobileStickerNative.ST_INPUT_PARAM_CAMERA_QUATERNION){
    inputEvent = new STStickerInputParams(
        mSensorEvent.values, 
        mCameraID == Camera.CameraInfo.CAMERA_FACING_FRONT, 
        event
    );
} else {
    inputEvent = new STStickerInputParams(
        new float[]{0,0,0,1}, 
        mCameraID == Camera.CameraInfo.CAMERA_FACING_FRONT, 
        event
    );
}
//バッファーストリームまたは他のデータを出力します。パラメーター値を True に設定します。
if (!needOutputBuffer) {

    result = mStStickerNative.processTexture(
        textureId, 
        humanAction, 
        orientation, 
        mImageWidth, 
        mImageHeight,
        frontStickerOrientation, 
        false, 
        mTextureOutId[0]
    );

} else {  //ストリーミング用のバッファーを出力します

    byte[] imageOut = new byte[mImageWidth * mImageHeight * 4];

    result = mStStickerNative.processTextureAndOutputBuffer(
        textureId, 
        humanAction, 
        orientation, 
        mImageWidth,
        mImageHeight, 
        frontStickerOrientation, 
        false, 
        mTextureOutId[0], 
        STCommon.ST_PIX_FMT_RGBA8888, 
        imageOut
    );

}
  • スタンプを変更するには、STMobileStickerNative API の changeSticker 関数を呼び出し、スタンプパスを入力します (setShowSticker 関数の使用に関する概要をご参照ください)。

//スタンプを変更します。入力パラメーターはスタンプのパスです。

public void setShowSticker(String sticker) {

    mCurrentSticker = sticker;

    mStStickerNative.changeSticker(mCurrentSticker);

    setHumanActionDetectConfig(
        mNeedBeautify | mNeedFaceAttribute,
        mStStickerNative.getTriggerAction()
    );

}
  • スタンプを変更するには、STMobileStickerNative API の changeSticker 関数を呼び出し、スタンプパスを入力します (setShowSticker 関数の使用に関する概要をご参照ください)。

    //新しいエンジンを重ね合わせてスタンプを貼ります。
    //スタンプ素材のパスを入力し、スタンプ素材 ID を返します。
    public int addSticker(String addSticker) {
        mCurrentSticker = addSticker;
        int stickerId = mStStickerNative.addSticker(mCurrentSticker);
        setHumanActionDetectConfig(
            mNeedBeautify | mNeedFaceAttribute,
            mStStickerNative.getTriggerAction()
        );
    }
    //スタンプ素材 ID と一緒に、スタンプを削除します
    result = mStStickerNative.removeSticker(packageId);
  • スタンプを変更後、StickerNative API の getNeededInputParams 関数を実行して、現在のスタンプに携帯電話センサーが必要かどうかを確認します。

mParamType = mStStickerNative.getNeededInputParams();
  • スタンプを変更後、STMobileStickerNative API の getTriggerAction 関数を実行して、現在のスタンプでサポートされているジェスチャ、前景、背景などの情報を取得します。戻り値は long で返されます。

public long getStickerTriggerAction(){

    return mStStickerNative.getTriggerAction();

}
  • getTriggerAction 関数の戻り値に応じて、humanActionDetect 関数の config コマンドをリセットし、効率を向上します。たとえば、現在のスタンプでサポートされている顔とジェスチャのみを検知するには、次の設定を使用します。

mDetectConfig = mSTMobileStickerNative.getTriggerAction()

            | STMobileHumanActionNative.ST_MOBILE_FACE_DETECT;
  • スタンプにサウンド機能が追加されました。自動的に、または TriggerAction API によってサウンドが再生されるようにスタンプをデザインできます。JNI の部分の STSoundPlay.java ファイルで、スタンプをデザインすることもできます。サンプルの STSoundPlay に従って、必要に応じてサウンドの再生をカスタマイズできます。

4.4.5 フィルター API の使用

  • フィルター API を使用する:

//フィルタータイプを設定します。OpenGL スレッドで呼び出す必要があります。

mSTMobileStreamFilterNative.setStyle(mCurrentFilterStyle);

//フィルターの強度を、[0,1] の値範囲で設定します。
//0 だとフィルターエフェクトは適用されず、1 は最大の強度となります。

mSTMobileStreamFilterNative.setParam(
    STFilterParamsType.ST_FILTER_STRENGTH,
    mCurrentFilterStrength
);

//フィルター用の関数

int ret = mSTMobileStreamFilterNative.processTexture(
    textureId, 
    mImageWidth, 
    mImageHeight, 
    mFilterTextureOutId[0]
);

4.4.6 一般的なオブジェクトのトラッキング API の使用

  • 一般的なオブジェクトのトラッキング領域を設定する

//トラッキング対象の顔枠を設定します

if (mNeedSetObjectTarget) {

    mSTMobileObjectTrackNative.setTarget(
        mRGBABuffer.array(),
        STCommon.ST_PIX_FMT_RGBA8888, 
        mImageWidth, 
        mImageHeight,
        tragetRect
    );

}
  • 一般的なオブジェクトの対象領域をトラッキングする

//連続したビデオフレーム内の対象をリアルタイムで高速にトラッキングし、
//対象領域の顔枠および信頼係数を返します (1 つの対象のみトラッキングできます)。

float[] socre = new float[1];

STRect outputRect = mSTMobileObjectTrackNative.objectTrack(
    mRGBABuffer.array(), 
    STCommon.ST_PIX_FMT_RGBA8888, 
    mImageWidth,
    mImageHeight, 
    score
);
  • 一般的なオブジェクトのトラッキング API ハンドルをリセットする

//一般的なオブジェクトのトラッキング API ハンドルをリセットします

mSTMobileObjectTrackNative.reset();

4.5 SDK ハンドルの解放

  • OpenGL リソースは、OpenGL スレッドで解放される必要があります。

mGlSurfaceView.queueEvent(new Runnable() {

    @Override

    public void run() {

        //スタンプ API ハンドルを解放します

        mStStickerNative.destroyInstance();

        //美化 API ハンドルを解放します

        mStBeautifyNative.destroyBeautify();

        //フィルター API ハンドルを解放します

        mSTMobileStreamFilterNative.destroyInstance();



        mRGBABuffer = null;

        deleteTextures();

        if(mSurfaceTexture != null){

            mSurfaceTexture.release();

        }

        mGLRender.destroyFrameBuffers();

    }

});
  • 非 OpenGL リソースを解放する

synchronized (mHumanActionHandleLock){

    //HumanAction API ハンドルを解放します

    mSTHumanActionNative.destroyInstance();

}

//FaceAttribute API ハンドルを解放します

mSTFaceAttributeNative.destroyInstance();



//一般的なオブジェクトトラッキング API ハンドルを解放します

mSTMobileObjectTrackNative.destroyInstance();

5 JNI API の概要

5.1 STMobileCommon

  • 本 API は、画像形式やエラーコードなどの静的定数と、いくつかの静的関数を定義します。詳細については STMobileCommon.java ファイルをご参照ください。

//色フォーマットの変換では、変換速度が遅いため、YUV420P 変換を使用することは推奨しません。

public static native int stColorConvert(
    byte[] inputImage, 
    byte[] outputImage,
    int width, 
    int height, 
    int type
);



//画像を回転します

public static native int stImageRotate(
    byte[] inputImage, 
    byte[] outputImage,
    int width, 
    int height, 
    int format, 
    int rotation
);



//点滅の閾値を [0,1] の信頼度で設定します。デフォルトの閾値は 0.5 です。

public native void setEyeblinkThreshold(float threshold);



//口を開く閾値を [0,1] の信頼度で設定します。デフォルトの閾値は 0.5 です。

public native void setMouthahThreshold(float threshold);



//口を開く閾値を [0,1] の信頼度で設定します。デフォルトの閾値は 0.5 です。

public native void setHeadyawThreshold(float threshold);



//口を開く閾値を [0,1] の信頼度で設定します。デフォルトの閾値は 0.5 です。

public native void setHeadpitchThreshold(float threshold);



//口を開く閾値を [0,1] の信頼度で設定します。デフォルトの閾値は 0.5 です。

public native void setBrowjumpThreshold(float threshold);



// 106 の顔特徴点を補正する閾値を設定します。
// 閾値が設定されていない場合は、デフォルト値 0.8 を入力します。 
// 推奨値の範囲: [0.0, 1.0]。
// 閾値が大きいほど、ジッター除去効果が向上し、トラッキングの遅延が長くなります。

public native void setSmoothThreshold(float threshold);



// 顔の 3D 回転角度をデジッタリングする閾値を設定します。
// 閾値が設定されていない場合は、デフォルト値 0.5 を入力します。 
// 推奨値の範囲: [0.0, 1.0]。
// 閾値が大きいほど、ジッター除去効果が向上し、トラッキングの遅延が長くなります。

public native void setHeadposeThreshold(float threshold);

5.2 STMobileHumanActionNative

  • HumanAction API を作成および検出する際に利用できる設定オプションを定義します。詳細については STMobileHumanActionNative.java ファイルをご参照ください。

//デフォルト設定によりビデオを検知します

public final static int ST_MOBILE_HUMAN_ACTION_DEFAULT_CONFIG_VIDEO;

//デフォルト設定により画像を検知します

public final static int ST_MOBILE_HUMAN_ACTION_DEFAULT_CONFIG_IMAGE;



//インスタンスを作成します

public native int createInstance(String modelpath, int config);



//リソースフォルダーからインスタンスを作成します

public native int createInstanceFromAssetFile(
    String assetModelpath, 
    int config, 
    AssetManager assetManager
);



//サブモデル、st_mobile_human_action_create、
//および st_mobile_human_action_create_with_sub_models により 
//human_action 検知 API ハンドルを作成します。呼び出せるのは 1 つのみです。

public native int createInstanceWithSubModels(
    String[] modelPaths, 
    int modelCount, 
    int config
);



//サブモデルを追加します。
//スレッドセーフではなく、st_mobile_human_action_detect の実行中の、
//使用しているサブモデルの上書きには対応していません。

public native int addSubModel(String modelPath);



//リソースフォルダーからサブモデルを追加します

public native int addSubModelFromAssetFile(
    String assetModelpath, 
    AssetManager assetManager
);



//追加されたサブモデルを削除します

public native int removeSubModelByConfig(int config);



//リソースフォルダーからサブモデルを追加します

public native int addSubModelFromAssetFile(
    String assetModelpath, 
    AssetManager assetManager
);



//設定する動作パラメータータイプ

public native int setParam(int type, float value);



//顔特徴点、動作情報、前景と背景のセグメンテーションなどを検知します

public native STHumanAction humanActionDetect(
    byte[] imgData, 
    int imageFormat,
    long detect_config,
    int orientation, 
    int imageWidth, 
    int imageHeight
);



//リソースを解放します

public native void destroyInstance();



//human_action API の結果から表情を取得します

public static native boolean[] getExpression(
    STHumanAction humanAction, 
    int orientation, 
    boolean needMirror
);



//表情の閾値を設定します

public static native void setExpressionThreshold(
    int detectExpression, 
    float threshold
);

5.3 STMobileFaceAttributeNative

  • 顔属性 API。詳細については STMobileFaceAttributeNative.java ファイルをご参照ください。

//インスタンスを作成します

public native int createInstance(String modelpath);

////顔属性検知

public native int detect(
    byte[] image, 
    int format, 
    int width,
    int height, 
    STMobile106[] mobile106, 
    STFaceAttribute[] attributes
);

//リソースを解放します

public native void destroyInstance();

5.4 STBeautifyNative

  • 美化 API。必要に応じて選択できます。詳細については STBeautifyNative.java ファイルをご参照ください。

//美化 API ハンドルを作成します

public native int createInstance(int width, int height);



//美化パラメーターを設定します

public native int setParam(int type, float value);



//画像バッファーを美化します。
//OpenGL 環境で呼び出す必要があります (OpenGL スレッドで実行します)。

public native int processBufferInGLContext(
    byte[] pInputImage, 
    int inFormat, 
    int outputWidth,
    int outputHeight, 
    STHumanAction humanActionInput, 
    byte[] pOutImage, 
    int outFormat,
    STHumanAction humanActionOutput
);



//画像を美化します。
//本 API は OpenGL 環境で関数を実行しない (OpenGL スレッドで実行しない) 
//ユーザー向けです。

public native int processBufferNotInGLContext(
    byte[] pInputImage, 
    int inFormat,
    int outputWidth, 
    int outputHeight, 
    STHumanAction humanActionInput, 
    byte[] pOutImage,
    int outFormat, 
    STHumanAction humanActionOutput
);



//OpenGL ES でテクスチャを美化します。OpenGL 環境で呼び出す必要があります。

public native int processTexture(
    int textureIn, 
    int outputWidth,
    int outputHeight, 
    STHumanAction humanActionInput,
    int textureOut, 
    STHumanAction humanActionOutput
);



//OpenGL ES でテクスチャを美化します。OpenGL 環境で呼び出す必要があります。
//バッファーと顔データを出力できます。

public native int processTextureAndOutputTexture(
    int textureIn, 
    int outputWidth,
    int outputHeight, 
    STHumanAction humanActionInput, 
    int textureOut, 
    byte[] outputBuf,
    int format, 
    STHumanAction humanActionOutput
);



//OpenGL 環境でインスタンスを解放します

public native void destroyBeautify();

5.5 STMobileStickerNative

  • スタンプ API。詳細については STMobileStickerNative.java ファイルをご参照ください。

//スタンプ API を作成します

public native int createInstance(Context context, String zipPath);



//OpenGL ES でテクスチャにスタンプを張ります。
//OpenGL 環境で呼び出す必要があります。RBGA 画像形式のみサポートしています。

public native int processTexture(
    int textureIn, 
    STHumanAction humanAction,
    int rotate, 
    int imageWidth, 
    int imageHeight, 
    int frontStickerRotate, 
    boolean needsMirroring,
    int textureOut
);



//OpenGL ES でテクスチャにスタンプを張ります。
//OpenGL 環境で呼び出す必要があります。RBGA 画像形式のみサポートしています。
//バッファー出力もサポートしています。

public native int processTextureAndOutputBuffer(
    int textureIn, 
    STHumanAction humanAction,
    int rotate, 
    int imageWidth, 
    int imageHeight, 
    int frontStickerRotate, 
    boolean needsMirroring,
    int textureOut, 
    int outFmt, 
    byte[] imageOut
);



//スタンプのパスを変更します
public native int changeSticker(String path);

//アセットファイルからスタンプを変更します
public native int changeStickerFromAssetsFile(
    String assetFilePath,
    AssetManager assetManager
);

//素材パッケージをあらかじめロードします
public native int preloadPackage(String path);

//バッファー内の素材パッケージをあらかじめロードします
public native int preloadPackageFromAssetsFile(
    String assetFilePath,
    AssetManager assetManager
);

//スタンプを追加します
public native int addSticker(String path);

//アセットファイルからスタンプを追加します
public native int addStickerFromAssetsFile(
    String assetFilePath,
    AssetManager assetManager
);

//スタンプを削除します
public native int removeSticker(int packageId);

//すべてのスタンプを削除します
public native void removeAllStickers();

//スタンプモジュールを作成します
public native int createModule(
    int moduleType, 
    int packageId, 
    int moduleId
);

//スタンプモジュールを素材パッケージに移動します
public native int moveModuleToPackage(int packageId, int moduleId);

//スタンプモジュールを削除します。非 OpenGL スレッドで呼び出す必要があります。
//次のフレーム処理時に、OpenGL リソースを解放します。
public native int removeModule(int moduleId);

//スタンプモジュール情報を取得します
public native STModuleInfo[] getModules();

//素材パッケージ ID の配列を取得します
public native int[] getPackageIds();

//現在のスタンプのトリガーアクションを取得します
public native long getTriggerAction();

//レンダリングする前に素材が読み込まれるのを待ちます。
//フレームやショートビデオの 3D 描画など、
//モデルの読み込みとレンダリングを待つために使用します。
public native int setWaitingMaterialLoaded(boolean needWait);

//スタンプ素材画像で使用される最大メモリを設定します
public native int setMaxMemory(int value);

//サウンド停止通知関数
public native int setSoundPlayDone(String name);

//インスタンスを破壊します。OpenGL 環境で呼び出す必要があります。
public native void destroyInstance();


//アバター関数に対応するモデルをロードします
public native int loadAvatarModel(String modelpath);

//アセットフォルダーからアバター関数に対応するモデルをロードします
public native int loadAvatarModelFromAssetFile(
    String assetModelpath,
    AssetManager assetManager
);

//アバター関数に対応するモデルを削除し、関連データを消去します
public native int removeAvatarModel();

//指定したスタンプモジュール向けの遷移を追加します
public native int addModuleTransition(
    int moduleId, 
    int targetState,
    STCondition[] conditionArray, 
    STTransParam[] paramArray, 
    int[] transId
);

//指定したスタンプモジュール向けの遷移を削除します
public native int removeTransition(int transId);

//指定したスタンプモジュール向けのすべての遷移を追加します
public native int clearModuleTransition(int moduleId);

//int、long、bool、float、および string などの XXX データ型のパラメーターを設定します
public native int setParamXXX(int moduleId, int paramType, int value);

//int データ型のパラメーターを取得します
public native int getParamInt(int moduleId, int paramType);

//素材パッケージを変更または追加する度に呼び出される、
//現在必要なカスタム入力パラメーターのリストを取得します
public native int getNeededInputParams();

5.6 STSoundPlay

  • STSoundPlay はサウンドスタンプの実装のために設計されたものです。

//オーディオ再生リスナー

public interface PlayControlListener {

    //オーディオ素材を読み込むためのコールバック

    void onSoundLoaded(String name, byte[] content);



    //オーディオを再生するためのコールバック

    void onStartPlay(String name, int loop);



    //再生を停止するためのコールバック

    void onStopPlay(String name);

}



public void setStickHandle(STMobileStickerNative stickHandle);



//オーディオ再生の終了フラグを設定します

public void setSoundPlayDone(String name);



//難読化なしで JNI を呼び出します

private void onSoundLoaded(String name, byte[] content);



//難読化なしで JNI を呼び出します

private void onStartPlay(String name, int loop);



//難読化なしで JNI を呼び出します

private void onStopPlay(String name);

//難読化なしで JNI を呼び出します
private void onSoundPause(String name)

//難読化なしで JNI を呼び出します
private void onSoundResume(String name)
......

5.7 STMobileStreamFilterNative

  • GPU フィルター API。OpenGL スレッド内で実行する必要があります。詳細については STMobileStreamFilterNative.java ファイルをご参照ください。

//インスタンスを作成します

public native int createInstance();



//フィルタータイプを設定します。OpenGL スレッド内で呼び出す必要があります。

public native int setStyle(String styleModelPath);



//フィルターパラメーターを設定します

public native int setParam(int type, float value);



//OpenGL ES のテクスチャにフィルターを適用します。
//OpenGL スレッド内で呼び出す必要があります。

public native int processTexture(
    int textureIn,
    int imageWidth, 
    int imageHeight, 
    int textureOut
);



//OpenGL ES のテクスチャにフィルターを適用し、バッファーを出力します。
//OpenGL スレッド内で呼び出す必要があります。

public native int processTextureAndOutputBuffer(
    int textureIn, 
    int imageWidth,
    int imageHeight,
    int textureOut, 
    byte[] outImage, 
    int outFormat
);



//画像バッファーにフィルターを適用します。OpenGL スレッド内で呼び出す必要があります。

public native int processBuffer(
    byte[] inputImage, 
    int inFormat, 
    int imageWidth,
    int imageHeight, 
    byte[] outImage, 
    int outFormat
);



//美化ハンドルを解放します。OpenGL スレッド内で呼び出す必要があります。

public native void destroyInstance();

5.8 STMobileFilterNative

  • CPU フィルター API。詳細については STMobileFilterNative.java ファイルをご参照ください。

//フィルターハンドルを作成します

public native int createInstance();



//フィルタータイプを設定します

public native int setStyle(String styleModelPath);



//フィルターパラメーターを設定します

public native int setParam(int type, float value);



//画像にフィルターを適用します

public native int process(
    byte[] inputImage, 
    int inFormat,
    int imageWidth, 
    int imageHeight, 
    byte[] outImage, 
    int outFormat
);



//フィルター API ハンドルを解放します

public native void destroyInstance();

5.9 STMobileObjectTrackNative

  • 一般的なオブジェクトトラッキング API。詳細については、STMobileObjectTrackNative.java ファイルをご参照ください。

//一般的なオブジェクトトラッキングハンドルを作成します

public native int createInstance();



//トラッキング対象の顔枠を設定します

public native int setTarget(
    byte[] inputImage, 
    int inFormat,
    int imageWidth, 
    int imageHeight, 
    STRect rect
);



//連続したビデオフレーム内の対象をリアルタイムで高速にトラッキングし、
//対象領域の顔枠を確実に返します

public native STRect objectTrack(
    byte[] inputImage, 
    int inFormat,
    int imageWidth,
    int imageHeight, 
    float[] resultScore
);



//一般的なオブジェクトトラッキングハンドルをリセットします

public native void reset();



//インスタンスを破壊します

public native void destroyInstance();

5.10 STHumanAction

//human_action 検知結果をミラーリングします

public static native STHumanAction humanActionMirror(
    int width, 
    STHumanAction humanAction
);



//human_action 検知結果を回転します

public static native STHumanAction humanActionRotate(
    int width, 
    int height, 
    int orientation, 
    boolean rotateBackGround, 
    STHumanAction humanAction
);



//human_action 検知結果をリサイズします

public static native STHumanAction humanActionResize(
    float scale, 
    STHumanAction humanAction
);

6 回転と方向に関する手順

6.1 カメラの方向

  • フロントカメラ: CameraInfo.orientation は、大抵の携帯電話のフロントカメラでは 270、特殊な電話では 90 に設定されています。

  • リアカメラ: CameraInfo.orientation は、大抵の携帯電話のリアカメラでは 90、特殊な電話では 270 に設定されています。

private CameraInfo mCameraInfo = new CameraInfo();

//カメラの方向を取得します

public int getOrientation(){

    if(mCameraInfo == null){

        return 0;

    }

    return mCameraInfo.orientation;

}

6.2 HumanAction API の方向

  • デバイスセンサーの方向によって、HumanActionDetect API の入力方向を決定します。

/**

 * HumanActionDetect API に使用されます。
 //センサーの方向に基づいて、さまざまなデバイス上のバッファー内の顔の方向を計算します。

 * @return バッファー内の顔の方向

 */

private int getHumanActionOrientation(){

    boolean frontCamera = (mCameraID == Camera.CameraInfo.CAMERA_FACING_FRONT);



    //重力センサーから返された向きを取得します

    int orientation = Accelerometer.getDirection();



    //リアカメラが使用されていて、センサーの方向が 0 または 2 の場合は、
    //リアカメラはフロントカメラの方向と反対です

    if(!frontCamera && orientation == STRotateType.ST_CLOCKWISE_ROTATE_0){

        orientation = STRotateType.ST_CLOCKWISE_ROTATE_180;

    }else if(!frontCamera && orientation == STRotateType.ST_CLOCKWISE_ROTATE_180){

        orientation = STRotateType.ST_CLOCKWISE_ROTATE_0;

    }



    //回転の定義は、フロントカメラとリアカメラ、および異なる携帯電話のカメラで異なることに注意してください

    if (((mCameraProxy.getOrientation() == 270 && 
        (orientation & STRotateType.ST_CLOCKWISE_ROTATE_90) == STRotateType.ST_CLOCKWISE_ROTATE_90) ||

            (mCameraProxy.getOrientation() == 90 && 
                (orientation & STRotateType.ST_CLOCKWISE_ROTATE_90) == STRotateType.ST_CLOCKWISE_ROTATE_0)))

        orientation = (orientation ^ STRotateType.ST_CLOCKWISE_ROTATE_180);

    return orientation;

}

Last updated