Java服务器部署基于OpenCV的C++图像处理项目(二)编译篇
Java服务器部署基于OpenCV的C++图像处理项目(二)编译篇
部署好环境之后,本篇记录编译的详细步骤。部署环境篇
1.创建文件
在native.cpp中写入以下代码。
#include <jni.h>
#include <string>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
extern "C" {
using namespace cv;
using namespace std;
JNIEXPORT jintArray JNICALL Java_opencv_opencvImp_gray(
JNIEnv *env,
jclass jcls,
jintArray buf,
jint w,
jint h) {
jint *cbuf = env->GetIntArrayElements(buf, JNI_FALSE );
if (cbuf == NULL) { return 0; }
Mat imgData(h, w, CV_8UC4, (unsigned char *) cbuf);
uchar* ptr = imgData.ptr(0);
for(int i = 0; i < w*h; i ++){
//计算公式:Y(亮度) = 0.299*R + 0.587*G + 0.114*B
// 对于一个int四字节,其彩色值存储方式为:BGRA
int grayScale = (int)(ptr[4*i+2]*0.299 + ptr[4*i+1]*0.587 + ptr[4*i+0]*0.114);
ptr[4*i+1] = grayScale; ptr[4*i+2] = grayScale;
ptr[4*i+0] = grayScale;
}
int size = w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result, 0, size, cbuf);
env->ReleaseIntArrayElements(buf, cbuf, 0);
printf("Hello from opencv++!\n");
return result;
}
JNIEXPORT void JNICALL Java_opencv_opencvImp_stringFromJNI(
JNIEnv* env,
jclass jcls) {
printf("Hello from C++!\n");
}
}
继续创建文件,
vi CMakeLists.txt
写入以下代码:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
#cmake version
cmake_minimum_required(VERSION 2.8)
#设置OpenCv的路径变量,这里的/app/opencv即是opencv的安装目录
set(pathToOpenCv /app/opencv)
set(PROJECT_SOURCE_DIR /root/cmake_opencv_imp)
#支持-std=gnu++11
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
#配置加载native依赖,这里加入自己的jdk路径。
include_directories(${pathToOpenCv}/include /usr/local/java/jdk1.8.0_191/include /usr/local/java/jdk1.8.0_191/include/linux)
#表示创建一个导入库,静态方式
add_library(lib_opencv STATIC IMPORTED )
#引入libopencv_java3.so文件
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${pathToOpenCv}/share/OpenCV/java/libopencv_java341.so )
# 自己的源文件
add_library(
# Sets the name of the library.
native
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
./native.cpp
)
#链接库
target_link_libraries(
# Specifies the target library.
native
# Links the target library to the lib_opencv library
lib_opencv
)
至此准备工作完成
2.编译
命令如下
mkdir build
cd build
cmake -D CMAKE_INSTALL_PREFIX=/root/cmake_opencv_imp/build ..
make
至此so库编译成功,将libnative.so拷贝到库搜索路径,例如:
cp libnative.so /usr/lib64
3.调用so库
在工程中的opencvImp中写入代码:
package opencv;
public class opencvImp {
static {
// 打印库搜索路径,一般有很多个
System.out.println(System.getProperty("java.library.path"));
// 加载so库
System.loadLibrary("native");
}
public static void check() {
stringFromJNI();
int w = 99, h = 99;
int[] pix = new int[w * h];
int[] resultPixes=gray(pix,w,h);
}
// 声明方法,和native.cpp中方法对应。
public static native int[] gray(int[] buf, int w, int h);
public static native void stringFromJNI();
}
启动程序时System.loadLibrary("native");
会在默认路径中搜索 libnative. so,这里load方法中只需要写成native,不用加lib以及so后缀。
在需要的类中直接调用即可:
import opencv.opencvImp;
public static void main(){
opencvImp.check();
System.out.println("成功调用!");
}
此时已经完成了opencv的调用,直接运行main
由于测试方法没有实际体现,此处打印成功即表示之前的opencv调用没有问题,打印顺序暂时不知道是什么原因,如果有问题会报错。