花了一个星期时间研究NDK编译OpenCV今天终于搞定了。。。。。看了网上无数的文章,感觉都写的不详细,现在我要整理一下整个NDK编辑过程
先给出一个连接参考 http://underthehood.blog.51cto.com/2531780/670169 虽然没成功,但是给我了很大的提示
好了首先要准备的工具
Cygwin 自行下载最近的
NDK 我用的是 r8版本的(之前用r7但是一直错,后来查了才知道r7有点BUG)
然后下载opencv-android2.3.1 http://sourceforge.net/projects/opencvlibrary/files/opencv-android/2.3/ 选择OpenCV-2.3.1-beta1-android-bin.tar.bz2 进行下载
这个是已经编辑好的
然后解压后~你应该可以看到这个目录
将其解压到你的文件下
然后穿件一个Android的工程 比如:我创建了一个OpenCVJNI
在你的工程目录下 新建一个jni目录 ,这个目录是存放你的 C/C++原分件和Android.mk (还有Application.mk,这个是可选的)
如何写C源代码这里我就不详细介绍了 我讲我参考的C的代码贴上
#include
#include
#include
#include
#include
#include
#include
#include
#define LOG_TAG "opencv_smooth"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
using namespace std;
using namespace cv;
extern "C" {
JNIEXPORT void JNICALL Java_XJ_Work_JNI_OpenCV_Util_JNI_1OpenCV_JSmooth(
JNIEnv* env,jobject thiz, jintArray javaIntArray0,
jintArray dstArray, jint width, jint height, jint smoothpara) {
LOGI("load image 1");
jint* src = env->GetIntArrayElements(javaIntArray0, 0);
LOGI("load image 2");
jint* dst = env->GetIntArrayElements(dstArray, 0);
LOGI("load image 3");
Mat srcMat = Mat(Size(width, height), CV_8UC4, (unsigned char*) src);
LOGI("load image 4");
Mat dstMat = Mat(Size(width, height), CV_8UC4, (unsigned char*) dst);
LOGI("load image 5");
CvMat cvsrcMat = srcMat;
LOGI("load image 6");
CvMat cvdstMat = dstMat;
LOGI("load image successfully");
cvSmooth(&cvsrcMat, &cvdstMat,CV_GAUSSIAN,smoothpara,0,0,0);//高斯模糊
LOGI("smooth image successfully");
env->ReleaseIntArrayElements(javaIntArray0, src, 0);
env->ReleaseIntArrayElements(dstArray, dst, 0);
}
}
这是一个处理图像使之模糊的函数
现在开始写mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include F:/workspace/OpenCV-2.3.1/share/OpenCV/OpenCV.mk // 这个是opencv下的opencv.mk文件的路径
LOCAL_MODULE := opencv_xj
LOCAL_SRC_FILES := opencv_xj.cpp
LOCAL_LDLIBS += -ldl -llog //这个如果你需要用到 android的Log功能 需要导入 -llog ,-ldl 是导入动态库的意思
include $(BUILD_SHARED_LIBRARY)
然后是开始写你的Application.mk(我现在也不知道什么情况下才需要用到这个文件)
APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI := armeabi armeabi-v7a //如果是2.2以上的版本需要 写armeabi-v7a
APP_PLATFORM := android-8
STLPORT_FORCE_REBUILD := true
然后很关键的一步:你需要将samples中的includeOpenCV.mk文件放到 你自己的工程目录下!!!
(当然这个是我已经编辑完成的所有目录,如果你还没用NDK编辑的话 obj和libs目录是不存在的)
现在可以进入Cygwin到$(你的工程目录)/jni下
用NDK命令编辑 (关于NDK的配置参考其他资料 http://blog.csdn.net/cxj1991/article/details/7694093)
好了,现在你觉得OK了吧。。。no!!!
因为接下来你可能会碰到这个问题
解决方法 在提示的目录下 找到这个文件 用UE打开 将64行改成 $(LOCAL_BUILT_MODULE): $(LOCAL_OBJECTS=%)
(这个是之前用NDK R7时做的出现的错误)
然后你继续编辑 可能还会碰到
然后你需要在你的NDK的 \sources\cxx-stl\gnu-libstdc++\libs\armeabi中找到这个静态文件 (如果你的Application.mk 中写了 armeabi-v7a,等会还会有需要这个文件的提示
目录也是一样的NDK的\sources\cxx-stl\gnu-libstdc++\libs\armeabi-v7a中找到它就行了),将它放入到F:\workspace\OpenCVJNI\obj\local\armeabi下面(这时你的工程目录会生成一个obj的目录)然后继续编译
很好,现在你需要在(你的OpenCV-2.3.1目录)\libs\armeabi下所有的静态库都复制到 之前的(你工程目录)\obj\local\armeabi下
继续编译
你需要将(你的OpenCV-2.3.1目录)\share\OpenCV\3rdparty\libs\armeabi下的文件复制到 (你工程目录)\obj\local\armeabi下
这个情况是你的Application.mk中写了armeabi-v7a的原因 ,然后就是一样的继续复制 只不过是放到(你工程目录)\obj\local\armeabi-7va下
OK,如果你的C源代码没有写错误的话 那么你应该可以看到 这个
编辑成功 得到我们需要的库文件了!(靠,就是这些问题我搞了差不多一个星期)
然后就是在java中使用了
比如我的代码
public class JNI_OpenCV {
static{
System.loadLibrary("opencv_xj");
}
public native void JSmooth(int[] src, int[] dst, int width, int height, int smoothpara);
}
public class OpenCVJNIActivity extends Activity {
/** Called when the activity is first created. */
private Button mohu;
private ImageView img;
private JNI_OpenCV jni;
String file = null;
Bitmap bm = null;
Bitmap map = null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mohu = (Button) findViewById(R.id.mohu);
img = (ImageView) findViewById(R.id.img);
jni = new JNI_OpenCV();
BitmapFactory.Options option = new BitmapFactory.Options();
option.inPreferredConfig = Config.ARGB_8888;
bm = BitmapFactory.decodeResource(this.getResources(),R.drawable.text);
img.setImageBitmap(bm);
mohu.setOnClickListener(new Button.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//String outfile = file+File.separator+"end.jpg";
int width = bm.getWidth();
int height = bm.getHeight();
int[] src=new int[width*height];
int[] dst=new int[width*height];
bm.getPixels(src,0, width, 0, 0, width, height);
/* 如果要对图像进行编辑 必须要使用Bitmap.createBitmap,
* 不然使用BitmapFactory.decodeResource(this.getResources(),R.drawable.text);
* 是不能对图像进行编辑,会报一个异常
* AndrodRuntime Caused by:java.lang.IllegalStateException
AndrodRuntime at android.graphics.Bitmap.setPixels(Bitmap.java:853)
*/
map = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
jni.JSmooth(src,dst,width,height,11);
map.setPixels(dst,0, width,0, 0, width,height);
img.setImageBitmap(map);
}
});
}
}
最后运行
完成!