java - Convirtiendo BufferedImage a Mat en opencv
(7)
¿No quieres lidiar con una gran matriz de píxeles? Simplemente usa esto
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 a 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()));
}
¿Cómo puedo convertir una Imagen Buffered a una Mat en OpenCV? Estoy usando el contenedor de Java para OpenCV (no JavaCV). Como soy nuevo en OpenCV, tengo algunos problemas para entender cómo funciona Mat.
Quiero hacer algo como esto (Basado en la respuesta de 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);
Esto no funciona "Lena_copy.png" es solo una imagen negra con las dimensiones correctas.
Encontré una solución here . La solución es similar a 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 );
Este funcionó bien para mí, y lleva de 0 a 1 ms.
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;
}
Puedes hacerlo en OpenCV de la siguiente manera:
File f4 = new File("aa.png");
Mat mat = Highgui.imread(f4.getAbsolutePath());
También estaba tratando de hacer lo mismo, debido a la necesidad de combinar la imagen procesada con dos bibliotecas. Y lo que he tratado de hacer es poner byte[]
en Mat
lugar de valor RGB. ¡Y funcionó! Entonces lo que hice fue:
1. Imagen BufferedImage
convertida a matriz de bytes con:
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
2. Luego, simplemente puede ponerlo en Mat si establece el tipo en CV_8UC3
image_final.put(0, 0, pixels);
Editar: También puedes intentar hacer lo inverso como en esta respuesta
Una manera simple sería crear un nuevo uso
Mat newMat = Mat(rows, cols, type);
luego obtén los valores de píxel de tu Imagen Buffered y ponlos en newMat usando
newMat.put(row, col, pixel);
Uso el siguiente código en mi programa.
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;
}
Referencia: here