在Android中使用Opencv有兩種方式,
一種是使用opencv的Java版本的API,但是這種方式不是通過本地調用實現的,全部都是java代碼,所以這裡先不講,
另外一種方式就是使用opencv的c++版本的API,將本地c++代碼編譯成.so鏈接庫,然後在安卓開發中進行調用,本地cpp代碼使用NDK進行編譯。
下面給出一個使用Canny算子檢測邊緣的本地代碼調用的使用方式。
新建Android Prject,這裡我的項目名稱為HaveImgFun
然後修改界面控製文件res->layout->activity_have_img_fun.xml
activity_have_img_fun.xml code<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="@+id/btnNDK"
android:text="使用C++ OpenCV进行处理" />
<Button android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:id="@+id/btnRestore"
android:text="还原" />
<TextView
android:text="TextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/textView2" />
<ImageView android:id="@+id/ImageView01"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
在文件夾src下的com.XXX.haveimgfun包中新建一個類用於包裝使用了opencv c++代碼的動態庫的導出函數,類名為LibImgFun。 Android Studio會為你創建一個新的文件LibImgFun.java,將裡面的內容改為:
package com.example.cheng.haveimgfun;
/**
* Created by Cheng on 2016/11/23.
*/
public class LibImgFun {
static {
System.loadLibrary("ImgFun");
}
public static native int[] ImgFun(int[] buf, int w, int h);
public native String getMycstring();
}
從上面的代碼可以得知,我們的動態庫名字應該為“
libImgFun.so”。
注意"public static native int[] ImgFun(int[] buf, int w, int h)"中的native關鍵字,表明這個函數來自native code。static表示這是一個靜態函數,
這樣就可以直接用類名去調用。
建立C++代碼
在項目中新建一個jni文件,用於放置該項目的所有cpp代碼。
在jni文件夾下建立一個"ImgFun.cpp"的文件,內容改為下面所示:
//
// Created by Cheng on 2016/11/23.
//
//
// Created by Cheng on 2016/11/23.
//
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
#include "com_example_cheng_haveimgfun_LibImgFun.h"
JNIEXPORT jstring JNICALL Java_com_example_cheng_haveimgfun_LibImgFun_getMycstring
(JNIEnv * evn, jobject obj) {
return ( * evn).NewStringUTF("Hello NKD demo");
}
using namespace cv;
IplImage * change4channelTo3InIplImage(IplImage * src);
extern "C" {
JNIEXPORT jintArray JNICALL Java_com_example_cheng_haveimgfun_LibImgFun_ImgFun
(JNIEnv * env, jobject obj, jintArray buf, jint w, jint h) {
jint * cbuf;
cbuf = env - > GetIntArrayElements(buf, NULL);
printf("%d",cbuf);
if (cbuf == NULL) {
return 0;
}
Mat myimg(h, w, CV_8UC4, (unsigned char * ) cbuf);
IplImage image = IplImage(myimg);
IplImage * image3channel = change4channelTo3InIplImage( & image);
IplImage * pCannyImage = cvCreateImage(cvGetSize(image3channel), IPL_DEPTH_8U, 1);
cvCanny(image3channel, pCannyImage, 50, 150, 3);
int * outImage = new int[w * h];
for (int i = 0; i < w * h; i++) {
outImage[i] = (int) pCannyImage - > imageData[i];
}
int size = w * h;
jintArray result = env - > NewIntArray(size);
env - > SetIntArrayRegion(result, 0, size, outImage);
env - > ReleaseIntArrayElements(buf, cbuf, 0);
return result;
}
}
IplImage * change4channelTo3InIplImage(IplImage * src) {
if (src - > nChannels != 4) {
return NULL;
}
IplImage * destImg = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);
for (int row = 0; row < src - > height; row++) {
for (int col = 0; col < src - > width; col++) {
CvScalar s = cvGet2D(src, row, col);
cvSet2D(destImg, row, col, s);
}
}
return destImg;
}
配置文件
然後再在jni下新建兩個文件"Android.mk"文件和"Application.mk"文件,這兩個文件事實上就是簡單的Makefile文件。
使用NDK進行編譯的時候,需要使用 Android.mk 和 Application.mk 兩個文件。
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE:=STATIC
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
#try to load OpenCV.mk from default install location
include D:\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := ImgFun
LOCAL_SRC_FILES := ImgFun.cpp
include $(BUILD_SHARED_LIBRARY)
在Android.mk文件中,需要主要修改的代碼是如下一行:
include D:\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk
Application.mk
APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI := all
Reference:
http://blog.csdn.net/watkinsong/article/details/8829235
http://blog.csdn.net/watkinsong/article/details/9849973
安裝環境