如何在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”只是一张尺寸正确的黑色照片。
答案 0 :(得分:24)
我也试图做同样的事情,因为需要将图像处理与两个库相结合。我尝试做的是将byte[]
放入Mat
而不是RGB值。它奏效了!所以我做的是:
1.将BufferedImage
转换为字节数组:
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
2。然后,如果将类型设置为 CV_8UC3
,则可以将其简单地放到Mat中image_final.put(0, 0, pixels);
修改强> 您也可以尝试按照this answer
进行反向操作答案 1 :(得分:18)
这个对我来说很好,并且需要执行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;
}
答案 2 :(得分:14)
不想处理大像素阵列?只需使用此
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到20毫秒)。 BMP 无损且快速(1或2 ms)但需要更多内存(可忽略不计)。 PNG 无损,但比BMP编码的时间多一点。使用 BMP 应该符合我认为的大多数情况。
答案 3 :(得分:3)
我找到了解决方案here。 解决方案类似于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 );
答案 4 :(得分:2)
我在程序中使用以下代码。
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;
}
参考:here
答案 5 :(得分:1)
一种简单的方法是使用
创建一个新的Mat newMat = Mat(rows, cols, type);
然后从BufferedImage获取像素值并使用
放入newMatnewMat.put(row, col, pixel);
答案 6 :(得分:1)
要从BufferedImage转换为Mat,请使用以下方法:
public static Mat img2Mat(BufferedImage image) {
image = convertTo3ByteBGRType(image);
byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
mat.put(0, 0, data);
return mat;
}
在转换为Mat之前,我将bufferedImage的类型更改为TYPE_3BYTE_BGR,因为对于某些类型的BufferedImages,方法为(((DataBufferByte)image.getRaster()。getDataBuffer())。getData(); 可能会返回 int [] ,这将破坏代码。
下面是转换为TYPE_3BYTE_BGR的方法。
private static BufferedImage convertTo3ByteBGRType(BufferedImage image) {
BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(),
BufferedImage.TYPE_3BYTE_BGR);
convertedImage.getGraphics().drawImage(image, 0, 0, null);
return convertedImage;
}
答案 7 :(得分:1)
当您用作JavaCP包装器bytedeco library (version 1.5.3)时,可以使用Java2DFrameUtils。
简单用法是:
import org.bytedeco.javacv.Java2DFrameUtils;
...
BufferedImage img = ImageIO.read(new File("some/image.jpg");
Mat mat = Java2DFrameUtils.toMat(img);
答案 8 :(得分:-6)
您可以在OpenCV中执行以下操作:
File f4 = new File("aa.png");
Mat mat = Highgui.imread(f4.getAbsolutePath());