寫這篇隨筆的原因是因為我用了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:\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重寫專案,但願不會再出現這個問題。