2021年3月6日 星期六

Android Studio NDK + OpenCV + CPP 測試程式(二十四):

Android Studio NDK + OpenCV + CPP 測試程式(二十四):

完成了 NDK(Native Development Kit)和 OpenCV 安裝和設置後,便可以測試 OpenCV 的 C++ 程式,現在 Android Studio 中已經可以調用 OpenCV 的C/C++。

Android Studio 的 NDK + OpenCV + CPP 測試程式
  • 操作系統:Windows 7 64-bit 版本
  • 開發環境:Android Studio 4.0.1 版本
  • Gradle 版本:6.1.1
  • 手機測試版本:API 19
  • 原程式:C:\Development\Development_Android\Android_Project\NDK
  • 程式:C:\Development\Development_Android\Android_Project\NDK
  • NDK 版本:NDK 21.0.6113669 版本 Android
1﹒在 MainActivity有 Java 中載入庫,用作運行 APP。程式內用 native 方法聲明和調用 int[] Bitmap2Grey 和 String stringFromJNI(),Bitmap2Grey 用來轉換灰階圖像。
app / java / MainActivity.java:

package bugworkshop.blogspot.ndk;

 

import androidx.appcompat.app.AppCompatActivity;

 

import android.os.Bundle;

import android.widget.TextView;

import org.opencv.android.OpenCVLoader;

import android.util.Log;

 

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.view.View;

import android.widget.Button;

import android.widget.ImageView;

 

import android.widget.Toast;

 

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

 

    // Used to load the 'native-lib' library on application startup.

    static {

        System.loadLibrary("native-lib");

    }

 

    private Button btn_1;

    private Button btn_2;

    private ImageView imageView;

    private Bitmap bitmap;

 

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

 

        // Example of a call to a native method

        TextView tv = findViewById(R.id.sample_text);

        tv.setText(stringFromJNI());

        Toast.makeText(MainActivity.this, stringFromJNI(),Toast.LENGTH_LONG).show();

 

        if (OpenCVLoader.initDebug()) {

            Log.i("CV", "Load OpenCV Library Successful.");

            tv.setText("Load OpenCV Library Successfully.");

        } else {

            Log.i("CV", "Load OpenCV Library Failed.");

            tv.setText("Load OpenCV Library Failed.");;

        }

 

        btn_1 = (Button)findViewById(R.id.button_1);

        imageView = (ImageView)findViewById(R.id.image);

        bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.face01);

        btn_1.setOnClickListener(this);

 

        btn_2 = (Button)findViewById(R.id.button_2);

        btn_2.setOnClickListener(this);

 

    }

 

    public void showImage(){

        bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.face01);

        imageView.setImageBitmap(bitmap);

    }

 

    public void gray(){

        int w = bitmap.getWidth();

        int h = bitmap.getHeight();

        int[] piexls = new int[w*h];

        bitmap.getPixels(piexls,0,w,0,0,w,h);

        int[] resultData =Bitmap2Grey(piexls,w,h);

        Bitmap resultImage = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);

        resultImage.setPixels(resultData,0,w,0,0,w,h);

        imageView.setImageBitmap(resultImage);

    }

 

    @Override

    public void onClick(View view){

        switch(view.getId()){

            case R.id.button_1:showImage();break;

            case R.id.button_2:gray();break;

        }

    }

 

    /**

     * A native method that is implemented by the 'native-lib' native library,

     * which is packaged with this application.

     */

    public native int[] Bitmap2Grey(int[] pixels,int w,int h);

 

    /**

     * A native method that is implemented by the 'native-lib' native library,

     * which is packaged with this application.

     */

    public native String stringFromJNI();

 

    @Override

    public void onResume(){

        super.onResume();

    }

}


2﹒native-lib.cpp 是 C++ 程式。
app / cpp / native-lib.cpp:

#include<opencv2/opencv.hpp>

 

using namespace cv;

using namespace std;

 

extern "C"

JNIEXPORT jintArray JNICALL

Java_bugworkshop_blogspot_ndk_MainActivity_Bitmap2Grey(

        JNIEnv *env,

jobject /* this */,jintArray buf,jint w,jint h) {

jint *cbuf;

jboolean ptfalse = false;

//讀取 int 陣列並轉為 Mat 類型

cbuf = env->GetIntArrayElements(buf, &ptfalse);

if(cbuf == NULL){

return 0;

}

 

Mat imgData(h, w, CV_8UC4, (unsigned char*)cbuf);

// 注意,Android 的 Bitmap 是 ARGB 四通道,而不是 RGB 三通道

cvtColor(imgData,imgData,CV_BGRA2GRAY);

cvtColor(imgData,imgData,CV_GRAY2BGRA);

 

int size=w * h;

jintArray result = env->NewIntArray(size);

env->SetIntArrayRegion(result, 0, size, (jint*)imgData.data);

env->ReleaseIntArrayElements(buf, cbuf, 0);

return result;

}

 

extern "C"

JNIEXPORT jstring JNICALL

Java_bugworkshop_blogspot_ndk_MainActivity_stringFromJNI(

        JNIEnv* env,

jobject /* this */) {

std::string hello = "Hello from C++";

return env->NewStringUTF(hello.c_str());

}


3﹒介面內容佈局。
app / res / layout / active_main.xml:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    xmlns:tools="http://schemas.android.com/tools"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:orientation="vertical"

    tools:context=".MainActivity">

 

    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_weight="1"

        android:orientation="vertical">

 

        <TextView

            android:id="@+id/sample_text"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Hello World!"

            app:layout_constraintBottom_toBottomOf="parent"

            app:layout_constraintLeft_toLeftOf="parent"

            app:layout_constraintRight_toRightOf="parent"

            app:layout_constraintTop_toTopOf="parent" />

 

        <ImageView

            android:id="@+id/image"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:layout_weight="1"

            app:srcCompat="@drawable/face01" />

    </LinearLayout>

 

    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_weight="1"

        android:orientation="horizontal">

 

        <Button

            android:id="@+id/button_2"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:layout_weight="1"

            android:text="Gray" />

 

        <Button

            android:id="@+id/button_1"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_weight="1"

        android:text="Color" />

    </LinearLayout>

 

</LinearLayout>


2021年 3月 6日(Sat)天氣報告
氣溫:67.0°F / 19.0°C @ 09:00
風速:每小時 18 公里
相對濕度:百分之 90%
天氣:多雲

沒有留言:

張貼留言