2014-11-23 126 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; 
}