OpenCV+NDK 模糊处理图像 (完全版)

来源:互联网 发布:ie11有道网络已断开 编辑:程序博客网 时间:2024/06/05 01:19

花了一个星期时间研究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 <string.h>
#include <jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <cv.h>
#include <cxcore.h>
#include <android/log.h>

#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);
            }
        });
    }

}


最后运行

完成!



原创粉丝点击