java Bufferdimage與opencv Mat在記憶體中的轉化
阿新 • • 發佈:2019-03-30
以前寫Java人臉識別爬蟲的時候遇到的問題,最早的時候是用tempfile的形式去解決每一個爬蟲執行緒爬取圖片到本地,儲存為tempfile,然後opencv再讀取出來做處理和識別,但是這樣涉及磁碟io,爬蟲效能異常緩慢,所以後面思考了一段時間琢磨出來再記憶體裡面對影象進行轉化,本質上,影象資料對Java來說都是bytes[]串,所以我的轉化過程的思路,就是把byte串取出來,重新組裝。
public static BufferedImage toBufferedImage(Mat matrix) { int type = BufferedImage.TYPE_BYTE_GRAY; if (matrix.channels() > 1) { type = BufferedImage.TYPE_3BYTE_BGR; } int bufferSize = matrix.channels() * matrix.cols() * matrix.rows(); byte[] buffer = new byte[bufferSize]; matrix.get(0, 0, buffer); // get all pixel from martix BufferedImage image = new BufferedImage(matrix.cols(), matrix.rows(), type); final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); System.arraycopy(buffer, 0, targetPixels, 0, buffer.length); return image; }
BufferImage轉為opencv Mat
public static Mat bufferToMartix(BufferedImage image) { Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); if (mat != null) { try { mat.put(0, 0, data); } catch (Exception e) { return null; } } return mat; }
byte陣列轉opencv Mat
public static Mat bufferToMartix(byte[] image) throws IOException {
BufferedImage bImage = ImageIO.read(new ByteArrayInputStream(image));
byte[] bytes = ((DataBufferByte) bImage.getRaster().getDataBuffer()).getData();
Mat data = new Mat(bImage.getHeight(), bImage.getWidth(), CvType.CV_8UC3);
data.put(0, 0, bytes);
return data;
}
有意思的是,當我讓一個BufferedImage巢狀為
//這裡假設b_image裡面包含有影象資料
BufferedImage b_image=b_image=new BufferedImage();
Mat matrix=toBufferedImage(bufferToMartix(b_image))
的時候,JVM概率死掉報出Core Error,於是我分離了這兩個函式避免巢狀使用,沒有去深究這個問題,猜測這可能與JVM的GC(垃圾回收)有關係,而且就算不出現JVM致命錯誤,這樣出來的影象也是有問題的,會缺失很多資料,然後變成一堆噪聲和一片白,直觀感覺就是toBufferedImage呼叫結束後圖像資料記憶體就被釋放掉了,當bufferToMartix從後面執行的時候取了同樣大小的記憶體區塊當做影象,隨機產生了JVM致命記憶體衝突,或者不衝突但是資料混亂的問題,因為不是專業Java這個