我正在尝试将BufferedImage转换为Mat,以获取从互联网下载的具有不同文件类型的大量图像。因为我是刮从网站的图像,我没有控制的文件格式。我可以在不知道格式的情况下轻松地将它们加载到BufferedImage,但是要将它们转换为Mat,我需要知道图像类型。不幸的是,CvType和BufferedImage类型之间似乎没有很好的对应关系。
CvType用格式CV_<bit-depth>{U|S|F}C<number_of_channels>表示图像类型,其中U是无符号字符,S是有符号字符,F是浮点。
BufferedImage类型在表示形式上有更多的变化,包括对称通道(TYPE_4BYTE_ABGR)、可变比特数(TYPE_BYTE_BINARY)以及任何索引字节图像(TYPE_BYTE_INDEXED)。
根据文件,我试图完成我自己的信件。
BufferedImage imgBuffer = ImageIO.read(new File("example.gif"));
//Save file as reference
File outputfile = new File("temp/image.png");
ImageIO.write(imgBuffer, "png", outputfile);
//My correspondance
int curCVtype = -1;
switch (imgBuffer.getType()) {
case BufferedImage.TYPE_3BYTE_BGR:
curCVtype = CvType.CV_8UC3;
break;
case BufferedImage.TYPE_BYTE_GRAY:
curCVtype = CvType.CV_8UC1;
break;
case BufferedImage.TYPE_INT_BGR:
case BufferedImage.TYPE_INT_RGB:
curCVtype = CvType.CV_8SC3;
break;
case BufferedImage.TYPE_INT_ARGB:
case BufferedImage.TYPE_INT_ARGB_PRE:
curCVtype = CvType.CV_8SC4;
break;
default:
// The types not handled by my correspondence
// BufferedImage.TYPE_BYTE_BINARY;
// BufferedImage.TYPE_USHORT_GRAY;
// BufferedImage.TYPE_4BYTE_ABGR;
// BufferedImage.TYPE_4BYTE_ABGR_PRE;
// BufferedImage.TYPE_BYTE_INDEXED;
// BufferedImage.TYPE_CUSTOM;
System.out.println("Unsupported format:" + imgBuffer.getType());
//Here I choose a default type
curCVtype = CvType.CV_8SC3;
}
//Convert to Mat
byte[] pixels = ((DataBufferByte) imgBuffer.getRaster().getDataBuffer()).getData();
Mat img = new Mat(imgBuffer.getHeight(), imgBuffer.getWidth(), curCVtype);
img.put(0, 0, pixels);
//Write the output to compare
Imgcodecs.imwrite("temp/image_mat.png", img);问题
示例
输入

用BufferedImage转换成PNG

转换成Mat后输出PNG。BufferedImage类型被TYPE_BYTE_INDEXED转换为CvType.CV_8SC3

转换成Mat后输出PNG。BufferedImage类型被TYPE_BYTE_INDEXED转换为CvType.CV_8UC3

资源:
我的起始代码来自Converting BufferedImage to Mat in opencv。
我对CvTypes的了解来自于What's the difference between cvtype values in OPENCV?。
发布于 2015-10-29 16:40:33
感谢Miki和haraldK的有益评论。
我的未知图像类型解决方案以RGB格式检索像素,并将它们放入Mat of CvType.CV_8UC4中。最后,使用Core.mixChannels将信道重新排序为OpenCV优先顺序: BGR(A)。
此示例只为未知图像类型重新排序通道,但所有非BGR图像类型都需要重新排序。
BufferedImage imgBuffer = ImageIO.read(new File("example.gif"));
//Save image as reference
File outputfile = new File("temp/image.png");
ImageIO.write(imgBuffer, "png", outputfile);
//My correspondance
int curCVtype = CvType.CV_8UC4; //Default type
boolean supportedType = true;
switch (imgBuffer.getType()) {
case BufferedImage.TYPE_3BYTE_BGR:
curCVtype = CvType.CV_8UC3;
break;
case BufferedImage.TYPE_BYTE_GRAY:
case BufferedImage.TYPE_BYTE_BINARY:
curCVtype = CvType.CV_8UC1;
break;
case BufferedImage.TYPE_INT_BGR:
case BufferedImage.TYPE_INT_RGB:
curCVtype = CvType.CV_32SC3;
break;
case BufferedImage.TYPE_INT_ARGB:
case BufferedImage.TYPE_INT_ARGB_PRE:
curCVtype = CvType.CV_32SC4;
break;
case BufferedImage.TYPE_USHORT_GRAY:
curCVtype = CvType.CV_16UC1;
break;
case BufferedImage.TYPE_4BYTE_ABGR:
case BufferedImage.TYPE_4BYTE_ABGR_PRE:
curCVtype = CvType.CV_8UC4;
break;
default:
// BufferedImage.TYPE_BYTE_INDEXED;
// BufferedImage.TYPE_CUSTOM;
System.out.println("Unsupported format:" + imgBuffer.getType());
supportedType = false;
}
//Convert to Mat
Mat img = new Mat(imgBuffer.getHeight(), imgBuffer.getWidth(), curCVtype);
if (supportedType) {
// Insert pixel buffer directly
byte[] pixels = ((DataBufferByte) imgBuffer.getRaster().getDataBuffer()).getData();
img.put(0, 0, pixels);
} else {
// Convert to RGB first
int height = imgBuffer.getHeight();
int width = imgBuffer.getWidth();
int[] pixels = imgBuffer.getRGB(0, 0, width - 1, height - 1, null, 0, width);
// Convert ints to bytes
ByteBuffer byteBuffer = ByteBuffer.allocate(pixels.length * 4);
IntBuffer intBuffer = byteBuffer.asIntBuffer();
intBuffer.put(pixels);
byte[] pixelBytes = byteBuffer.array();
img.put(0, 0, pixelBytes);
// Reorder the channels for Opencv BGRA format from
// BufferedImage ARGB format
Mat imgMix = img.clone();
ArrayList<Mat> imgSrc = new ArrayList<Mat>();
imgSrc.add(imgMix);
ArrayList<Mat> imgDest = new ArrayList<Mat>();
imgDest.add(img);
int[] fromTo = { 0, 3, 1, 2, 2, 1, 3, 0 }; //Each pair is a channel swap
Core.mixChannels(imgSrc, imgDest, new MatOfInt(fromTo));
}
//Save output image
Imgcodecs.imwrite("temp/image_mat.png", img);新输出图像

https://stackoverflow.com/questions/33403526
复制相似问题