怎样在eclipse中加载opencv for android

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎样在eclipse中加载opencv for android相关的知识,希望对你有一定的参考价值。

android中使用Opencv

使用opencv有两种方式,一种是使用opencv的java版本的API,但是这种方式不是通过本地调用实现的,全部都是java代码,所以这里先不讲,另外一种方式就是使用opencv的c++版本的API,将本地c++代码编译成.so链接库,然后在安卓开发中进行调用,本地cpp代码使用NDK进行编译。

5.1
安卓代码

下面给出一个使用Canny算子检测边缘的本地代码调用的使用方式。

新建安卓项目,配置使用安卓API等信息,这里我的项目名称为HaveImgFun

然后修改界面控制文件res->layout->activity_have_img_fun.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_
android:layout_
>
<Button android:layout_
android:layout_
android:id="@+id/btnNDK"
android:text="使用C++ OpenCV进行处理" />
<Button android:layout_
android:layout_
android:id="@+id/btnRestore"
android:text="还原" />
<ImageView android:id="@+id/ImageView01"
android:layout_
android:layout_ />
</LinearLayout>

在文件夹src下的com.testopencv.haveimgfun包中新建一个类用于包装使用了opencv
c++代码的动态库的导出函数,类名为LibImgFun。

Eclipse会为你创建一个新的文件LibImgFun.java,将里面的内容改为:
package com.testopencv.haveimgfun;
public class LibImgFun
static
System.loadLibrary("ImgFun");

/**
* @param width the current view width
* @param height the current view height
*/
public static native int[] ImgFun(int[] buf, int w, int h);


从上面的代码可以得知,我们的动态库名字应该为“libImgFun.so”,注意"public
static native int[] ImgFun(int[] buf, int w, int h)"中的native关键字,表明这个函数来自native
code。static表示这是一个静态函数,这样就可以直接用类名去调用。

修改功能代码,修改HaveImgFun.java的代码,代码内容如下:
package com.testopencv.haveimgfun;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.widget.Button;
import android.view.View;
import android.widget.ImageView;

public class HaveImgFun extends Activity
/** Called when the activity is first created. */
ImageView imgView;
Button btnNDK, btnRestore;

@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_have_img_fun);

this.setTitle("使用NDK转换灰度图");
btnRestore = (Button) this.findViewById(R.id.btnRestore);
btnRestore.setOnClickListener(new ClickEvent());
btnNDK = (Button) this.findViewById(R.id.btnNDK);
btnNDK.setOnClickListener(new ClickEvent());
imgView = (ImageView) this.findViewById(R.id.ImageView01);
Bitmap img = ((BitmapDrawable) getResources().getDrawable(
R.drawable.lena)).getBitmap();
imgView.setImageBitmap(img);


class ClickEvent implements View.OnClickListener
public void onClick(View v)
if (v == btnNDK)
long current = System.currentTimeMillis();
Bitmap img1 = ((BitmapDrawable) getResources().getDrawable(
R.drawable.lena)).getBitmap();
int w = img1.getWidth(), h = img1.getHeight();
int[] pix = new int[w * h];
img1.getPixels(pix, 0, w, 0, 0, w, h);
int[] resultInt = LibImgFun.ImgFun(pix, w, h);
Bitmap resultImg = Bitmap.createBitmap(w, h, Config.RGB_565);
resultImg.setPixels(resultInt, 0, w, 0, 0, w, h);
long performance = System.currentTimeMillis() - current;
imgView.setImageBitmap(resultImg);
HaveImgFun.this.setTitle("w:" + String.valueOf(img1.getWidth())
+ ",h:" + String.valueOf(img1.getHeight()) + "NDK耗时"
+ String.valueOf(performance) + " 毫秒");
else if (v == btnRestore)
Bitmap img2 = ((BitmapDrawable) getResources().getDrawable(
R.drawable.lena)).getBitmap();
imgView.setImageBitmap(img2);
HaveImgFun.this.setTitle("使用OpenCV进行图像处理");





5.2 C++代码

在项目中新建一个jni文件,用于放置该项目的所有cpp代码。

在jni文件夹下建立一个"ImgFun.cpp"的文件,内容改为下面所示:

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
using namespace cv;
IplImage * change4channelTo3InIplImage(IplImage * src);

extern "C"
JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(
JNIEnv* env, jobject obj, jintArray buf, int w, int h);
JNIEXPORT jintArray JNICALL Java_com_testopencv_haveimgfun_LibImgFun_ImgFun(
JNIEnv* env, jobject obj, jintArray buf, int w, int h)

jint *cbuf;
cbuf = env->GetIntArrayElements(buf, false);
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;

在上面的代码中,给出了简单的Canny算子检测边缘的代码,并且返回检测后的图像显示。
上面的代码中#include
<jni.h>是必须要包含的头文件,#include
<opencv2/opencv.hpp>是opencv要包含的头文件。

5.3
配置文件

然后再在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 E:\\java\\OpenCV-2.4.5-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)
Application.mk: APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI:=armeabi armeabi-v7a
在Android.mk文件中,需要主要修改的代码是如下一行: include E:\\java\\OpenCV-2.4.5-android-sdk\\sdk\\native\\jni\\OpenCV.mk

这里需要将Android
SDK中的OpenCV.mk文件包含进来,可以使用相对路径或者绝对路径。但是最好不要将Android
SDK放在和工作空间不在一个磁盘分区的地方,这样很容易出错。

然后需要使用LOCAL_SRC_FILES包含需要编译的文件。

5.4
编译本地C++代码

编译本地C++代码可以使用Cygwin进行编译,cd
到项目目录,然后运行ndk-build

也可以使用windows控制台进行编译,同样cd到项目目录,运行ndk-build

还可以使用Eclipse进行编译,建议配置使用Eclipse进行编译,这样当项目的本地cpp代码发生变化的时候就可以实现自动的cpp代码编译,不用每次都在命令行中手动的进行编译,虽然使用黑乎乎的命令行手动编译,输出一堆信息显着很牛逼的样子。

(一下内容,如果使用cygwin进行编译,则不需要进行操作,直接使用cygwin或者命令行进行编译,保证编译通过以后即可运行程序,如果选择使用Eclipse自动进行编译,则参考一下内容进行配置)

首先需要将该项目转换到C++项目,使得该项目具有C++代码属性,如下所述。

点击项目,右击,
New
-> Other -> C/C++ -> Convert to a C/C++ Project .

配置Eclipse对cpp代码进行编译:

首先需要给当前项目添加一个编译环境变量

如下目录

open
Eclipse menu Window -> Preferences -> C/C++ -> Build
-> Environment ,

点击
Add...

添加一个NDKROOT,并且设置值为Android
SDK的根目录。

然后设置编译的一些参数

Project
Properties -> C/C++ Build , uncheck Use
default build command ,
replace “Build command” text from "make"
to

"$NDKROOT/ndk-build.cmd"
on Windows,

"$NDKROOT/ndk-build"
on Linux and MacOS.
参考技术A 第一部分 准备工作:
1.1 本文所使用的软件版本如下:
ADT版本:ADT-22.6.3 , 开发工具ADT(Android Development Tool),集成了最新的ADT和NDK插件以及Eclipse,还有一个最新版本SDK。解压之后就可以用了,下载地址 http://developer.android.com/tools/sdk/ndk/index.html
NDK: android-ndk-r10, NDK插件:用于开发Android NDK的插件,ADT版本在20以上,就能安装NDK插件,另外NDK集成了CDT插件,NDK版本在r7以上之后就集成了Cygwin,而且还是十分精简版。下载链接见: http://developer.android.com/tools/sdk/ndk/index.html
OpenCV:OpenCV-2.4.4-android-sdk, 下载地址 http://opencv.org/downloads.html
1.2 配置NDK的环境变量
1.2.1解压NDK压缩包,配置环境变量。
将解压的地址写入环境变量PATH中。在命令提示符下输入ndk-build如果弹出如下的错误,而不是说ndk-build not found,就说明ndk环境已经安装成功了。特别提示一下,搜索引擎中会告诉一些早期的NDK版本的使用,是在命令提示符下输入build/host- setup.sh;但是NDK经过更新,这个文件已经没有了。只需要输入ndk-build就可以了。

Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
/home/braincol/workspace/android/android-ndk-r5/build/core/build-local.mk:85: *** Android NDK: Aborting . Stop.

1.2.2 Eclipse配置NDK环境
打开Eclipse,点Window->Preferences->Android->NDK,设置NDK路径,例如当前的NDK版本是是E:/android-ndk-r10。

1.3 配置OpenCv
下载 OpenCV-2.4.4-android-sdk解压出来,可以看到文件下有apk文件,doc文档,sample例子程序,以及OpenCV4Android-sdk。
其 中,OpenCV4Android-sdk目录即是我们开发opencv所需要的类库;samples目录中存放着若干opencv应用示例(包括人脸检测等),可为我们进行 android下的opencv开发提供参考;doc目录为opencv类库的使用说明及api文档等;而apk目录则存放着对应于各内核版本的。
1.3.1 安装OpenCV_Manager
OpenCV_2.4.3.2_Manager_2.4应用安装包。此应用用来管理手机设备中的opencv类库,在运行opencv应用之前,必须确保手机中已经安装了OpenCV_2.4.4.4_Manager_2.6_*.apk,否则opencv应用将会因为无法加载opencv类库而无法运行。
可以根据自己的手机类型来安装OpenCV_2.4.4.4_Manager.apk.
通过查询自己的手机CPU信息
参考技术B 这里有完整教程,你参考一下:
连接地址:

http://blog.csdn.net/donglynn/article/details/23301615
希望能帮到你,满意请采纳,欢迎追问。

以上是关于怎样在eclipse中加载opencv for android的主要内容,如果未能解决你的问题,请参考以下文章

怎样在treeview中加载数据库 C#

Arcgis for js,Openlayers中加载GeoJSON

在vector<Mat> Opencv中加载许多图像

如何在文件夹opencv&&qt c++中加载图像[关闭]

如何在 Jframe java(eclipse) 中加载图像?

如何将opencv Mat矩阵保存到可以在Matlab中加载的文件中