前言

本博客写于2017/08/11, 博主非专业搞安卓开发, 只是工作的需要倒腾了下Android NDK相关的开发, 博文中有什么不正确、不严格的地方欢迎指正哈    本文后续也许还会有删改, 就这样。

一、工具、开发环境

博主的操作系统是Windows 10 x64位,虽然感觉Windows 7更适合用来搞开发, 但是用着Win 10也是挺好使的(没必要在操作系统上有很大纠结,Win 10和Win 7都可以)。

1.搭建并测试JAVA开发环境

首先要搭建Java开发环境,Java开发环境的搭建教程网上可以找到,这里不予赘述; 测试是否搭建成功的时候,需要打开命令提示符依次输入java、javac、javah命令进行测试,显示如下界面结果就成功了:

图一    java命令测试

 图二    javac命令测试

 图三    javah命令测试

 

2.搭建Android开发环境

很长一段时间内,Eclipse + ADT插件是Android开发的主流,不过现在流行的是Android Studio。 还记得Android Studio刚出来的时候很是不被看好, 不过现在它也是很好用的安卓开发工具了,此文介绍的所需要的工具只有Android Studio。

网上有介绍说设置ndk-build环境变量的, 但是要弄明白一件事, 他们设置这个变量是因为他们的"NDK"这个依赖包是单独下载的, 并没有在Android Studio里面下载, 本文的"NDK"依赖包是在Android Studio里面下载的, 因此并不需要设置ndk-build环境变量。

开始正式搭建环境,我用的是Android Studio 2.2.3版本。 安装完Android Studio之后, 选择"File" -> "Settings" -> "Appearence & Behavior" -> "System Settings" -> "Android SDK", 配置 "SDK Platforms"
和 "SDK Tools" :

(1)"SDK
Platforms":这个是选择安卓SDK版本,根据自己想法跟需要下载,我下载了安卓4.4、5.0、7.1.1

 
(2)"SDK Tools":这个是选择SDK相关开发工具,基础的"NDK"包(必选)是必须有的,刚安装上Android
Studio的时候默认有什么包我忘了,"Android SDK Build-Tools"这个包应该不用自己勾选,默认就有。NDK开发现在提供了CMake的方式来进行编译调试,通过下载"CMake"跟"LLDB"这俩(可选)就可以用CMake来开发了,本文未基于CMake的方式进行编译调试,而是采用的传统的gradle方式(相对而言,我其实更推荐使用CMake的方式)。

 
(3)正如(2)中所说的, 我采用的是gradle的方式进行的开发, 本文不介绍CMake的方式。 所以在采用gradle的基础上,才有了这第(3)步骤。
这一步就是为了更方便的进行gradle方式的开发而写的。 
可以将gradle经常用到的一些命令简化到菜单中,具体设置在"File" -> "Settings" -> "Tools" -> "External Tools"这里:

1) 添加javah,它用于生成头文件

Program:$JDKPath$/bin/javah

Parameters: -d
../jni -jni $FileClass$


Working directory: $SourcepathEntry$\..\java

最后单击"OK"按钮进行保存。

2) 添加ndk-build,它用于构建so包

Program: 你的NDK目录\build\ndk-build.cmd

Parameters: 什么都不用填

Working directory:$ModuleFileDir$\src\main

最后单击"OK"按钮进行保存。

3) 添加ndk-build
clean,它用于清理so包

Program: 你的NDK目录\build\ndk-build.cmd

Parameters: clean

Working directory:$ModuleFileDir$\src\main

最后单击"OK"按钮进行保存。



3.来一个栗子

一个NDK开发项目总体就分为生成so库、调用so库两部分,本博客栗子就是先将基于OpenCV的C++代码编译生成so库,再通过jni接口来实现对安卓摄像头的灰度化处理。

(1)首先新建一个工程

1)选择新建项目:

 2)填入一些基本信息, 不勾选"Include C++ Support", 然后Next:

 3)默认就可以了,继续Next:

 4)继续Next:

 5)最后Finish:

 
(2)项目创建完毕了,开始向项目中导入OpenCV库
1)去OpenCV官网下载OpenCV for Android版本,  我下载的是2.4.9版本,下载下来的是一个压缩包, 名字是"OpenCV-2.4.9-android-sdk", 我们将其解压放到某个位置, 待会会用到。 我将其解压缩到了D:\Usual\Android目录下面。
2)选择导入组件:

3)选择文件夹

 
在我这里, 就找到刚才解压位置OpenCV for Android包那里, 找到java文件夹然后"OK"开始确认。

接下来默认即可, "next"然后"finish"。
4)接下来还需要将OpenCV库添加到依赖:


 选择Project Structure之后, 弹出以下画面, 按图示进行操作来添加依赖:

 5)进行一些必要的小修改

切换到"Project"视图界面,

 将openCVLibrary249目录下的build.gradle向"app"->"src"下的build.gradle看齐, 也就是将前者的这四项参数修改的和后者一样:

 修改之后还需要单击"Sync Now"来更新一下:

 至此,算是正式导入成功OpenCV库。

(3)开始生成so库
首先分析一下项目, 整个项目要实现对安卓摄像头的实时灰度化, 我们在java类里面来实现摄像头画面的获取, 用C/C++代码来实现对一帧图像(一幅图像)的灰度化。
NDK开发将C/C++代码生成so库, 留一个对单幅图片进行灰度化的接口, 然后我们在Java层获取摄像头数据, 通过JNI调用所生成so库的接口, 对每一帧摄像头数据进行灰度化。
那么现在可以生成so库了。
 1)在app->src->main右键新建一个jni文件夹, 操作指示如图:

 
单击"JNI Folder"会出现一个界面来确认操作, 选择界面上的"Finish"结束即可。

2)新建一个类OpencvClass,负责与C/C++代码对接。

 

 3)开始生成C/C++头文件
打开新创建的类文件,添加一行代码:
 
 
 
 
 
 
 
1
    public native static int convertGray(long matAddrRgba, long matAddrgray);
 
 

接下来,右键单击类OpencvClass,来生成C/C++头文件

 生成成功后会在main文件夹下多出来一个jni文件夹,里面有个头文件:

 
接下来新建一个.cpp文件,名字和该头文件一样,如下图所示操作:

 输入.cpp名字, 然后单击"OK"结束。

 4)开始写.c/.cpp源文件

上一步生成了头文件, 此头文件内容是:

<wiz_code_mirror>

 
 
 
 
 
 
 
1
/* DO NOT EDIT THIS FILE - it is machine generated */
2
#include <jni.h>
3
/* Header for class com_hoos_grayprocessing_OpencvClass */
4
5
#ifndef _Included_com_hoos_grayprocessing_OpencvClass
6
#define _Included_com_hoos_grayprocessing_OpencvClass
7
#ifdef __cplusplus
8
extern "C" {
9
#endif
10
/*
11
 * Class:     com_hoos_grayprocessing_OpencvClass
12
 * Method:    convertGray
13
 * Signature: (JJ)I
14
 */
15
JNIEXPORT jint JNICALL Java_com_hoos_grayprocessing_OpencvClass_convertGray
16
  (JNIEnv *, jclass, jlong, jlong);
17
18
#ifdef __cplusplus
19
}
20
#endif
21
#endif
 
 

其中, JNIEXPORT是接口声明, 我们需要在cpp源文件里将它实现, 这里当然需要我们有C/C++基础, 可以写出cpp文件的框架了:

 
 
 
 
 
 
 
1
//
2
// Created by HooS on 2017/8/14.
3
//
4
#include <com_hoos_grayprocessing_OpencvClass.h>
5
6
7
JNIEXPORT jint JNICALL Java_com_hoos_grayprocessing_OpencvClass_convertGray
8
  (JNIEnv *, jclass, jlong, jlong){
9
  
10
  }
 
 

在实现时, 接口的两个jlong类型需要用来传输OpenCV里面的Mat类型数据, 所以要略微修改一下那里:

<wiz_code_mirror>

 
 
 
 
 
 
 
1
//
2
// Created by HooS on 2017/8/14.
3
//
4
#include <com_hoos_grayprocessing_OpencvClass.h>
5
6
7
JNIEXPORT jint JNICALL Java_com_hoos_grayprocessing_OpencvClass_convertGray
8
  (JNIEnv *, jclass, jlong addrRgba, jlong addrGray){
9
  
10
  }
 
 

然后完善代码,完善JNI接口数据转换,实现单幅图像的灰度化功能:

 
 
 
 
 
 
 
1
//
2
// Created by HooS on 2017/7/25.
3
//
4
#include <com_hoos_ndkopencvtest_OpencvNativeClass.h>
5
6
7
JNIEXPORT jint JNICALL Java_com_hoos_ndkopencvtest_OpencvNativeClass_convertGray
8
  (JNIEnv *, jclass, jlong addrRgba, jlong addrGray){
9
       // 实现jlong类型到Mat类型的转换
10
       Mat& mRgb = *(Mat*)addrRgba;
11
       Mat& mGray = *(Mat*)addrGray;
12
       
13
       // 定义 int 和 jint 类型来接收函数返回值
14
       int conv;
15
       jint retVal;
16
       // 此处调用了toGray函数来对图片进行灰度化处理
17
       conv = toGray(mRgb, mGray);
18
19
       retVal = (jint)conv;
20
       return retVal;
21
  }
 
 

看注释可以知道, 我们还需要实现toGray函数来实现单幅图片的灰度化, 这个实现代码很简单, 为啥非得再麻烦些折腾些呢, 因为大项目往往会有好多源文件, 相互调用, 所以之前最好有多源文件编译的机会来锻炼一下, nao, 自己创造机会。

接下来,新建gray.h、gray.cpp文件来实现toGray这个函数。按照刚才新建.c/.cpp文件的操作来新建:

 gray.h  和 gray.cpp里面就是跟纯C/C++编程一样了, 写一个对单个图像进行灰度化的函数:
<wiz_code_mirror>

 
 
 
 
 
 
 
1
// this is gray.h
2
#include <stdio.h>
3
#include <opencv2/opencv.hpp>
4
5
using namespace cv;
6
using namespace std;
7
8
bool toGray(Mat img, Mat& gray);
 
 
 
 
 
 
 
 
 
1
// this is gray.cpp
2
#include "gray.h"
3
4
bool toGray(Mat img, Mat& gray)
5
{
6
    if (img.channels()  == 3)
7
            cvtColor(img, gray, CV_BGR2GRAY);
8
    else if (img.channels() == 4)
9
            cvtColor(img, gray, CV_BGRA2GRAY);
10
    else if (img.channels() == 1)
11
            gray = img;
12
    if(gray.rows == img.rows && gray.cols == img.cols)
13
        return true;
14
    else
15
        return false;
16
}
 
 

然后再修改下com_hoos_ndkopencvtest_OpencvNativeClass.h文件就好了,添加如下代码(在哪里添加应该都懂):

<wiz_code_mirror>

 
 
 
 
 
 
 
1
#include "gray.h"
2
3
using namespace cv;
4
using namespace std;
 
 

至此,C/C++源文件搞定。

5)写 Android.mk 和 Application.mk 文件

因为本文采用的gradle的方式来进行NDK开发的, 所以我们会用到 Android.mk 和 Application.mk文件,开始新建这两个文件:

 

 创建Application.mk文件的方法也是这样,我就不予赘述了。
两个文件内容如下,需要修改的地方都注释了:
 
 
 
 
 
 
 
1
# this is Android.mk
2
3
LOCAL_PATH := $(call my-dir)
4
5
include $(CLEAR_VARS)
6
7
#opencv
8
OPENCVROOT:= D:/Usual/Android/OpenCV-2.4.9-android-sdk  #这句代码等号右边写上自己的OpenCV安卓开发包的位置
9
OPENCV_CAMERA_MODULES:=on
10
OPENCV_INSTALL_MODULES:=on
11
OPENCV_LIB_TYPE:=SHARED
12
13
#思考下,参考我的修改一下就好了
14
include D:/Usual/Android/OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk
15
16
#这里写上自己的开发需要的源文件, 我这里需要两个
17
LOCAL_SRC_FILES := com_hoos_grayprocessing_OpencvClass.cpp gray.cpp
18
19
20
#设置生成的so库的名字  前面的lib和后缀名不用写
21
LOCAL_MODULE := MyLibs
22
23
LOCAL_LDLIBS += -llog
24
25
include $(BUILD_SHARED_LIBRARY)
 
 
<wiz_code_mirror>

 
 
 
 
 
 
 
1
# this is Application.mk
2
3
APP_STL := gnustl_static
4
APP_CPPFLAGS := -frtti -fexceptions
5
6
#这句是设置生成的cpu指令类型,可以根据自己需求来设置生成的平台, 一般这两个就够了
7
APP_ABI := armeabi-v7a x86
8
9
APP_PLATFORM := android-8    #这句是设置最低安卓平台,可以不弄
 
 

6)开始生成so库

 可以看到,多出来了一个libs文件夹,如图:

 至此,so库生成完成。

(4)JNI调用so库
这一部分将大体分析一下, 毕竟实现不同的功能类有不同的写法, 本文主要提供一个思路, 以待能够举一反三写出其他NDK开发实例来。这是这一部分的五个关键文件:


1)activity_main.xml

源内容如下:

 
 
 
 
 
 
 
1
<?xml version="1.0" encoding="utf-8"?>
2
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:tools="http://schemas.android.com/tools"
4
    android:id="@+id/activity_main"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    android:paddingBottom="@dimen/activity_vertical_margin"
8
    android:paddingLeft="@dimen/activity_horizontal_margin"
9
    android:paddingRight="@dimen/activity_horizontal_margin"
10
    android:paddingTop="@dimen/activity_vertical_margin"
11
    tools:context="com.hoos.grayprocessing.MainActivity">
12
13
    <TextView
14
        android:layout_width="wrap_content"
15
        android:layout_height="wrap_content"
16
        android:text="Hello World!" />
17
</RelativeLayout>
 
 

根据实际情况, 我们不需要TextView, 而需要一个JavaCameraView来显示摄像头帧, 控件ID为"java_camera_view", 修改如下:

<wiz_code_mirror>

 
 
 
 
 
 
 
1
<?xml version="1.0" encoding="utf-8"?>
2
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
    xmlns:tools="http://schemas.android.com/tools"
4
    android:id="@+id/activity_main"
5
    android:layout_width="match_parent"
6
    android:layout_height="match_parent"
7
    android:paddingBottom="@dimen/activity_vertical_margin"
8
    android:paddingLeft="@dimen/activity_horizontal_margin"
9
    android:paddingRight="@dimen/activity_horizontal_margin"
10
    android:paddingTop="@dimen/activity_vertical_margin"
11
    tools:context="com.hoos.grayprocessing.MainActivity">
12
13
    <org.opencv.android.JavaCameraView
14
        android:layout_width="fill_parent"
15
        android:layout_height="fill_parent"
16
        android:id="@+id/java_camera_view"
17
        />
18
</RelativeLayout>
 
 

2)AndroidManifest.xml

原内容是:

 
 
 
 
 
 
 
1
<?xml version="1.0" encoding="utf-8"?>
2
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
    package="com.hoos.grayprocessing">
4
    <application
5
        android:allowBackup="true"
6
        android:icon="@mipmap/ic_launcher"
7
        android:label="@string/app_name"
8
        android:supportsRtl="true"
9
        android:theme="@style/AppTheme">
10
        <activity android:name=".MainActivity">
11
            <intent-filter>
12
                <action android:name="android.intent.action.MAIN" />
13
14
                <category android:name="android.intent.category.LAUNCHER" />
15
            </intent-filter>
16
        </activity>
17
    </application>
18
19
</manifest>
 
 

因为应用需要摄像头权限, 所以需要在这个文件添加摄像头权限:

<wiz_code_mirror>

 
 
 
 
 
 
 
1
<?xml version="1.0" encoding="utf-8"?>
2
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
    package="com.hoos.grayprocessing">
4
    
5
    <uses-permission android:name="android.permission.CAMERA"/>
6
    
7
    <application
8
        android:allowBackup="true"
9
        android:icon="@mipmap/ic_launcher"
10
        android:label="@string/app_name"
11
        android:supportsRtl="true"
12
        android:theme="@style/AppTheme">
13
        <activity android:name=".MainActivity">
14
            <intent-filter>
15
                <action android:name="android.intent.action.MAIN" />
16
17
                <category android:name="android.intent.category.LAUNCHER" />
18
            </intent-filter>
19
        </activity>
20
    </application>
21
22
</manifest>
 
 

3)gradle.propertise

需要添加对以前版本的支持,在此文件内容的最后添加一行:

 
 
 
 
 
 
 
1
android.useDepredcatedNdk=true
 
 

4)build.gradle

原内容:

<wiz_code_mirror>

 
 
 
 
 
 
 
1
apply plugin: 'com.android.application'
2
3
android {
4
    compileSdkVersion 26
5
    buildToolsVersion "26.0.1"
6
    defaultConfig {
7
        applicationId "com.hoos.grayprocessing"
8
        minSdkVersion 21
9
        targetSdkVersion 26
10
        versionCode 1
11
        versionName "1.0"
12
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13
    }
14
15
    buildTypes {
16
        release {
17
            minifyEnabled false
18
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19
        }
20
    }
21
}
22
23
dependencies {
24
    compile fileTree(include: ['*.jar'], dir: 'libs')
25
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
26
        exclude group: 'com.android.support', module: 'support-annotations'
27
    })
28
    compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
29
    testCompile 'junit:junit:4.12'
30
    compile project(':openCVLibrary249')
31
}
32
 
 

添加内容, 指明生成的so库的路径:

 
 
 
 
 
 
 
1
apply plugin: 'com.android.application'
2
3
android {
4
    compileSdkVersion 26
5
    buildToolsVersion "26.0.1"
6
    defaultConfig {
7
        applicationId "com.hoos.grayprocessing"
8
        minSdkVersion 21
9
        targetSdkVersion 26
10
        versionCode 1
11
        versionName "1.0"
12
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13
    }
14
15
    sourceSets.main{
16
        jniLibs.srcDirs = ['src/main/libs']
17
        jni.srcDirs = []
18
    }
19
20
    buildTypes {
21
        release {
22
            minifyEnabled false
23
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
24
        }
25
    }
26
}
27
28
dependencies {
29
    compile fileTree(include: ['*.jar'], dir: 'libs')
30
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
31
        exclude group: 'com.android.support', module: 'support-annotations'
32
    })
33
    compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
34
    testCompile 'junit:junit:4.12'
35
    compile project(':openCVLibrary249')
36
}
37
 
 

5)MainActivity.java

部分注释在代码中,

<wiz_code_mirror>

 
 
 
 
 
 
 
1
package com.hoos.grayprocessing;
2
3
import android.support.v7.app.AppCompatActivity;
4
import android.os.Bundle;
5
import android.util.Log;
6
import android.view.View;
7
8
import org.opencv.android.BaseLoaderCallback;
9
import org.opencv.android.CameraBridgeViewBase;
10
import org.opencv.android.JavaCameraView;
11
import org.opencv.android.LoaderCallbackInterface;
12
import org.opencv.android.OpenCVLoader;
13
import org.opencv.core.CvType;
14
import org.opencv.core.Mat;
15
16
public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2{
17
    
18
    private static String TAG = "MainActivity";
19
    // 初始化一个实例,用来获取摄像头帧
20
    JavaCameraView javaCameraView;
21
    Mat mRgba;  // 用来存储原始摄像头数据
22
    Mat mGray;  // 用来存储灰度化后的帧数据
23
24
    // 静态加载之前生成的so库——Mylins
25
    static{
26
        System.loadLibrary("MyLibs");
27
    }
28
29
    // 回调开初始化帧数据
30
    BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
31
        @Override
32
        public void onManagerConnected(int status) {
33
            switch(status){
34
                case BaseLoaderCallback.SUCCESS:
35
                    javaCameraView.enableView();
36
                    break;
37
                default:
38
                    super.onManagerConnected(status);
39
                    break;
40
            }
41
            super.onManagerConnected(status);
42
        }
43
    };
44
45
    @Override
46
    protected void onCreate(Bundle savedInstanceState) {
47
        super.onCreate(savedInstanceState);
48
        setContentView(R.layout.activity_main);
49
50
        // 与java_camera_view控件绑定
51
        javaCameraView = (JavaCameraView)findViewById(R.id.java_camera_view);
52
        javaCameraView.setVisibility(View.VISIBLE);
53
        javaCameraView.setCvCameraViewListener(this);
54
    }
55
56
    @Override
57
    protected void onPause(){
58
        super.onPause();
59
        if(javaCameraView!=null)
60
            javaCameraView.disableView();
61
    }
62
63
    protected void onDestroy(){
64
        super.onDestroy();
65
        if(javaCameraView!=null)
66
            javaCameraView.disableView();
67
    }
68
69
    // 判断是否加载成功OpenCV库
70
    protected void onResume(){
71
        super.onResume();
72
        if(OpenCVLoader.initDebug()){
73
            Log.i(TAG, "Opencv loaded successfully");
74
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
75
        }
76
        else{
77
            Log.i(TAG, "Opencv not loaded");
78
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this, mLoaderCallback);
79
        }
80
    }
81
82
    @Override
83
    public void onCameraViewStarted(int width, int height) {
84
        // 初始化这两个Mat类型
85
        mRgba = new Mat(height, width, CvType.CV_8UC4);
86
        mGray = new Mat(height, width, CvType.CV_8UC1);
87
    }
88
89
    @Override
90
    public void onCameraViewStopped() {
91
        mRgba.release();
92
    }
93
94
    @Override
95
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
96
        // 得到摄像头原始帧数据
97
        mRgba = inputFrame.rgba();
98
        // 调用OpencvClass类的方法来对帧数据进行灰度化
99
        OpencvClass.convertGray(mRgba.getNativeObjAddr(), mGray.getNativeObjAddr());
100
101
        return mGray;
102
    }
103
}
 
 

此外, 出现了如下提示"Gradle files have changed ...", 请单击右边的"Sync Now"来进行更新。

 
(4)在x86的Android 5.0的虚拟机器上运行了下,
木有问题

当然了,想要虚拟安卓机能用电脑或者usb外置摄像头需要修改虚拟机一点参数:
1)鼠标左键单击下图红色标记按钮:

 

 2)鼠标左键单击下图红色标记按钮(前提是你已经创建了一个虚拟机,
建议创建x86的虚拟机):

3) 鼠标左键单击下图红色标记按钮:

 
4)将参数 "Front" 或者 "Back" 的其中任意一个改成Webcam0就可以了, 这样只要电脑内置或者外置摄像头可用虚拟机就可以调用了。

 
 

简单的调用OpenCV库的Android NDK开发 工具Android Studio的更多相关文章

  1. Android中开发工具Android Studio修改created用户(windows环境)

    最近经常有朋友反馈说我的安卓项目中,在一些类中会出现Created by panchengjia on 2016/12/30的字样,是如何自动实现的(默认一般为Administrator),如下图: ...

  2. Android NDK开发之Android.mk文件

    Android NDK开发指南---Android.mk文件 博客分类: Android NDK开发指南   Android.mk文件语法详述 介绍: ------------ 这篇文档是用来描述你的 ...

  3. Android NDK开发及调用标准linux动态库.so文件

    源:Android NDK开发及调用标准linux动态库.so文件 预备知识及环境搭建 1.NDK(native development Kit)原生开发工具包,用来快速开发C.C++动态库,并能自动 ...

  4. !! 2.对十份论文和报告中的关于OpenCV和Android NDK开发的总结

    http://hujiaweibujidao.github.io/blog/2013/11/18/android-ndk-and-opencv-development-3/ Android Ndk a ...

  5. Android NDK开发及OpenCV初步学习笔记

    https://www.jianshu.com/p/c29bb20908da Android NDK开发及OpenCV初步学习笔记 Super_圣代 关注 2017.08.19 00:55* 字数 6 ...

  6. windows下Qt Creator5.1.0编写程序以及调用OpenCV库

    系统说明 最近使用opencv编写程序,程序编的差不多就学习使用QT加个界面,首先声明下本人的系统和使用的软件版本, 系统: windows xp QT IDE:QT Creator5.1.0 Ope ...

  7. Android NDK开发初识

    神秘的Android NDK开发往往众多程序员感到兴奋,但又不知它为何物,由于近期开发应用时,为了是开发的.apk文件不被他人解读(反编译),查阅了很多资料,其中有提到使用NDK开发,怀着好奇的心理, ...

  8. Android NDK 开发(二) -- 从Hlello World学起【转】

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/41805719  上篇文章讲述了Android NDK开发的一些基本概念,以及NDK ...

  9. Android NDK开发Hello Word!

    在之前的博客中已经为大家介绍了,如何在win环境下配置DNK程序,本篇我将带大家实现一个简单的Hello jni程序,让大家真正感受一下NDK开发的魅力.这里我们选择使用C+JAVA开发Android ...

随机推荐

  1. 【开源】【前后端分离】【优雅编码】分享我工作中的一款MVC+EF+IoC+Layui前后端分离的框架——【NO.1】框架概述

    写博客之前总想说点什么,但写的时候又忘了想说点什么,算了,不说了,还是来送福利吧. 今天是来分享我在平时工作中搭建的一套前后端分离的框架. 平时工作大多时候都是在做管理类型的软件开发,无非就是增.删. ...

  2. POI不同版本替换Word模板时的问题

    一.问题描述 通过POI,把Word中的占位符替换为实际的值,以生成复杂结构的业务报告. 在POI 3.9上,功能正常.由于某些原因升级到POI 3.10.1后,项目组反馈说Word模板出错,无法生成 ...

  3. SpringBoot下配置FreeMarker配置远程模版

    需求产生原因 要求在同一个接口中,根据不同的参数,返回不同的视图结果 所有的视图中的数据基本一致 要求页面能静态化,优化SEO 例如:A接口返回客户的信息 客户A在调用接口时,返回其个性化定制的页面A ...

  4. .NET MVC 二级域名路由的实现

    .NET MVC 5以下版本: http://www.cnblogs.com/luanwey/archive/2009/08/12/1544444.html http://blog.maartenba ...

  5. 【持续更新】JavaScript常见面试题整理

    [重点提前说]这篇博客里的问题涉及到了了JS中常见的的基础知识点,也是面试中常见的一些问题,建议初入职场的园友Mark收藏,本文会持续更新~ 1. 引入JS的三种方式 1.在HTML标签中直接使用,直 ...

  6. day2--命令总结

    1.mkdir               创建目录  -p递归(用来创建层级目录,底层目录不存在) 2.touch               创建文件 3.ls                  ...

  7. windows中更换Jdk版本不生效

    本机已经安装了jdk1.7,而比较早期的项目需要依赖jdk1.6,于是同时在本机安装了jdk1.6和jdk1.7. 安装jdk1.6前,执行java -version得到 C:\Users\liuxi ...

  8. 检测应用的内存泄漏情况(shell)

    写代码--调试--修BUG 改来改去可能还存在一些没发现的问题,在工程量大的时候更容易出现,例如内存泄漏这样的问题,严重影响着系统性能. 网上有些检测C程序是否存在内存泄漏的工具还不错的,例如valg ...

  9. 从零一起学Spring Boot之LayIM项目长成记(五)websocket

    前言 距离上一篇已经比较久的时间了,项目也是开了个头.并且,由于网上的关于Spring Boot的websocket讲解也比较多.于是我采用了另外的一个通讯框架 t-io 来实现LayIM中的通讯功能 ...

  10. 1)C语言简介(C自考学习)

    C语言历史由来 世界上第一个高级语言是"ALFOL",而C的前身是ALGOL语言.1970年美国贝尔实验室的肯·汤普逊对BCPL(基本复合程序设计语言)进行了进一步的简化,突出了硬 ...