zoukankan      html  css  js  c++  java
  • JavaCV与OpenCV的区别和使用中遇到的问题

      写这篇随笔的原因是因为我用了JavaCV一段时间后项目情况糟透了,可能大家很熟悉OpenCV,也有一部分人熟悉JavaCV,但是我相信真正把JavaCV用到生产上的不是太多。

    我参与图片处理项目快一个月了,最初抱着很大兴趣参与这个项目,渐渐的发现这个领域并不太好走。

    • 官网地址

    JavaCV:http://bytedeco.org/,https://github.com/bytedeco/javacv

    OpenCV:https://docs.opencv.org

      JavaCV据说比OpenCV多封装了很多库,但是目前我都没用到,当时应用JavaCV的理由是不用单独安装OpenCV,不用根据环境进行库的切换,

    引入pom文件后则可以直接干活。

    <dependency>
                <groupId>org.bytedeco</groupId>
                <artifactId>javacv-platform</artifactId>
                <version>1.5.4</version>
            </dependency>
    • JavaCV的不稳定问题

    多次仿射结果不一致,我想用JavaCV做仿射变换,缩小图片,发现多次结果不一致,但是用OpenCV就没有这个问题

    @Test
        public void warpAffine() {
            Mat src=imread("D:\img\0_7p-1.jpg");
            Mat dst = new Mat();
            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=new Date();
            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的结果

    @Test
        public void test(){
    
            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 = new MatOfPoint2f(p1,p2,p3);
            MatOfPoint2f ma2 = new MatOfPoint2f(p4,p5,p6);
    Date date=new Date();
            // 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:imghs_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:imghs_err_pid21668.mdmp
    上次写入时间:    2020/9/16 10:04:42
    进程名称:    java.exe : C:Program FilesJavajdk-11.0.8injava.exe
    进程架构:    x64
    异常代码:    0xC0000005
    异常信息:    该线程尝试读写某个虚拟地址,而它对该地址不具有相应的访问权限。
    堆信息:    存在

    查询一番资料并没有找到解决办法,我并不清楚直接用OpenCV JavaAPI是否有同样的问题,如果知道如何解决欢迎留言,感激不尽。

    虽然找到了一个缓解问题的方法,是设置JVM参数的-Xmx8g -Xms8g -Xmn4g,20个线程测试一般不出问题,50个并发有一半的概率死掉。

    现在我决定用OpenCV重写项目,但愿不会再出现这个问题。

  • 相关阅读:
    dijkstra (模板)
    LUOGU P2476 [SCOI2008]着色方案
    LUOGU P2344 奶牛抗议 (树状数组优化dp)
    LaTeX 公式大全
    LUOGU P1505 [国家集训队]旅游 (树链剖分+线段树)
    LUOGU P2416 泡芙 (缩点+树剖)
    LUGOU P1092 虫食算
    BZOJ 3090: Coci2009 [podjela] (树形背包)
    bzoj 4823 [Cqoi2017]老C的方块——网络流
    bzoj 3158 千钧一发——网络流
  • 原文地址:https://www.cnblogs.com/stjwy/p/13678635.html
Copyright © 2011-2022 走看看