博文目录
OpenCV 官网
OpenCV 是使用C/C++开发的, 然后开放了其他多种语言的调用入口, java利用JNI的方式调用OpenCV函数
OpenCV GitHub Releases
到OpenCV的GitHub的Releases页面找到当前最新版本, 下载其中的 opencv-4.5.5-vc14_vc15.exe 安装包
安装好后文件夹内容大概如下
我们需要的是 opencv > build > java 下的内容
其中, opencv-454.jar 是我们需要引入的依赖 jar, 其内部方法全是本地(native)调用 x64 下的 opencv_java454.dll 中的实现, 这两个文件都需要引入到我们的工程中
Java加载dll或so库文件的路径 java.library.path
Java的System.load 和 System.loadLibrary都可以用来加载库文件
例如你可以这样载入一个windows平台下JNI库文件:
System.load("C://Documents and Settings//TestJNI.dll"); // 绝对路径
System.loadLibrary ("TestJNI"); // 参数为库文件名
这里TestJNI必须在 java.library.path这一jvm变量所指向的路径中,可以查看 System.getProperty("java.library.path");
默认情况下,Windows平台下包含下面的路径:
在linux下添加一个java.library.path的方法如下:在/etc/profile 后面加上一行 export LB_LIBRARY_PATH=路径
也可以在执行程序的时候可以显式指定,使用jvm参数 -Djava.library.path=路径,这种会清除掉预设置的java.library.path的值 。实例如下:
java -jar -Djava.library.path=/home/fly/Desktop/sound_dream sound.war
使用Java开发OpenCV3程序-1.开发环境安装与配置
使用Java开发OpenCV3程序-2.读取并显示一幅图片
在工程根目录下新建 lib 目录, 将依赖的 jar 和 dll 都复制过来, 不和本地文件目录产生强关联
在 pom.xml 里添加 jar 的本地引用
<dependency>
<groupId>opencvgroupId>
<artifactId>opencvartifactId>
<version>454version>
<scope>systemscope>
<systemPath>${project.basedir}/lib/opencv-454.jarsystemPath>
dependency>
需确保程序运行时, 系统已载入 dll, System.loadLibrary 需要提前配置环境变量或添加JVM参数, 且JVM参数需要用到绝对路径? 会本地文件目录产生强关联, 所以我们推荐使用 System.load 的方式, 这样可以通过代码获取到工程路径
System.load(System.getProperty("user.dir") + "\\lib\\opencv_java454.dll");
package com.mrathena.opencv.starter;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import java.lang.reflect.Field;
@Slf4j
public class Starter {
/*
使用Java开发OpenCV3程序-1.开发环境安装与配置 https://www.cnblogs.com/superbool/p/5323211.html
用Java开发OpenCV3程序-2.读取并显示一幅图片 https://www.cnblogs.com/superbool/p/5331196.html
使用Java开发OpenCV3程序-3.OpenCV的组件结构以及java版本的数据结构 https://www.cnblogs.com/superbool/p/5426890.html
*/
public static void main(String[] args) {
try {
// 方式1
System.load(System.getProperty("user.dir") + "\\lib\\opencv_java454.dll");
// 方式2
// 需要 jvm 参数 -Djava.library.path=D:\\resource\\develop\\opencv\\build\\java\\x64
// 也可以将该 dll 复制到工程目录下, 通过代码修改添加依赖目录
// Starter.addLibraryDir(System.getProperty("user.dir") + "\\lib");
// System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 测试代码
Mat mat = Mat.eye(3, 3, CvType.CV_8UC1);
log.info("{}", mat.dump());
} catch (Throwable cause) {
cause.printStackTrace();
}
}
public static void addLibraryDir(String path) {
try {
Field field = ClassLoader.class.getDeclaredField("usr_paths");
field.setAccessible(true);
String[] paths = (String[]) field.get(null);
String[] tmp = new String[paths.length + 1];
System.arraycopy(paths, 0, tmp, 0, paths.length);
tmp[paths.length] = path;
field.set(null, tmp);
} catch (Throwable cause) {
cause.printStackTrace();
}
}
}
package com.mrathena.opencv.starter;
import org.opencv.core.Mat;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
/**
* 参考自
* 用Java开发OpenCV3程序-2.读取并显示一幅图片
* https://www.cnblogs.com/superbool/p/5331196.html
*/
public class MatKit {
public static void showImage(Mat mat) {
showImage(mat, null);
}
public static void showImage(Mat mat, String windowName) {
try {
// 本来是组件的原始皮肤, 这样写会加载适合本系统的好看的皮肤
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable cause) {
cause.printStackTrace();
}
Image image = toBufferedImage(mat);
JLabel label = new JLabel(new ImageIcon(image));
JScrollPane scrollPane = new JScrollPane(label);
// 不设置大小而设置必要时显示滚动条, 则窗口达到屏幕最大时才展示滚动条
// scrollPane.setPreferredSize(new Dimension(width, height));
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
JFrame frame = new JFrame(windowName);
frame.add(scrollPane, BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
// 用户点击窗口关闭
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private static Image toBufferedImage(Mat mat) {
int type = BufferedImage.TYPE_BYTE_GRAY;
if (mat.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR;
}
int bufferSize = mat.channels() * mat.cols() * mat.rows();
byte[] buffer = new byte[bufferSize];
// 获取所有的像素点
mat.get(0, 0, buffer);
BufferedImage image = new BufferedImage(mat.cols(), mat.rows(), type);
final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
System.arraycopy(buffer, 0, targetPixels, 0, buffer.length);
return image;
}
}
package com.mrathena.opencv.starter;
import com.mrathena.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
@Slf4j
public class 模板匹配 {
public static void main(String[] args) {
System.load(System.getProperty("user.dir") + "\\lib\\opencv_java454.dll");
String big = System.getProperty("user.dir") + "\\image\\big.bmp";
String small = System.getProperty("user.dir") + "\\image\\small.png";
System.out.println(find(big, small));
findAndShow(big, small);
}
public static Point find(String big, String small) {
try {
Mat bigMat = Imgcodecs.imread(big);
Mat templateMat = Imgcodecs.imread(small);
int method = Imgproc.TM_CCORR_NORMED;
int width = bigMat.cols() - templateMat.cols() + 1;
int height = bigMat.rows() - templateMat.rows() + 1;
Mat result = new Mat(width, height, CvType.CV_32FC1);
Imgproc.matchTemplate(bigMat, templateMat, result, method);
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
return (method == Imgproc.TM_SQDIFF_NORMED || method == Imgproc.TM_SQDIFF) ? mmr.minLoc : mmr.maxLoc;
} catch (Throwable cause) {
throw new ServiceException(cause);
}
}
public static void findAndShow(String big, String small) {
try {
Mat bigMat = Imgcodecs.imread(big);
Mat templateMat = Imgcodecs.imread(small);
int method = Imgproc.TM_CCORR_NORMED;
int width = bigMat.cols() - templateMat.cols() + 1;
int height = bigMat.rows() - templateMat.rows() + 1;
Mat result = new Mat(width, height, CvType.CV_32FC1);
Imgproc.matchTemplate(bigMat, templateMat, result, method);
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
Point point = (method == Imgproc.TM_SQDIFF_NORMED || method == Imgproc.TM_SQDIFF) ? mmr.minLoc : mmr.maxLoc;
// 在大图里标记找到的小图(画矩形)
Imgproc.rectangle(bigMat, new Rect((int) point.x, (int) point.y, templateMat.cols(), templateMat.rows()), new Scalar(0, 255, 0));
MatKit.showImage(bigMat);
} catch (Throwable cause) {
throw new ServiceException(cause);
}
}
}