Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Opencv java - Load image to GUI

I'm developing an application using Java Opencv-2.4.4 and swing GUI. Problem is that I'm unable to find any solution, that shows efficient way how to print processed image (saved in Mat object) to java swing GUI. For this moment I'm using this clumsy solution:

javax.swing.JLabel outputImage;
outputImage.setIcon(new javax.swing.ImageIcon("/home/username/Output.png"));

private void sliderStateChanged(javax.swing.event.ChangeEvent evt) { 
       .
       .
  Mat canny; // Here is saved what I want to plot
  String filename = "/home/username/Output.png";
  Highgui.imwrite(filename, canny);  // write to disk
  outputImage.setIcon(new ImageIcon(ImageIO.read(new File(filename)))); //update Icon
       .
       .
}

When user changes some values, inputs etc ., in GUI I have to overwrite Output.png on disk and update jLabel with new image from disk.

Is there any more elegant / efficient solution to this ? Is it posible to plot or convert Mat object directly to Canvas or Image or anything that is printable as image in swing ?

like image 233
mholecy Avatar asked Mar 27 '13 22:03

mholecy


3 Answers

Yes there is more elegant way to do it. You can concert Mat to BufferedImage type and then just Load it with swing. The code to convert it to Buffered image is:

    Mat image_tmp = your image

    MatOfByte matOfByte = new MatOfByte();

    Highgui.imencode(".jpg", image_tmp, matOfByte); 

    byte[] byteArray = matOfByte.toArray();
    BufferedImage bufImage = null;

    try {

        InputStream in = new ByteArrayInputStream(byteArray);
        bufImage = ImageIO.read(in);
    } catch (Exception e) {
        e.printStackTrace();
    }

And then you just can paint it in your GUI object:

g.drawImage(bufImage , 0, 0, null);

where g is of type Graphics

Hope this helps.

like image 163
andriy Avatar answered Oct 24 '22 03:10

andriy


jpeg encoding is interesting, but there are a couple problems:

  • it is not a lossless format, you will lose image data when compressing
  • it takes quite a while (around 6 to 10 times longer than the suggested one below)
public Image toBufferedImage(Mat m){
      int type = BufferedImage.TYPE_BYTE_GRAY;
      if ( m.channels() > 1 ) {
          type = BufferedImage.TYPE_3BYTE_BGR;
      }
      int bufferSize = m.channels()*m.cols()*m.rows();
      byte [] b = new byte[bufferSize];
      m.get(0,0,b); // get all the pixels
      BufferedImage image = new BufferedImage(m.cols(),m.rows(), type);
      final byte[] targetPixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
      System.arraycopy(b, 0, targetPixels, 0, b.length);  
      return image;

  }
like image 34
dannyxyz22 Avatar answered Oct 24 '22 05:10

dannyxyz22


This is a readymade solution for Imshow() equivalent in Java OpenCV Its simple to use. API will look like:

Imshow im = new Imshow("Title");
im.showImage(matimage);

Visit here https://github.com/master-atul/ImShow-Java-OpenCV

This is a better solution as you don't store the image into disk and read again. Hence it reduces the overhead of reading from a disk and thus is faster.

like image 2
Atul Avatar answered Oct 24 '22 04:10

Atul