查看: 2841|回复: 0

Rayeager PX2试用活动+Android+OPNECV+JNI开发模式之开发环境配置

[复制链接]
  • TA的每日心情
    开心
    2018-6-10 20:29
  • 签到天数: 711 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2015-6-5 15:02:04 | 显示全部楼层 |阅读模式
    分享到:
    上一篇写Android+OPNECV+JNI开发模式之边缘检测的程序代码,但没有把相关的软件环境配置交代清楚,这里补上。

    开发环境及软件:
    Windows 7 64
    adt-bundle-windows-x86_64,这里面包含了eclipseV10 SDK SDK manager
    android-ndk-r10d
    OpenCV-2.4.10-android-sdk
    至于为什么要学习 Android下OPENCV 的NDK 开发模式,那时因为以前的很多的算法都是基于OPENCV 的C/C++写的,如果要将这些代码全部转换为JAVA这将给开发人员很大的工作量,何况前人留下了那么多的开源项目代码,放在现成的代码不用真是有点浪费。另外C/C++也有它在底层的执行效率高的特殊优势,方便对原始数据的处理。而且由于Linux系统的权限限制和Android封装架构限制,很多涉及底层设备、接口、驱动控制的应用开发,不得不使用到本文的NDK开发环境(基于Android源码或内核源码修改),开发语言使用C/C++,NDK开发更接近于Linux开发,需要更多关于Linux应用编程知识。基于以上的种种原因,在Android的环境下学习NDK的开发模式是很有必要的。
    有了NDK的这种开发模式,其实你关注的更多的算法的实现,JAVA语音只要会一点点就可以开发,将开发的好的算法生成.SO的库给Android的上层应用开发人员调用就是,本人就是这么做的(无奈JAVA我也只会一点点)。
    需要的软件可以到这来下载:http://pan.baidu.com/s/1i3rDdlj
    按照自己的版本下载adt和ndk,一般人都有了adt,需要重点下载一下ndk解压好,任意目录。我演示的环境是64位 windows平台(adt-bundle-windows-x86_64-20140702和android-ndk32-r10-windows-x86_64)最新版下载也可以官网下载,不过好像需要翻墙。
    软件如下:
    QQ截图20150528143837.jpg

    至于eclipse的安装我前面已经讲解过了,不清楚的可以自己百度。或者https://www.cirmall.com/bbs/thread-41870-1-1.html
         下载下来的android-ndk32-r10我解压到D:盘如下图:

    QQ截图20150528143927.jpg
    设置系统的环境变量:

    QQ截图20150528144400.jpg

    仅此而已!!
    可以开始开发了……………………
    在eclipse中新建一个Android的应用工程:

    QQ截图20150528144852.jpg
    由于我已经建了一个相同名称的应用,所以会提示这个项目已经在你的workspace中了,如果你没有建过自然就不会提示了,接下来就是一路next到生成结束,我就不一一截图了。

    QQ截图20150528145017.jpg
    建好工程后鼠标右键工程名给这个工程新建一个名称为jni的文件夹如图:

    QQ截图20150528150055.jpg
    现在我建好的工程结构如图:

    QQ截图20150528150001.jpg
    1. MainActivity.java中的代码如下:
    2. package com.example.hellojnitest;

    3. import android.app.Activity;
    4. import android.os.Bundle;
    5. import android.graphics.Bitmap;
    6. import android.graphics.Bitmap.Config;
    7. import android.graphics.drawable.BitmapDrawable;
    8. import android.widget.Button;
    9. import android.view.View;
    10. import android.widget.ImageView;

    11. public class MainActivity extends Activity {
    12.         /** Called when the activity is first created. */
    13.         ImageView imgView;
    14.         Button btnNDK, btnRestore;

    15.         @Override
    16.         protected void onCreate(Bundle savedInstanceState) {
    17.                 super.onCreate(savedInstanceState);
    18.                 setContentView(R.layout.activity_main);
    19.                 ////////////////////////////////////////////////////
    20.                 this.setTitle("使用NDK转换成轮廓图");
    21.                 btnRestore = (Button) this.findViewById(R.id.btnRestore);
    22.                 btnRestore.setOnClickListener(new ClickEvent());
    23.                 btnNDK = (Button) this.findViewById(R.id.btnNDK);
    24.                 btnNDK.setOnClickListener(new ClickEvent());
    25.                 imgView = (ImageView) this.findViewById(R.id.ImageView01);
    26.                 Bitmap img = ((BitmapDrawable) getResources().getDrawable(
    27.                                 R.drawable.lena)).getBitmap();
    28.                 imgView.setImageBitmap(img);
    29.                
    30.         }
    31.         ///////////////////////////////////////////////////
    32.         class ClickEvent implements View.OnClickListener {
    33.                 public void onClick(View v) {
    34.                         if (v == btnNDK) {
    35.                                 long current = System.currentTimeMillis();
    36.                                 Bitmap img1 = ((BitmapDrawable) getResources().getDrawable(
    37.                                                 R.drawable.lena)).getBitmap();
    38.                                 int w = img1.getWidth(), h = img1.getHeight();
    39.                                 int[] pix = new int[w * h];
    40.                                 img1.getPixels(pix, 0, w, 0, 0, w, h);
    41.                                 int[] resultInt = LibImgFun.ImgFun(pix, w, h);
    42.                                 Bitmap resultImg = Bitmap.createBitmap(w, h, Config.RGB_565);
    43.                                 resultImg.setPixels(resultInt, 0, w, 0, 0, w, h);
    44.                                 long performance = System.currentTimeMillis() - current;
    45.                                 imgView.setImageBitmap(resultImg);
    46.                                 MainActivity.this.setTitle("w:" + String.valueOf(img1.getWidth())
    47.                                                 + ",h:" + String.valueOf(img1.getHeight()) + "NDK耗时"
    48.                                                 + String.valueOf(performance) + " 毫秒");
    49.                         } else if (v == btnRestore) {
    50.                                 Bitmap img2 = ((BitmapDrawable) getResources().getDrawable(
    51.                                                 R.drawable.lena)).getBitmap();
    52.                                 imgView.setImageBitmap(img2);
    53.                                 MainActivity.this.setTitle("使用OpenCV进行图像处理");
    54.                         }
    55.                 }
    56.         }
    57. }
    复制代码
    读者可能会问我:为什么我的工程目录下没有LigImgeFun.java这个文件呢?别急,这个需要自己新建。
    步奏如下图:
    QQ截图20150528151621.jpg

    QQ截图20150528151713.jpg
    由于我已经建过一样的每次的类库了,所以提示这个类已经在里面了,在此跳过。
    QQ截图20150528151850.jpg

    LigImgeFun.java文件中的代码如下,这个类的的主要作用就是装载native的ImgFun.so库,并且提供提供函数接口:
    package com.example.hellojnitest;
    public classLibImgFun {
        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);   
    }
    在jni文件夹中新建hello-jni.cpp文件,添加代码如下,这些代码就是我们熟悉的C\C++代码,只是在函数的名称上有点特别,这个以后再论:
    1. #include <jni.h>
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #include <string.h>

    5. #include <highgui.h>
    6. #include <opencv2/opencv.hpp>
    7. using namespace cv;
    8. IplImage * change4channelTo3InIplImage(IplImage * src);

    9. extern "C" {
    10. JNIEXPORT
    11. jintArray JNICALL Java_com_example_hellojnitest_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h);
    12. JNIEXPORT
    13. jintArray JNICALL Java_com_example_hellojnitest_LibImgFun_ImgFun(JNIEnv* env, jobject obj, jintArray buf, int w, int h)
    14. {
    15.         jint *cbuf;
    16.         cbuf = env->GetIntArrayElements(buf, NULL);
    17.         if (cbuf == NULL) {
    18.                 return 0;
    19.         }

    20.         Mat myimg(h, w, CV_8UC4, (unsigned char*) cbuf);
    21.         IplImage image=IplImage(myimg);
    22.         IplImage* image3channel = change4channelTo3InIplImage(&image);

    23.         IplImage* pCannyImage=cvCreateImage(cvGetSize(image3channel),IPL_DEPTH_8U,1);

    24.         cvCanny(image3channel,pCannyImage,50,150,3);

    25.         int* outImage=new int[w*h];
    26.         for(int i=0;i<w*h;i++)
    27.         {
    28.                 outImage[i]=(int)pCannyImage->imageData[i];
    29.         }

    30.         int size = w * h;
    31.         jintArray result = env->NewIntArray(size);
    32.         env->SetIntArrayRegion(result, 0, size, outImage);
    33.         env->ReleaseIntArrayElements(buf, cbuf, 0);
    34.         return result;
    35. }
    36. }

    37. IplImage * change4channelTo3InIplImage(IplImage * src) {
    38.         if (src->nChannels != 4) {
    39.                 return NULL;
    40.         }

    41.         IplImage * destImg = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 3);
    42.         for (int row = 0; row < src->height; row++) {
    43.                 for (int col = 0; col < src->width; col++) {
    44.                         CvScalar s = cvGet2D(src, row, col);
    45.                         cvSet2D(destImg, row, col, s);
    46.                 }
    47.         }

    48.         return destImg;
    49. }
    复制代码
    在jni文件夹中新建Android.mk文件,这个如果开发过linux的应该很熟悉,这个是C\C++的编译配置文件,代码如下:
    1. LOCAL_PATH := $(call my-dir)  
    2. include $(CLEAR_VARS)  
    3. OPENCV_LIB_TYPE:=STATIC
    4. OPENCV_INSTALL_MODULES:=on
    5. OPENCV_CAMERA_MODULES:=off
    6. ifeq ("$(wildcard $(OPENCV_MK_PATH))","")  
    7. #try to load OpenCV.mk from default install location  
    8. include E:\Workspace\OpenCV-2.4.10-android-sdk\sdk\native\jni\OpenCV.mk
    9. else  
    10. include $(OPENCV_MK_PATH)  
    11. endif  
    12. LOCAL_MODULE    := ImgFun
    13. LOCAL_SRC_FILES := hello-jni.cpp
    14. include $(BUILD_SHARED_LIBRARY)
    复制代码
    在jni中新建Application.mk文件,这里面的代码主要的主要的作用是生成不同的处理器平台的工程代码,每种处理器都会产生相应的.SO库文件,代码如下:
    1. APP_STL:=gnustl_static  
    2. APP_CPPFLAGS:=-frtti -fexceptions  
    3. APP_ABI:=armeabi armeabi-v7a
    4. APP_PLATFORM := android-19
    复制代码
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-4-20 05:56 , Processed in 0.131301 second(s), 16 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.