在opencv中将BufferedImage转换为Mat

如何在OpenCV中将BufferedImage转换为Mat? 我使用java包装器的OpenCV(而不是JavaCV)。 由于我是OpenCV的新手,我在理解Mat的工作原理时遇到了一些问题。

我想做这样的事情。 (根据Ted W.回复):

BufferedImage image = ImageIO.read(b.getClass().getResource("Lena.png")); int rows = image.getWidth(); int cols = image.getHeight(); int type = CvType.CV_16UC1; Mat newMat = new Mat(rows,cols,type); for(int r=0; r<rows; r++){ for(int c=0; c<cols; c++){ newMat.put(r, c, image.getRGB(r, c)); } } Highgui.imwrite("Lena_copy.png",newMat); 

这不起作用。 “Lena_copy.png”只是一张尺寸正确的黑色照片。

我也试图做同样的事情,因为需要将图像处理与两个库相结合。 我试图做的是将byte[]放入Mat而不是RGB值。 它奏效了! 所以我做的是:

1.将BufferedImage为字节数组:

 byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); 

2.如果将类型设置为CV_8UC3,则可以将其简单地放到Mat中

 image_final.put(0, 0, pixels); 

编辑:您也可以尝试按照此答案执行反向操作

这个对我很好,需要0到1毫秒才能完成。

 public static Mat bufferedImageToMat(BufferedImage bi) { Mat mat = new Mat(bi.getHeight(), bi.getWidth(), CvType.CV_8UC3); byte[] data = ((DataBufferByte) bi.getRaster().getDataBuffer()).getData(); mat.put(0, 0, data); return mat; } 

不想处理大像素arrays? 只需使用它

BufferedImage to Mat

 public static Mat BufferedImage2Mat(BufferedImage image) throws IOException { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ImageIO.write(image, "jpg", byteArrayOutputStream); byteArrayOutputStream.flush(); return Imgcodecs.imdecode(new MatOfByte(byteArrayOutputStream.toByteArray()), Imgcodecs.CV_LOAD_IMAGE_UNCHANGED); } 

Mat to BufferedImage

 public static BufferedImage Mat2BufferedImage(Mat matrix)throws IOException { MatOfByte mob=new MatOfByte(); Imgcodecs.imencode(".jpg", matrix, mob); return ImageIO.read(new ByteArrayInputStream(mob.toArray())); } 

注意 ,虽然它可以忽略不计。 但是,通过这种方式,您可以获得可靠的解决方案,但它使用编码+解码。 所以你失去了一些表现。 通常为10到20毫秒。 JPG编码失去了一些图像质量也很慢(可能需要10到20ms)。 BMP无损且快速(1或2 ms)但需要更少的内存(可忽略不计)。 PNG无损,但比BMP编码的时间多一点。 使用BMP应该适合我认为的大多数情况。

我在这里找到了解决方案。 解决方案类似于Andriys。

 Camera c; c.Connect(); c.StartCapture(); Image f2Img, cf2Img; c.RetrieveBuffer(&f2Img); f2Img.Convert( FlyCapture2::PIXEL_FORMAT_BGR, &cf2Img ); unsigned int rowBytes = (double)cf2Img.GetReceivedDataSize()/(double)cf2Img.GetRows(); cv::Mat opencvImg = cv::Mat( cf2Img.GetRows(), cf2Img.GetCols(), CV_8UC3, cf2Img.GetData(),rowBytes ); 

一种简单的方法是创建一个新的使用

 Mat newMat = Mat(rows, cols, type); 

然后从BufferedImage获取像素值并使用

 newMat.put(row, col, pixel); 

我在我的程序中使用以下代码。

 protected Mat img2Mat(BufferedImage in) { Mat out; byte[] data; int r, g, b; if (in.getType() == BufferedImage.TYPE_INT_RGB) { out = new Mat(in.getHeight(), in.getWidth(), CvType.CV_8UC3); data = new byte[in.getWidth() * in.getHeight() * (int) out.elemSize()]; int[] dataBuff = in.getRGB(0, 0, in.getWidth(), in.getHeight(), null, 0, in.getWidth()); for (int i = 0; i < dataBuff.length; i++) { data[i * 3] = (byte) ((dataBuff[i] >> 0) & 0xFF); data[i * 3 + 1] = (byte) ((dataBuff[i] >> 8) & 0xFF); data[i * 3 + 2] = (byte) ((dataBuff[i] >> 16) & 0xFF); } } else { out = new Mat(in.getHeight(), in.getWidth(), CvType.CV_8UC1); data = new byte[in.getWidth() * in.getHeight() * (int) out.elemSize()]; int[] dataBuff = in.getRGB(0, 0, in.getWidth(), in.getHeight(), null, 0, in.getWidth()); for (int i = 0; i < dataBuff.length; i++) { r = (byte) ((dataBuff[i] >> 0) & 0xFF); g = (byte) ((dataBuff[i] >> 8) & 0xFF); b = (byte) ((dataBuff[i] >> 16) & 0xFF); data[i] = (byte) ((0.21 * r) + (0.71 * g) + (0.07 * b)); } } out.put(0, 0, data); return out; } 

参考: 这里

您可以在OpenCV中执行以下操作:

 File f4 = new File("aa.png"); Mat mat = Highgui.imread(f4.getAbsolutePath());