zoukankan      html  css  js  c++  java
  • (原+转)Eclipse中Android调用OpenCv

    大部分都是参考下面的网址,如果感觉看起来不舒服,可以直接查看原网址。最后遇到了一点问题:

    Description      Resource Path Location   Type

    E:/~codeEclipseopencvV4sdk ativejni/../libs/armeabi-v7a/libopencv_core.a(persistence.cpp.o): in function cvOpenFileStorage:persistence.cpp(.text.cvOpenFileStorage+0x1ac): error: undefined reference to 'gzrewind'         ~       C/C++ Problem

    可以直接拖到最后查看。

    参考文章: http://www.cnblogs.com/adong7639/p/3925347.html(WINDOWS系统Eclipse+NDK+Android + OpenCv)

    使用的ADT:

     

    使用的NDK:android-ndk-r10c

    使用的opencv:OpenCV-2.4.9-android-sdk

    具体的配置就不说了,由于自己是NDK中直接调用opencv的函数,因而直接说明此步骤。

    1. 将OpenCV-2.4.9-android-sdk 中的sdk文件夹放到Eclipse工程中,为了方便查看,可以改名成opencvV4sdk。

    2. 安装OpenCV_Manager,没有测试如果不安装这个会怎么样(卸载后继续运行程序,可以正常运行。因而不确定是否一定需要这步)。

    3. 利用JNI接口通过NDK平台调用OpenCV API函数

    1. 新建一个Android工程 NDK_OPENCV(后面将会看到这种命名方式不是很好)

    默认使用MainActivitiy,包名com.example.ndk_opencv

    1. 构建Android的Java层代码

     (1)布局文件:main.xml 

     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2 xmlns:tools="http://schemas.android.com/tools"
     3 android:layout_width="match_parent"
     4 android:layout_height="match_parent"
     5 tools:context="${packageName}.${activityClass}" >
     6 <Button
     7 android:id="@+id/imagegray"
     8 android:layout_width="fill_parent"
     9 android:layout_height="wrap_content"
    10 android:text="图像灰度化" />
    11  
    12 <ImageView
    13 android:id="@+id/imageview"
    14 android:layout_width="wrap_content"
    15 android:layout_height="wrap_content"
    16 android:layout_below="@+id/imagegray"
    17 android:layout_centerHorizontal="true"
    18 android:layout_marginTop="86dp" />
    19 </RelativeLayout>

    (2) 在AndroidManifest.xml文件中加入

    1 <!-- 在SDCard中创建与删除文件权限 -->
    2 <uses-permission
    3 android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
    4 <!-- 往SDCard写入数据权限 -->
    5 <uses-permission
    6 android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

     (3) MainActivity.java

     1 package com.example.ndk_opencv;
     2 
     3 import android.annotation.SuppressLint;
     4 import android.app.Activity;
     5 import android.graphics.Bitmap;
     6 import android.graphics.Bitmap.Config;
     7 import android.graphics.BitmapFactory;
     8 import android.os.Bundle;
     9 import android.view.View;
    10 import android.view.View.OnClickListener;
    11 import android.widget.Button;
    12 import android.widget.ImageView;
    13 
    14 @SuppressLint("SdCardPath")
    15 public class MainActivity extends Activity {
    16 private Button btngray;
    17 private ImageView imageview;
    18 private Bitmap bmp;
    19 
    20     @SuppressLint("SdCardPath")
    21     @Override
    22     protected void onCreate(Bundle savedInstanceState) {
    23         super.onCreate(savedInstanceState);
    24         setContentView(R.layout.activity_main);
    25         this.setTitle("Android NDK OpenCV");
    26         btngray = (Button)findViewById(R.id.imagegray);
    27 //btnProc.setOnClickListener(this);
    28 
    29 imageview = (ImageView)this.findViewById(R.id.imageview);
    30 
    31 bmp=BitmapFactory.decodeFile("/sdcard/andimg/img1.jpg");
    32 
    33 imageview.setImageBitmap(bmp);
    34 
    35 //点击按钮,调用Opencv接口实现SD卡中的图片灰度化
    36 
    37 btngray.setOnClickListener(new OnClickListener() {    
    38             @Override
    39             public void onClick(View v) {
    40          bmp=BitmapFactory.decodeFile(stringNDKOPENCV());
    41          imageview.setImageBitmap(bmp);
    42             }
    43         });
    44     }
    45 
    46     //通过jni接口实现的本地函数
    47 
    48     public native String stringNDKOPENCV();
    49 
    50     static {
    51             System.loadLibrary("NDK_OPENCV");
    52 }
    53 }

    3.2 配置工程的NDK编译环境

    3.2.1在工程上右键点击Android Tools->Add Native Support...,然后给我们的.so文件取个名字,例如: NDK_OPENCV(默认为工程名字)

    这时候工程就会多一个jni的文件夹,jni下有Android.mk和NDK_OPENCV.cpp文件。

    3.2.2工程右键,点Properties->C/C++ Build的Building Settings中去掉Use default build command,然后输入${NDKROOT}/ndk-build.cmd 

    3.2.3在C/C++ Build中点击Environment,点Add...添加环境变量NDKROOT,值为NDK的根目录E:projectAndroidadt-bundle-windows-x86-20140321android-ndk-r10 

    3.3 编写NDK_OPENCV.cpp文件

    3.3.1生成.h文件

    (其实此步骤可以不管,即便不生成.h文件,也可以正常使用.so文件)

    在编写NDK_OPENCV.cpp文件前,需要利用javah这个工具生成相应的.h文件,然后根据这个.h文件编写相应的C/C++代码。用eclipse编译该工程,生成相应的.class文件,这步必须在下一步之前完成,因为生成.h文件需要用到相应的.class文件。暂时不考虑报错信息。

    进入到刚才建立的NDK_OPENCV工程目录中,在工程目录下执行: 

    Javah -classpath binclasses -d jni com.example.ndk_opencv.MainActivity

    这里-classpath表示类的路径;-d jni表示生成的.h文件存放的目录com.example.ndk_opencv.MainActivity则是完整的类名。现在可以在jni目录下看到多了一个.h文件:com_example_ndk_opencv_MainActivity.h;

    打开后,可以看到.h的内容:

     1 /* DO NOT EDIT THIS FILE - it is machine generated */
     2 #include <jni.h>
     3 /* Header for class com_example_ndk_opencv_MainActivity */
     4 
     5 #ifndef _Included_com_example_ndk_opencv_MainActivity
     6 #define _Included_com_example_ndk_opencv_MainActivity
     7 #ifdef __cplusplus
     8 extern "C" {
     9 #endif
    10 
    11 /*
    12 
    13 * Class: com_example_ndk_opencv_MainActivity
    14 
    15 * Method: stringNDKOPENCV
    16 
    17 * Signature: ()Ljava/lang/String;
    18 
    19 */
    20 
    21 JNIEXPORT jstring JNICALL Java_com_example_ndk_1opencv_MainActivity_stringNDKOPENCV
    22  (JNIEnv *, jobject);
    23 
    24 #ifdef __cplusplus
    25 
    26 }
    27 #endif
    28 #endif

    代码解释:

    1. JNI接口的命名规范是:Java_ + 调用该方法的包名(包名的点用_代替) + _ + 调用该接口的类名 + _ + 方法名。函数名比较长但是完全按照:java_pacakege_class_mathod 形式来命名。也就是说:MainActivity.java中stringNDKOPENCV () 方法对应于 C/C++中的 Java_com_example_ndk_1opencv_MainActivity_stringNDKOPENCV () 方法。
    2. 对于实例方法, JNIEXPORT 和 JNICALL 是jni的宏,在android的jni中不需要,当然写上去也不会有错。注意下其中的注释:Signature: ()Ljava/lang/String表示函数的参数为空,这里为空是指除了JNIEnv *, jobject 这两个参数之外没有其他参数,JNIEnv*, jobject是所有jni函数必有的两个参数,分别表示jni环境和对应的java类(或对象)本身,Ljava/lang/String表示函数的返回值是java的String对象。
    3. ndk_1opencv 代码中的红色标记处多了个1,这个1应该表示ndk_opencv为一个整体而非继承结构,因此不建议包名出现空格,以免出错。

    3.3.2 编写NDK_OPENCV.cpp

     1 #include <jni.h>
     2 #include <string.h>
     3 #include <opencv2/core/core.hpp>
     4 #include <opencv2/features2d/features2d.hpp>
     5 #include <opencv2/highgui/highgui.hpp>
     6 #include <opencv2/imgproc/imgproc.hpp>
     7 #include <opencv2/calib3d/calib3d.hpp>
     8 #include <opencv2/imgproc/imgproc_c.h>
     9 
    10 extern "C" jstring
    11 
    12 Java_com_example_ndk_1opencv_MainActivity_stringNDKOPENCV( JNIEnv* env,
    13 jobject thiz )
    14 {
    15     //return env->NewStringUTF("/sdcard/andimg/img2.jpg");
    16      const char* file="/sdcard/andimg/img1.jpg";
    17      IplImage* object = cvLoadImage(file,CV_LOAD_IMAGE_GRAYSCALE);
    18      std::string filePath="/sdcard/andimg/img1_result.jpg";
    19      jstring filePath1=env->NewStringUTF(filePath.c_str());
    20      const char * resultpath=env->GetStringUTFChars(filePath1, 0);
    21      cvSaveImage(resultpath,object);
    22      //env->ReleaseStringUTFChars(path, file);
    23      env->ReleaseStringUTFChars(filePath1, resultpath);
    24      return filePath1;
    25 }

    代码解释:这段代码首先读取了SD卡中的一张图像,接着调用env->GetStringUTFChars,以灰度形式读取图像并保存在SD卡中,最后返回灰度图像的路径。

    3.4利用NDK平台编译C++语言函数成.so文件

    3.4.1首先需要编写Android.mk文件

     1 LOCAL_PATH := $(call my-dir) 
     2 include$(CLEAR_VARS) 
     3 # OpenCV 
     4 OPENCV_CAMERA_MODULES:=on 
     5 OPENCV_INSTALL_MODULES:=on 
     6 OPENCV_LIB_TYPE:=STATIC 
     7 include E:projectJavaWorkJavaExistWorksdknativejniOpenCV.mk 
     8 LOCAL_MODULE := NDK_OPENCV 
     9 LOCAL_SRC_FILES := NDK_OPENCV.cpp 
    10 include$(BUILD_SHARED_LIBRARY) 

    3.4.2同时建立Application.mk文件

    1 APP_STL := gnustl_static 
    2 APP_CPPFLAGS := -frtti -fexceptions 
    3 APP_ABI := armeabi-v7a 
    4 APP_PLATFORM := android-9 

    4测试运行

        如果在Eclipse下面打开NDK_OPEC.cpp文件会出现很多错误,需要将错误删除掉,否则无法编译。

    "Eclipse可能报一堆的错误提示 由于eclipse的语法检查,当你打开一个源码,尤其是引入外面开发完成的项目,因为源码不是在工程中管理的,大部分情况会报一堆的错误提示,而你是明 确这些问题实际上是不存在的,那么就可以这样子做了,设置项目属性,把eclipse多管的这些闲事给免了它的职,如下图,保存后,你会发现你的 problems窗口下非常清爽了:"

    解决方法之一:需要将错误删除掉,否则无法编译。

    解决方法之二:打开工程属性,选择C/C++ General 中的Code Analysis ,接着选择Useproject setting 去掉Syntax and Semantic……,这是Eclipse在检测一些不符合java中的符号报错,其实代码没有错的。

    运行结果

    问题:按照示例编译代码没问题,但是自己的代码调用opencv则出现如下错误:

    之后,参考:

    http://stackoverflow.com/questions/10858055/opencv2-4-with-android-native-activity

    在Android.mk中加上了

    LOCAL_LDLIBS += -lz # Compression library

    之后,错误消失。

  • 相关阅读:
    shell 函数用法
    shell read变量的读入
    利用系统函数模拟实现nginx 系统脚本启动的特殊颜色专业效果
    shell重定向介绍及使用
    监控MySQL或Web服务是否正常
    centos 6.5下安装nmap工具及简单用法
    if条件简单语法
    shell 的条件表达式及逻辑操作符简单介绍
    mysql常见的错误代码
    Linux MySql 安装与配置(二进制包)
  • 原文地址:https://www.cnblogs.com/darkknightzh/p/4239202.html
Copyright © 2011-2022 走看看