Konwersja BufferedImage do Mat w OpenCV

Jak mogę przekonwertować obraz BufferedImage na matę w OpenCV? Im using the java wrapper for OpenCV (not JavaCV). Jako że jestem nowy w OpenCV, mam pewne problemy ze zrozumieniem, jak działa Mat.

Chcę zrobić coś takiego. (Na podstawie odpowiedzi Teda 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);
To nie działa. Lena_copypng " to po prostu czarny obraz o prawidłowych wymiarach.
Author: Jompa234, 2013-02-19

7 answers

Starałem się również zrobić to samo, ponieważ trzeba było połączyć obraz przetwarzany z dwiema bibliotekami. A to, co próbowałem zrobić, to umieścić byte[] w Mat zamiast wartości RGB. I zadziałało! Więc to co zrobiłem to:

1.Konwersja BufferedImage do tablicy bajtów z:

byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();

2. Następnie możesz po prostu umieścić go na Mat, jeśli ustawisz typ na CV_8UC3

image_final.put(0, 0, pixels);

Edit: Możesz również spróbować zrobić odwrotność jak na ta odpowiedź

 23
Author: andriy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-05 10:12:15

Ten działał dobrze dla mnie, i to trwa od 0 do 1 ms do wykonania.

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;
}
 17
Author: Jorge Mardones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-15 15:39:49

Nie chcesz mieć do czynienia z dużą macierzą pikseli? Po prostu użyj tego

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 do Buforedimage

public static BufferedImage Mat2BufferedImage(Mat matrix)throws IOException {
    MatOfByte mob=new MatOfByte();
    Imgcodecs.imencode(".jpg", matrix, mob);
    return ImageIO.read(new ByteArrayInputStream(mob.toArray()));
}

Uwaga , choć jest bardzo znikoma. Jednak w ten sposób można uzyskać niezawodne rozwiązanie, ale wykorzystuje kodowanie + dekodowanie. Więc tracisz jakiś występ. Zwykle wynosi od 10 do 20 milisekund. JPG kodowanie traci jakość obrazu również jest powolne (może potrwać od 10 do 20ms). BMP jest bezstratny i szybki (1 lub 2 ms), ale wymaga niewiele więcej pamięci (znikome). PNG jest bezstratny, ale trochę więcej czasu na kodowanie niż BMP. Używanie BMP powinno pasować do większości przypadków.

 12
Author: Ultraviolet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-09 10:39:06

Znalazłem rozwiązanie Tutaj . Rozwiązanie jest podobne do Andrija.

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 );
 3
Author: Jompa234,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-11 12:56:22

Jednym z prostych sposobów byłoby utworzenie nowego za pomocą

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

Następnie pobierz wartości pikseli z BufferedImage i umieść w newMat za pomocą

newMat.put(row, col, pixel);
 1
Author: Ted W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-19 13:55:11

Używam poniższego kodu w moim programie.

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

Reference: here

 1
Author: Karthik N G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-03 16:15:34

Możesz to zrobić w OpenCV w następujący sposób:

File f4 = new File("aa.png");
Mat mat = Highgui.imread(f4.getAbsolutePath());
 -6
Author: Ishan Randeniya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-20 19:08:03