安卓下c语言opencv,Android基于CMake进行OpenCV开发配置

一、创建支持C++的android基础模版项目

新建项目,勾选【Include C++ support】,后续一直按【next】按钮取默认设置即可。

9f5758c36b34

image.png

最终生成的目录结构如下图:

9f5758c36b34

image.png

此时直接build并运行能正确看到效果。

打开MainActivity,可以看到生成的示例代码:

public class MainActivity extends AppCompatActivity {

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

static {

System.loadLibrary("native-lib");

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// Example of a call to a native method

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

tv.setText(stringFromJNI());

}

/**

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

* which is packaged with this application.

*/

public native String stringFromJNI();

}

再打开 native-lib.cpp 文件,也可以看到自动生成的JNI风格代码:

#include

#include

extern "C" JNIEXPORT jstring

JNICALL

Java_com_woodstream_opencvdemo_MainActivity_stringFromJNI(

JNIEnv *env,

jobject /* this */) {

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

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

}

其中Java_com_woodstream_opencvdemo_MainActivity_stringFromJNI就包含了java对应方法的不少信息。

为了看看IDE是怎么操作的,回到MainActivity,写入一个新的方法:

public native int[] gray(int[] buf, int w, int h);

9f5758c36b34

image.png

此时方法名会标红,在IDE的智能提示下选择Create function xxx,会自动跳转到native-lib.cpp文件,并且自动添加了代码:

extern "C"

JNIEXPORT jintArray JNICALL

Java_com_woodstream_opencvdemo_MainActivity_gray(JNIEnv *env, jobject instance, jintArray buf_,

jint w, jint h) {

jint *buf = env->GetIntArrayElements(buf_, NULL);

// TODO

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

}

就这么简单的步骤就可以进行JNI的开发,可见Android Studio(下称AS)大为减少我们编写JNI的工作量,而它又是怎么工作的?常规的makefile什么的不用了?

二、默认CMake的构建方式

可以看到目录有一个CMakeLists.txt文件。

打开build.gradle,看到有外部native编译的配置:

9f5758c36b34

image.png

打开app/build/intermediates/cmake目录,看到其子目录下生成了so文件:

9f5758c36b34

image.png

从这几个信息可以知道AS默认是通过CMake来完成上述操作的,当然也支持android.mk的方式,但比后者要方便不少。

三、用CMake的方式集成OpenCV

首先,可以先看下此文:Android 接入 OpenCV库的三种方式

除非你是用java写图像处理算法,不然不建议用第一种方式,因为图像识别实现考虑由C++来完成,所以选用第二种方式,此时如下步骤搭建OpenCV的环境:

新建jniLibs文件夹,把OpenCV中sdk/native/libs内容复制到其下:

9f5758c36b34

image.png

修改CMakeLists.txt文件:

# For more information about using CMake with Android Studio, read the

# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

set(pathToOpenCv /Users/woodstream/Documents/dev/projects/android/OpenCV-android-sdk)#设置OpenCv的路径变量

cmake_minimum_required(VERSION 3.4.1)

#支持-std=gnu++11

set(CMAKE_VERBOSE_MAKEFILE on)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

#配置加载native依赖

include_directories(${pathToOpenCv}/sdk/native/jni/include)

#动态方式加载

add_library(lib_opencv STATIC IMPORTED ) #表示创建一个导入库,静态方式

#引入libopencv_java3.so文件

set_target_properties(lib_opencv

PROPERTIES

IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/src/main/jniLibs/${}/libopencv_java3.so

)

# Creates and names a library, sets it as either STATIC

# or SHARED, and provides the relative paths to its source code.

# You can define multiple libraries, and CMake builds them for you.

# Gradle automatically packages shared libraries with your APK.

#自己的源文件

add_library( # Sets the name of the library.

native-lib

# Sets the library as a shared library.

SHARED

# Provides a relative path to your source file(s).

src/main/cpp/native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a

# variable. Because CMake includes system libraries in the search path by

# default, you only need to specify the name of the public NDK library

# you want to add. CMake verifies that the library exists before

# completing its build.

find_library( # Sets the name of the path variable.

log-lib

# Specifies the name of the NDK library that

# you want CMake to locate.

log )

# Specifies libraries CMake should link to your target library. You

# can link multiple libraries, such as libraries you define in this

# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.

native-lib

# Links the target library to the log library

# included in the NDK.

${log-lib} android -ljnigraphics lib_opencv)

至此环境已经搭好了(主要修改pathToOpenCv、set_target_properties的IMPORTED_LOCATION、add_library的source file)。

四、编写代码测试效果

完善C++文件native-lib.app先前生成的gray方法:

#include

#include

#include

#include

#include

#include

using namespace cv;

using namespace std;

extern "C"

JNIEXPORT jintArray JNICALL

Java_com_eastcom_cpptest_MainActivity_gray(JNIEnv *env, jobject instance, jintArray buf, jint w,

jint h) {

jint *cbuf = env->GetIntArrayElements(buf, JNI_FALSE );

if (cbuf == NULL) {

return 0;

}

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

//对于一个int四字节,其彩色值存储方式为: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] = grayScale;

ptr[4*i+2] = grayScale;

ptr[4*i+0] = grayScale;

}

int size = w * h;

jintArray result = env->NewIntArray(size);

env->SetIntArrayRegion(result, 0, size, cbuf);

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

return result;

}

MainActivity改成:

public class MainActivity extends AppCompatActivity {

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

static {

System.loadLibrary("native-lib");

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(

R.mipmap.pic_test)).getBitmap();

int w = bitmap.getWidth(), h = bitmap.getHeight();

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

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

// 调用JNI实现的gray方法

int [] resultPixes = gray(pix,w,h);

Bitmap result = Bitmap.createBitmap(w,h, Bitmap.Config.RGB_565);

result.setPixels(resultPixes, 0, w, 0, 0,w, h);

ImageView img = (ImageView)findViewById(R.id.img2);

img.setImageBitmap(result);

}

/**

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

* which is packaged with this application.

*/

public native int[] gray(int[] buf, int w, int h);

public native String stringFromJNI();

}

activity_main.xml布局文件改成:

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

android:id="@+id/activity_main"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="16dp"

android:paddingLeft="16dp"

android:paddingRight="16dp"

android:paddingTop="16dp"

android:orientation="vertical"

tools:context="com.eastcom.cpptest.MainActivity">

android:id="@+id/txt"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="原图:" />

android:id="@+id/img"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:src="@mipmap/pic_test"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_marginTop="10dp"

android:text="处理后的图:" />

android:id="@+id/img2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"/>

此时编译运行可以看到效果如图:

9f5758c36b34

运行图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值