2014-11-23 123 views
5

我正在嘗試使用OpenCV Java API創建一個輔助函數來處理輸入圖像並返回輸出字節數組。輸入圖像是保存在電腦中的jpg文件。輸入和輸出圖像使用Swing在Java UI中顯示。將OpenCV Mat對象轉換爲BufferedImage

System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 
// Load image from file 
Mat rgba = Highgui.imread(filePath); 

Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0); 

// Convert back to byte[] and return 
byte[] return_buff = new byte[(int) (rgba.total() * rgba.channels())]; 
rgba.get(0, 0, return_buff); 
return return_buff; 

return_buff被返回並轉換爲BufferedImage時,我返回NULL。當我註釋掉Imgproc.cvtColor函數時,return_buff已正確轉換爲我可以顯示的BufferedImage。看起來像Imgproc.cvtColor正在返回一個我無法在Java中顯示的Mat對象。

這裏是我的代碼從字節[]轉換設置爲BufferedImage:

InputStream in = new ByteArrayInputStream(inputByteArray); 
BufferedImage outputImage = ImageIO.read(in); 

在上面的代碼中,outputImage是NULL

沒有任何人有任何建議或想法?

回答

10

ImageIO.read(...)(和一般的javax.imageio包)用於從文件格式讀取/寫入圖像。你有什麼是包含「原始」像素的數組。 ImageIO不可能從這個字節數組中確定文件格式。因此,它將返回null

相反,您應該直接從字節創建BufferedImage。我不太瞭解OpenCV,但我假設Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0)的結果將是灰度圖像(8位/採樣,1採樣/像素)。這與BufferedImage.TYPE_BYTE_GRAY的格式相同。如果這個假設是正確的,你應該能夠做到:

// Read image as before 
Mat rgba = Highgui.imread(filePath); 
Imgproc.cvtColor(rgba, rgba, Imgproc.COLOR_RGB2GRAY, 0); 

// Create an empty image in matching format 
BufferedImage gray = new BufferedImage(rgba.width(), rgba.height(), BufferedImage.TYPE_BYTE_GRAY); 

// Get the BufferedImage's backing array and copy the pixels directly into it 
byte[] data = ((DataBufferByte) gray.getRaster().getDataBuffer()).getData(); 
rgba.get(0, 0, data); 

這樣做,這樣,可以節省你一個大的字節數組分配和一個字節數組拷貝作爲獎金。 :-)

2

我用這種代碼將Mat對象轉換爲緩衝圖像。

static BufferedImage Mat2BufferedImage(Mat matrix)throws Exception {   
    MatOfByte mob=new MatOfByte(); 
    Imgcodecs.imencode(".jpg", matrix, mob); 
    byte ba[]=mob.toArray(); 

    BufferedImage bi=ImageIO.read(new ByteArrayInputStream(ba)); 
    return bi; 
}