1.Windows系统运行java-cv代码
安装OpenCV
在Windows安装OpenCV比较简单,进入官网,进入releases,选择Windows版本,下载执行文件,然后一步一步执行可视化安装即可。
OpenCV官网:https://opencv.org 安装完成后,安装目录如下:
进入build目录:
进入java目录:
可以看到opencv-460.jar包,这个后续会用到。
进入x64目录:
这里的opencv_java460.dll是后续Native类会调用的动态链接库。
运行java-cv进行人脸检测
引入依赖
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.8</version>
</dependency>
添加opencv-460到类路径
打开IDEA的工程结构界面,将opencv-460.jar包添加到依赖库中。
配置opencv_java460.dll
后续代码需要加载dll文件,所以需要将opencv_java460.dll放到path路径中,Windows系统,直接放到C:\Windows\System32目录即可。
代码案例
下面的代码进行人脸检测:
// 加载本地库
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 新建人脸识别类对象
CascadeClassifier faceDetector = new CascadeClassifier("D:\\haarcascade_frontalface_alt.xml");
// 原始照片
Mat image = Imgcodecs.imread("D:\\test.png");
MatOfRect faceDetections = new MatOfRect();
// 进行人脸检测
faceDetector.detectMultiScale(image, faceDetections);
上面代码主要分为四个步骤:
- 从系统中加载native库
- 创建人脸识别类对象
- 读取图片
- 进行人脸检测
OpenCV 库中的人脸检测功能,需要用到haarcascade_frontalface_alt.xml 特征分类器文件,该文件包含了一系列针对人脸的分类器,可以用于识别图像或视频中的人脸区域。
代码调用链分析
下面来分析一下下面这段代码(加载本地库)的调用链路:
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
通过libname加载本地库:
public static void loadLibrary(String libname) {
Runtime.getRuntime().loadLibrary0(Reflection.getCallerClass(), libname);
}
查看libname取值:
public static final String NATIVE_LIBRARY_NAME = getNativeLibraryName();
private static String getNativeLibraryName() { return "opencv_java460"; }
从上面可以看出代码是通过opencv_java460这个名称来加载本地库的。
接下来看看是从哪加载的本地库:
public void loadLibrary(String libname) {
loadLibrary0(Reflection.getCallerClass(), libname);
}
synchronized void loadLibrary0(Class<?> fromClass, String libname) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkLink(libname);
}
if (libname.indexOf((int)File.separatorChar) != -1) {
throw new UnsatisfiedLinkError("Directory separator should not appear in library name: " + libname);
}
ClassLoader.loadLibrary(fromClass, libname, false);
}
static void loadLibrary(Class<?> fromClass, String name, boolean isAbsolute) {
ClassLoader loader =(fromClass == null) ? null : fromClass.getClassLoader();
if (sys_paths == null) {
usr_paths = initializePath("java.library.path");
sys_paths = initializePath("sun.boot.library.path");
}
......
}
上面代码表明是从"java.library.path"路径加载的本地库,至于"java.library.path"路径是哪个目录,可以通过下面代码确认:
System.getProperty("java.library.path")
运行改代码输出结果为opencv_java460.dll所在的路径。
2.Linux系统安装OpenCV
安装jdk配置环境变量
略
安装ant
JavaCV 在构建过程中需要Ant 来构建和编译 C++ 代码,生成对应的 Java JNI 接口和共享库文件,在安装 JavaCV 之前,需要先安装 Ant 工具。下面通过yum来安装ant
sudo yum install ant
配置环境变量:
export ANT_HOME=/usr/share/ant
export PATH=$PATH:$ANT_HOME/bin
安装完成后查看ant版本:
ant -version
如果上面代码报错:Caused by: java.lang.ClassNotFoundException: org.apache.tools.ant.launch.Launcher
表示Ant 的 launcher JAR 文件没有在 classpath 中找到,需要将 Ant launcher JAR 文件添加到 classpath中:
export CLASSPATH="$ANT_HOME/lib/ant-launcher.jar:$CLASSPATH"
安装OpenCV
首先下载opencv-4.5.5.tar.gz、opencv_contrib-4.5.5.tar.gz两个安装包,
opencv-4.5.5.tar.gz下载地址:https://github.com/opencv/opencv/tags opencv_contrib-4.5.5.tar.gz下载地址:https://github.com/opencv/opencv_contrib/tags 解压安装包:
tar -zxvf opencv-4.5.5.tar.gz
tar -zxvf opencv_contrib-4.5.5.tar.gz
进入opencv-4.5.5目录,新建build目录:
cd ./opencv-4.5.5
mkdir build
进入build目录:
cd build
执行构建:
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_GENERATE_PKGCONFIG=ON -D OPENCV_EXTRA_MODULES_PATH=/root/software/opencv_contrib-4.5.5/modules -D ENABLE_CXX11=ON -D WITH_1394=OFF -D BUILD_opencv_xfeatures2d=OFF -D BUILD_SHARED_LIBS=OFF -D BUILD_TESTS=OFF ..
上面构建过程参考:《Linux环境下编译并使用java_opencv》
然后进行编译:
make -j4
make install
编译完成后,查看/usr/local/share/java/opencv4目录:
看是否生成so与jar文件,没有的话需要分析原因重新编译。
运行java-cv进行人脸检测
可能的报错
完成OpenCV安装后,在Linux环境运行java-cv代码进行人脸检测,如果报如下错误:
根据上面的代码调用链分析,系统在loadLibrary的时候没有从java.library.path中找到相关的库文件(报错信息里面是opencv_java460.so文件)。
为什么是读取opencv_java460库文件
Linux环境安装的OpenCV版本是4.5.5,可是代码缺报错找不到opencv_java460对应的本地库文件。
先看maven依赖:
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.5.8</version>
</dependency>
通过Dependency Analyzer插件查看引入的opencv版本:
从上面的依赖树可以看出,javacv1.5.8对应引入的opencv是4.6.0版本(Windows系统安装的也是该版本),
通过下面的代码可以看出,系统是通过opencv_java460这个name来加载相关本地库的:
public static final String NATIVE_LIBRARY_NAME = getNativeLibraryName();
private static String getNativeLibraryName() { return "opencv_java460"; }
下面将javacv的版本改成1.5.7,再通过Dependency Analyzer插件查看引入的opencv版本:
可以看出,javacv1.5.7对应的opencv版本正是4.5.5,由于Linux环境安装的OpenCV是4.5.5,所以将代码重新打包到Linux环境运行。
配置环境变量
将/usr/local/share/java/opencv4目录下的libopencv_java455.so文件路径添加到LD_LIBRARY_PATH路径中:
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/leptonica/lib:/usr/local/tesseract/lib:/usr/local/share/java/opencv4
export LD_LIBRARY_PATH
重新运行java-cv代码。