Import OpenCV
- macOS 10.13.6
- Android Studio 3.5
- Android API level 29
- NDK r20
- CMake 3.10.2
- OpenCV 4.1.1 for Android
Create empty native project
android {
defaultConfig {
externalNativeBuild {
cmake {
cppFlags ""
arguments "-DANDROID_STL=c++_shared"
}
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
C++ Library Support
CMake
Download OpenCV
- copy
include
folder from /Downloads/OpenCV-android-sdk/sdk/native/jni
to Android project's c++ source folder: src/main/cpp
.
- copy all library folder from
/Downloads/OpenCV-android-sdk/sdk/native/libs/
to Android project's JNI forlder: src/main/jniLibs/
.
.
├── jni
│ └── include
│ └── opencv2
├── libs
│ ├── arm64-v8a
│ │ └── libopencv_java4.so
│ ├── armeabi-v7a
│ │ └── libopencv_java4.so
│ ├── x86
│ │ └── libopencv_java4.so
│ └── x86_64
│ └── libopencv_java4.so
└── staticlibs
.
├── cpp
│ └── include
│ └── opencv2
├── java
│ └── com
│ └── opencv
├── jniLibs
│ ├── arm64-v8a
│ │ └── libopencv_java4.so
│ ├── armeabi-v7a
│ │ └── libopencv_java4.so
│ ├── x86
│ │ └── libopencv_java4.so
│ └── x86_64
│ └── libopencv_java4.so
└── res
OpenCV releases page
Using CMake to import library
cmake_minimum_required(VERSION 3.10.2)
set(libs ${CMAKE_SOURCE_DIR}/../jniLibs)
include_directories(${CMAKE_SOURCE_DIR}/include)
add_library(lib_opencv SHARED IMPORTED)
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${libs}/${ANDROID_ABI}/libopencv_java4.so)
add_library(native-lib SHARED native-lib.cpp)
find_library(log-lib log)
target_link_libraries(native-lib lib_opencv ${log-lib})
CMake variables document
Others
#include <jni.h>
#include <string>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
extern "C" JNIEXPORT jintArray JNICALL
Java_com_opencv_MainActivity_gray(JNIEnv *env, jobject instance, jintArray buf, jint w, jint h) {
jint *cbuf = env->GetIntArrayElements(buf, JNI_FALSE);
if (cbuf == nullptr) {
return nullptr;
}
Mat imgData(h, w, CV_8UC4, (unsigned char *) cbuf);
uchar *ptr = imgData.ptr(0);
for (int i = 0; i < w * h; i++) {
// Y = 0.299*R + 0.587*G + 0.114*B
// BGRA
int grayScale = (int) (ptr[4 * i + 2] * 0.299 + ptr[4 * i + 1] * 0.587 + ptr[4 * i + 0] * 0.114);
ptr[4 * i + 1] = static_cast<uchar>(grayScale);
ptr[4 * i + 2] = static_cast<uchar>(grayScale);
ptr[4 * i + 0] = static_cast<uchar>(grayScale);
}
int size = w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result, 0, size, cbuf);
env->ReleaseIntArrayElements(buf, cbuf, 0);
return result;
}
package com.opencv
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.view.View
import android.widget.ImageView
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val bitmap = (ContextCompat.getDrawable(this, R.drawable.image) as BitmapDrawable).bitmap
val w = bitmap.width
val h = bitmap.height
val pix = IntArray(w * h)
bitmap.getPixels(pix, 0, w, 0, 0, w, h)
val resultPixes = gray(pix, w, h)
val result = Bitmap.createBitmap(w, h, Bitmap.Config.RGB_565)
result.setPixels(resultPixes, 0, w, 0, 0, w, h)
val img = findViewById<View>(R.id.img2) as ImageView
img.setImageBitmap(result)
}
external fun gray(buf: IntArray, w: Int, h: Int): IntArray
companion object {
init {
System.loadLibrary("native-lib")
}
}
}