在opencv中将BufferedImage转换为Mat

问题描述 投票:27回答:7

如何在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”只是一张尺寸正确的黑色照片。

java opencv bufferedimage mat
7个回答
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那样做逆


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

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
投票

我找到了解决方案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 );

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


1
投票

一种简单的方法是创建一个新的使用

Mat newMat = Mat(rows, cols, type);

然后从BufferedImage获取像素值并使用

newMat.put(row, col, pixel);

-6
投票

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

File f4 = new File("aa.png");
Mat mat = Highgui.imread(f4.getAbsolutePath());
© www.soinside.com 2019 - 2024. All rights reserved.