写这篇随笔的原因是因为我用了JavaCV一段时间后项目情况糟透了,可能大家很熟悉OpenCV,也有一部分人熟悉JavaCV,但是我相信真正把JavaCV用到生产上的不是太多。
我参与图片处理项目快一个月了,最初抱着很大兴趣参与这个项目,渐渐的发现这个领域并不太好走。
官网地址:
JavaCV据说比OpenCV多封装了很多库,但是目前我都没用到,当时应用JavaCV的理由是不用单独安装OpenCV,不用根据环境进行库的切换,
引入pom文件后则可以直接干活。
org.bytedeco
javacv-platform
1.5.4
JavaCV的不稳定问题
多次仿射结果不一致,我想用JavaCV做仿射变换,缩小图片,发现多次结果不一致,但是用OpenCV就没有这个问题
@Testpublic voidwarpAffine() {
Mat src=imread("D:\\img\\0_7p-1.jpg");Mat dst= newMat();
Point2f point2fSrc= new Point2f(3);
point2fSrc.position(0).y(0).x(0);//TopLeft
point2fSrc.position(1).y(0).x(src.cols()-1);//TopRight
point2fSrc.position(2).y(src.rows()-1).x(0);//Bottom Left
Point2f point2fDst= new Point2f(3);
point2fDst.position(0).y(0).x(0);//TopLeft
point2fDst.position(1).y(0).x(src.cols()/2);//TopRight
point2fDst.position(2).y(src.rows()/2).x(0);//Bottom Left
Date date=newDate();
Mat affineTrans2=opencv_imgproc.getAffineTransform(point2fSrc,point2fDst);
opencv_imgproc.warpAffine(src, dst, affineTrans2, src.size());
System.out.println(new Date().getTime()-date.getTime());
imwrite("D:\\img\\7p-2.jpg", dst);
}
结果应为等比缩小一倍,但是右边的图有变形,而且多次结果会不一致。
再看直接用OpenCV javaAPI的结果
@Testpublic voidtest(){
System.load("C:\\Program Files\\opencv\\opencv\\build\\java\\x64\\opencv_java410.dll");
System.out.println("Welcome to OpenCV " +Core.VERSION);
Mat src= Imgcodecs.imread("D:/img/0_7p-1.jpg");
Mat dst= new Mat((src.rows()/2),src.cols()/2,src.type());
Point p1= new Point( 0,0);
Point p2= new Point( src.cols() - 1, 0);
Point p3= new Point( 0, src.rows() - 1);Point p4 = new Point( 0, 0);Point p5 = new Point( src.cols() /2, 0 );Point p6 = new Point( 0, src.rows() /2);
// Point p4= new Point( src.cols() /2, 0);
// Point p5= new Point( src.cols() /2, src.rows() /2);
// Point p6= new Point( 0, 0);
MatOfPoint2f ma1= newMatOfPoint2f(p1,p2,p3);
MatOfPoint2f ma2= newMatOfPoint2f(p4,p5,p6);
Date date=newDate();//Creating the transformation matrix
Mat tranformMatrix =Imgproc.getAffineTransform(ma1,ma2);//Applying Wrap Affine
Imgproc.warpAffine(src, dst, tranformMatrix, src.size());
System.out.println(new Date().getTime()-date.getTime());//Writing the image
Imgcodecs.imwrite("D:/img/bbb.jpg", dst);
}
bbb.jpg图像处理正确,多次执行代码结果一致。
性能对比:
同样的图片放射缩小,基于JavaCV处理时间为174毫秒,OpenCV javaAPI的处理时间为11毫秒,差别接近17倍;
这里我要说明一下,例子不具备普遍性,其它API我没有一个一个的测试,希望对大家有帮助。
JavaCV的另外一个多线程并发问题:
我尝试用20个线程压测系统报了一个JVM错误:
#
#A fatal error has been detected by the Java Runtime Environment:#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffec4062738, pid=21668, tid=8404
#
# JRE version: Java(TM) SE Runtime Environment 18.9 (11.0.8+10) (build 11.0.8+10-LTS)
# Java VM: Java HotSpot(TM) 64-Bit Server VM 18.9 (11.0.8+10-LTS, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
#Problematic frame:# C [opencv_imgproc430.dll+0x1e2738]#
# Core dump will be written. Default location: E:\img\hs_err_pid21668.mdmp#
# If you would like to submit a bug report,please visit:# https://bugreport.java.com/bugreport/crash.jsp# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
查看mdmp文件:
转储文件: hs_err_pid21668.mdmp : E:\img\hs_err_pid21668.mdmp
上次写入时间:2020/9/16 10:04:42进程名称: java.exe : C:\Program Files\Java\jdk-11.0.8\bin\java.exe
进程架构: x64
异常代码:0xC0000005异常信息: 该线程尝试读写某个虚拟地址,而它对该地址不具有相应的访问权限。
堆信息: 存在
查询一番资料并没有找到解决办法,我并不清楚直接用OpenCV JavaAPI是否有同样的问题,如果知道如何解决欢迎留言,感激不尽。
虽然找到了一个缓解问题的方法,是设置JVM参数的-Xmx8g -Xms8g -Xmn4g,20个线程测试一般不出问题,50个并发有一半的概率死掉。
现在我决定用OpenCV重写项目,但愿不会再出现这个问题。