JavaCV版本:JavaCV 1.5.4
Idea版本:2020.2
OpenCV版本:OpenCV 4.4.0
在IDEA上添加jar包
File->Project Structure
点Libraries再点+号选java
添加需要的jar包
简单写一段代码运行,报错
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.ArrayStoreException: sun.reflect.annotation.TypeNotPresentExceptionProxy
也不知道哪里出问题了,网上说是版本问题,在pom里换一个版本,我刚学IDEA所以也不知道这个pom怎么配置,就用我自己的方法来搞
首先说换JavaCV版本,我试了1.5到1.5.4,只有1.5能正常运行,其他版本都会报这个错误,所以我就用JavaCV 1.5试试
大部分OpenCV函数都是可以用的就是Imgproc.getPerspectiveTransform会报错,可能还有其他会报错的函数,只是我没测试到,由于我需要使用Imgproc.getPerspectiveTransform,所以只能换一个方法了
这个方法就是JavaCV+OpenCV混合配置
由于JavaCV 1.5.4里的OpenCV是OpenCV 4.4.0,所以先去下载OpenCV 4.4.0
添加opencv-440.jar
Main->Edit Configurations
VM options:-Djava.library.path=X:/javacv
把opencv_java440.dll放入上边的X:/javacv文件夹内
或者把VM options:-Djava.library.path=设置成X:/opencv/build/java/x64,效果都一样
这样就设置完成,只是JavaCV里的OpenCV相关的代码就无法使用了,但是有些代码可以复制出来继续用
static {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
public static void main(String[] args) {
// write your code here
String savePath = "Y:\\test\\img.mp4";
File saveFile = new File(savePath);
if(saveFile.exists()){
if(!saveFile.delete()){
return;
}
}
String img = "Y:\\test\\video";
File file = new File(img);
if(!file.exists()){
return;
}
File[] files = file.listFiles();
if(files == null || files.length == 0){
return;
}
List<File> fileList = FileUtils.filesToList(files);
Mat mat = Imgcodecs.imread(fileList.get(0).getAbsolutePath(), Imgcodecs.IMREAD_UNCHANGED);
int width = mat.cols();
int height = mat.rows();
try {
matToVideo(savePath,fileList,width,height);
} catch (IOException e) {
e.printStackTrace();
}
}
private static void matToVideo(String savePath,List<File> fileList,int width,int height) throws IOException {
FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(savePath, width, height);
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
recorder.setFrameRate(25);
recorder.setVideoBitrate(width*height*3/8);
recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
recorder.setFormat("mp4");
recorder.start();
for (File file : fileList) {
Mat mat = Imgcodecs.imread(file.getAbsolutePath(), Imgcodecs.IMREAD_UNCHANGED);
recorder.record(convert(mat));
}
recorder.stop();
recorder.release();
}
public static Frame convert(Mat mat) {
if (mat == null) {
return null;
} else {
Frame frame = new Frame();
frame.imageWidth = mat.cols();
frame.imageHeight = mat.rows();
frame.imageDepth = getFrameDepth(mat.depth());
frame.imageChannels = mat.channels();
frame.imageStride = (int)mat.step1();
ByteBuffer byteBuffer = (new BytePointer() {
{
this.address = mat.dataAddr();
}
}).capacity((long)mat.rows() * mat.step1() * mat.elemSize1()).asByteBuffer();
switch(mat.depth()) {
case 0:
case 1:
frame.image = new Buffer[]{byteBuffer};
break;
case 2:
case 3:
frame.image = new Buffer[]{byteBuffer.asShortBuffer()};
break;
case 4:
frame.image = new Buffer[]{byteBuffer.asIntBuffer()};
break;
case 5:
frame.image = new Buffer[]{byteBuffer.asFloatBuffer()};
break;
case 6:
frame.image = new Buffer[]{byteBuffer.asDoubleBuffer()};
break;
default:
frame.image = null;
}
frame.opaque = mat;
return frame;
}
}
public static int getFrameDepth(int depth) {
switch(depth) {
case -2147483640:
case 1:
return -8;
case -2147483632:
case 3:
return -16;
case -2147483616:
case 4:
return -32;
case 0:
case 8:
return 8;
case 2:
case 16:
return 16;
case 5:
case 32:
return 32;
case 6:
case 64:
return 64;
default:
return -1;
}
}
FileUtils.java
public class FileUtils {
public static List<File> filesToList(File[] files){
List<File> fileLists = new ArrayList<>();
for (File f : files) {
if (!f.isDirectory()) {
fileLists.add(f);
}
}
Collections.sort(fileLists, new Comparator<File>() {
String nameToNumber(String name){
String[] s = name.split("_");
if(s.length < 2){
return null;
}
return s[1];
}
@Override
public int compare(File o1, File o2) {
String n1 = nameToNumber(o1.getName());
String n2 = nameToNumber(o2.getName());
if(n1 == null){
return -1;
}
if(n2 == null){
return 1;
}
String regEx = "[^0-9]";
Pattern p = Pattern.compile(regEx);
Matcher m1 = p.matcher(n1);
Matcher m2 = p.matcher(n2);
String s1 = m1.replaceAll("").trim();
String s2 = m2.replaceAll("").trim();
long i1 = Long.parseLong(s1);
long i2 = Long.parseLong(s2);
return (int) (i1 - i2);
// return o1.getName().compareTo(o2.getName());
}
});
return fileLists;
}
}
上边这段是把图片转成视频的代码,使用OpenCV读图片,使用JavaCV转成视频,感觉不用OpenCV 4.4.0用其他版本的OpenCV也是可以的