Java 在OpenCV中将“BuffereImage”转换为“Mat”

Java 在OpenCV中将“BuffereImage”转换为“Mat”,java,opencv,bufferedimage,mat,Java,Opencv,Bufferedimage,Mat,如何将OpenCV中的buffereImage转换为Mat 我正在为OpenCV(而不是JavaCV)使用JAVA包装器。由于我是OpenCV新手,我在理解Mat的工作原理时遇到了一些问题 我想做这样的事。(根据Ted W.回复): buffereImage image=ImageIO.read(b.getClass().getResource(“Lena.png”); int rows=image.getWidth(); int cols=image.getHeight(); int type

如何将
OpenCV
中的
buffereImage
转换为
Mat

我正在为
OpenCV
(而不是JavaCV)使用JAVA包装器。由于我是
OpenCV
新手,我在理解
Mat
的工作原理时遇到了一些问题

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

buffereImage image=ImageIO.read(b.getClass().getResource(“Lena.png”);
int rows=image.getWidth();
int cols=image.getHeight();
int type=CvType.CV_16UC1;
Mat newMat=新Mat(行、列、类型);
对于(int r=0;r

这不管用
Lena_copy.png
只是一张尺寸正确的黑色图片

一个简单的方法是使用

Mat newMat = Mat(rows, cols, type);
然后从BuffereImage中获取像素值,并使用

newMat.put(row, col, pixel);

我也试着做同样的事情,因为需要将图像处理与两个库结合起来。我试着把
byte[]
放进
Mat
而不是RGB值。成功了!所以我所做的是:

1.将
buffereImage
转换为字节数组,具有:

byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
二,。然后,如果将type设置为CV_8UC3

image_final.put(0, 0, pixels);
编辑: 你也可以试着做相反的事情,因为我找到了一个解决方案。 解决方案类似于安德烈

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 );

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

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

这个对我来说效果很好,需要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;
}

我在程序中使用以下代码

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;
    }
protectedmat img2Mat(BufferedImage in){
垫出;
字节[]数据;
int r,g,b;
if(in.getType()==BuffereImage.TYPE\u INT\u RGB){
out=新垫(in.getHeight()、in.getWidth()、CvType.CV_8UC3);
数据=新字节[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>0)和0xFF);
数据[i*3+1]=(字节)((dataBuff[i]>>8)和0xFF);
数据[i*3+2]=(字节)((dataBuff[i]>>16)和0xFF);
}
}否则{
out=新垫(in.getHeight()、in.getWidth()、CvType.CV_8UC1);
数据=新字节[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>0)和0xFF);
g=(字节)((dataBuff[i]>>8)和0xFF);
b=(字节)((dataBuff[i]>>16)和0xFF);
数据[i]=(字节)((0.21*r)+(0.71*g)+(0.07*b));
}
}
输出(0,0,数据);
返回;
}

参考资料:

不想处理大像素阵列?简单地使用这个

缓冲图像到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);
}
垫到缓冲区图像

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毫秒),但只需要很少的内存(可以忽略不计)PNG是无损的,但编码时间比BMP多一点。使用BMP应该适合我认为的大多数情况。

要将BuffereImage转换为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之前,我将BuffereImage的类型更改为类型_3BYTE_BGR,因为对于某些类型的BuffereImage,方法是((DataBufferByte)image.getRaster().getDataBuffer()).getData()可能返回int[],这将破坏代码

以下是转换为类型3BYTE\u 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;
    }

当您使用as JavaCP包装器时,就可以使用

简单用法如下:

import org.bytedeco.javacv.Java2DFrameUtils;
...
BufferedImage img = ImageIO.read(new File("some/image.jpg");
Mat mat = Java2DFrameUtils.toMat(img);

注意:不要混合使用不同的包装,Mat与Mat不同。

这是您的自定义java包装吗?对于
javacv
来说,它只是
IplImage.createFrom(bufferedImage)
。请发布一些代码,从2.4.4版开始,Opencv有自己的Java绑定。我明白了,我还没有检查,谢谢,维克多里奇在他的回答中没有说些什么。BuffereImage对象必须这样声明:
img=new buffereImage(320240,buffereImage.TYPE_3BYTE_BGR)
img.setRGB(0,03203240intarray,0320)在其他情况下,上述代码将不起作用。该代码在其他情况下也会起作用。两种格式都必须匹配,例如
buffereImage.TYPE_BYTE\u GRAY
CV\u 8UC(1)
也可以工作。此库的工作版本是什么?它对我不起作用(Mat类没有将此方法与这样的签名放在一起),我使用的是bytedeco javacv 1.3.2。这需要JNI。谢谢。上面的功能对我来说只需要一点改变。我正在处理灰度单通道图像。我使用了
Mat Mat=new Mat(bi.getHeight(),bi.getWidth(),CvType.CV_8UC1)这对我很有效。你将如何处理RGBA图像?很好,谢谢。此解决方案独立于BuffereImage的图像输入格式。它适用于24位JPG,同时也适用于32位PNG。这保存了我的屁股,我得到了非常奇怪的颜色失真,直到我遇到这种方法,这是奇怪的原因,如果我保存了图像,然后加载了imread它工作得很好,但我没有理由保存这些图像。