注:无法下载的会出现以下提示
此时采用有Android SDK在线更新镜像服务器来下载安装:
北京化工大学镜像服务器地址:
IPv4: ubuntu.buct.edu.cn/ 端口:80
IPv4: ubuntu.buct.cn/ 端口:80
IPv6: ubuntu.buct6.edu.cn/ 端口:80
大连东软信息学院镜像服务器地址: //一般用这个服务器比较快
mirrors.neusoft.edu.cn 端口:80
郑州大学开源镜像站:
mirrors.zzu.edu.cn 端口:80
使用方法:
启动 Android SDK Manager,打开主界面,依次选择『Tools』、『Options...』,弹出『Android SDK Manager - Settings』窗口;
在『Android SDK Manager - Settings』窗口中,在『HTTP ProxyServer』和『HTTP Proxy Port』输入框内填入上面镜像服务器地址(不包含http://,如下图)和端口,并且选中『Force https://... sources to be fetched using http://...』复选框。设置完成后单击『Close』按钮关闭『AndroidSDK Manager - Settings』窗口返回到主界面;
依次选择『Packages』、『Reload』
等待安装完成后,需要将SDK的文件安装路径配置到Eclipse上,单击“Browse…”按钮,选择你的SDK安装路径,添加好就行啦~如下图:
五、新建Android工程
5.1、打开eclipse,在Eclipse里,选择菜单项File—>New—>Project新建一个项目,我们就能看到建立Android项目的选项了:
5.2、接下来是选择API,重点,前往别选择错!!!!!
到此为止,新建Android工程,完毕。
六、配置AndroidNDK环境
6.1、在本文的资源包里面包含android-ndk64-r10-windows-x86_64.zip,解压到当前文件夹即可,如下图:
6.2、打开eclipse Window—>Prefernces—>Android—>NDK选择你NDKLocation的存放路径:
七、将该项目转换到C++项目
7.1、首先需要将该项目转换到C++项目,使得该项目具有C++代码属性,如下所述。
点击项目,右击,New -> Other -> C/C++ -> Convert to a C/C++ Project.
7.2、配置Eclipse对cpp代码进行编译:
首先需要给当前项目添加一个编译环境变量
如下目录Eclipse ->Window -> Preferences -> C/C++ -> Build ->Environment,点击Add...
添加一个NDKROOT,并且设置值为NDK的根目录,如下图:
7.3、在工程中设置编译的一些参数
右击你新建的工程,找到Properties,并按照顺序 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.如下图:
7.4、然后修改Behaviour选项卡,设置编译配置(配置在保存代码的时候进行自动编译)
7.5在此之后出现这种情况,不要着急,我们接着开始写C++程序,并编译成动态链接库;
八、在Android中使用Opencv
8.1、安卓java代码
8.1.1、MainActivity函数代码如下:
package com.Rng.freescale;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
importandroid.graphics.drawable.BitmapDrawable;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
public class MainActivity extendsActivity {
ImageView imgView;
Button btnNDK, btnRestore;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.setTitle("使用NDK转换灰度图");
btnRestore = (Button) this.findViewById(R.id.btnRestore);
btnRestore.setOnClickListener(newClickEvent());
btnNDK = (Button) this.findViewById(R.id.btnNDK);
btnNDK.setOnClickListener(newClickEvent());
imgView = (ImageView) this.findViewById(R.id.ImageView01);
@SuppressWarnings("deprecation")
Bitmap img =((BitmapDrawable) getResources().getDrawable(
R.drawable.we)).getBitmap();
imgView.setImageBitmap(img);
}
class ClickEvent implementsView.OnClickListener {
public void onClick(Viewv) {
if (v == btnNDK) {
long current = System.currentTimeMillis();
@SuppressWarnings("deprecation")
Bitmapimg1 = ((BitmapDrawable) getResources().getDrawable(
R.drawable.we)).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);
MainActivity.this.setTitle("w:"+ String.valueOf(img1.getWidth())
+ ",h:" +String.valueOf(img1.getHeight()) + "NDK耗时"
+ String.valueOf(performance)+ " 毫秒");
} else if (v ==btnRestore) {
@SuppressWarnings("deprecation")
Bitmapimg2 = ((BitmapDrawable) getResources().getDrawable(
R.drawable.we)).getBitmap();
imgView.setImageBitmap(img2);
MainActivity.this.setTitle("使用OpenCV进行图像处理");
}
}
}
}
8.1.2、在文件夹src下的com.testopencv.haveimgfun包中新建一个类用于包装使用了opencv c++代码的动态库的导出函数,类名为LibImgFun。Eclipse会为你创建一个新的文件LibImgFun.java,我们将里面的内容改为:
packagecom.Rng.freescale;
publicclass LibImgFun {
static {
System.loadLibrary("ImgFun");
}
publicstatic native int[] ImgFun(int[] buf, int w, int h);
}
从上面的代码可以得知,我们的动态库名字应该为“libImgFun.so”,注意"public static native int[] ImgFun(int[] buf, int w, inth)"中的native关键字,表明这个函数来自native code。static表示这是一个静态函数,这样就可以直接用类名去调用。
8.1.3、然后修改界面控制文件res->layout->activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.Rng.freescale.MainActivity" >
<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="还原" />
<ImageView android:id="@+id/ImageView01"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
文件图如下:
8.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_Rng.freescale_LibImgFun_ImgFun (
JNIEnv* env, jobject obj, jintArray buf, int w, int h);
JNIEXPORT jintArray JNICALL Java_com_Rng.freescale_LibImgFun_ImgFun (
JNIEnv* env, jobject obj, jintArray buf, int w, int h) {
jint *cbuf;
cbuf = env->GetIntArrayElements(buf, false);
if (cbuf == 0) {
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 0;
}
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要包含的头文件。
说明:
这个函数名,必须与java代码中的包名以及类名,函数名完全一致,
分别表示了包,类,函数名,中间用_分开,这个是非常重要的,否则会提示找不到函数的异常错误。
8.3 配置文件
然后再在jni下新建两个文件"Android.mk"文件和"Application.mk"文件,这两个文件事实上就是简单的Makefile文件。使用NDK进行编译的时候,需要使用Android.mk和Application.mk两个文件。
8.3.1如果是只有一个.cpp文件可以采用下面的Android.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 F:\Eclipse\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)
8.3.2如果是有多个.cpp文件则要采用下面的Android.mk
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OpenCV_INSTALL_MODULES:=on
OPENCV_CAMERA_MODULES:=off
OPENCV_LIB_TYPE:=STATIC
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
#try to load OpenCV.mk from default install location
include F:\Eclipse\OpenCV-android-sdk\sdk\native\jni\OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := ImgFun
LOCAL_SRC_FILES := ImgFun.cpp \
cut.cpp \
stdafx.cpp \
lsd.cpp
include $(BUILD_SHARED_LIBRARY)
8.3.3 Application.mk:
APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions
APP_ABI:=armeabi armeabi-v7a