项目实操中,有一处的需求是将BufferedImage转换至Mat,然后调用OpenCV方法进行处理,然后报此错,如下图所示。
解决方案(实测有效)
更改 BufferedImage 类型
BufferedImage bi1 = openSlide.createThumbnailImage(700);
BufferedImage bi2= new BufferedImage(bi1.getWidth(),bi1.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
bi2.getGraphics().drawImage(bi1 , 0, 0, null);
通过getGraphics().drawImage
方法将bi1的图像属性修改为TYPE_3BYTE_BGR
原因是BufferedImage.TYPE_3BYTE_BGR使用 byte[3] 来表示每个像素并且 BufferedImage.TYPE_INT_RGB只使用一个 int
本人使用的BufferedImage转Mat方法如下
/**
* 图像格式转换:BufferedImage -> Mat
*
* @param bi bi
* @return {@link Mat}
*/
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
image.getRaster().getDataBuffer()返回的是 DataBufferByte,而您正试图转换为 DataBufferInt。这是两个不同的类,都是 DataBuffer 的子类,但一个不是另一个的子类,因此无法在它们之间进行转换。
Raster 的规范没有清楚地描述是什么决定 getDataBuffer, 是返回 DataBufferByte 还是 DataBufferInt(或者可能是其他类型的 DataBuffer)。但大概这取决于被处理的图像类型。(可能是因为处理的像素和代码期待的像素位数冲突)
事实上,可能需要从该部分中删除一些逻辑并将其添加到显式构造函数中,这样您就可以测试返回的 DataBuffer 类型并相应地处理它,而不是无条件地将其强制转换为 DataBufferInt。
解决方案 3
image.getRaster().getDataBuffer().getDataType()从 class 传递一个类型常量DataBuffer,例如TYPE_BYTE, TYPE_SHORT, TYPE_INT,这些中的每一个都绑定 的唯一DataBuffer[Type]子类DataBuffer。因此,您可以检测类型化缓冲区转换是否会成功。
int 和 byte[4] 之间的转换基本上取决于字节顺序规则,该规则未在 Java 内部类型级别上定义,因此无法很好地定义此类数组的重新解释转换。需要定义和应用类型转换。DataInputStream.readInt实际上使用定义的转换:Big-endianness byte[]从到 的转换int[]可以通过从作为源的DataInputStreamwith中读取整数来执行ByteArrayInputStream,并用字节数组初始化。