web-dev-qa-db-fra.com

Opencv Java - Charger l'image dans l'interface graphique

Je développe une application utilisant Java Opencv-2.4.4 et une interface graphique. Le problème est que je ne trouve aucune solution qui montre de manière efficace comment imprimer une image traitée (enregistrée dans Mat object) sur l'interface graphique de Java Swing. Pour le moment, j'utilise cette solution maladroite: 

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

Lorsque l'utilisateur modifie certaines valeurs, entrées, etc., dans l'interface graphique, je dois écraser Output.png sur le disque et mettre à jour jLabel avec une nouvelle image à partir du disque.

Y at-il une solution plus élégante/efficace à cela? Est-il possible de tracer ou de convertir Mat objet directement en Toile ou Image ou tout ce qui est imprimable en tant qu'image en swing?

18
mholecy

le codage JPEG est intéressant, mais il y a quelques problèmes:

  • ce n'est pas un format sans perte, vous perdrez des données d'image lors de la compression
  • cela prend un certain temps (environ 6 à 10 fois plus long que celui suggéré ci-dessous)
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;

  }
10
dannyxyz22

Oui, il existe un moyen plus élégant de le faire. Vous pouvez concocter Mat au type BufferedImage, puis le charger simplement avec swing. Le code pour le convertir en image tamponnée est:

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

Et puis vous pouvez simplement le peindre dans votre objet GUI:

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

où g est de type Graphics

J'espère que cela t'aides.

15
andriy

Ceci est une solution prête à l'emploi pour l'équivalent de Imshow() en Java OpenCV. Son utilisation est simple. L'API ressemblera à:

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

Visitez ici https://github.com/master-atul/ImShow-Java-OpenCV

C'est une meilleure solution car vous ne stockez pas l'image sur le disque et ne le lisez pas à nouveau. Par conséquent, cela réduit la surcharge de lecture d'un disque et est donc plus rapide.

2
Atul

Utilisation de la réponse de @ andriy. Je suis venu avec cette solution. J'ai utilisé JFrame au lieu de Graphics. J'espère que cela t'aides.

public void imshow(Mat src){
    BufferedImage bufImage = null;
    try {
        MatOfByte matOfByte = new MatOfByte();
        Highgui.imencode(".jpg", src, matOfByte); 
        byte[] byteArray = matOfByte.toArray();
        InputStream in = new ByteArrayInputStream(byteArray);
        bufImage = ImageIO.read(in);

        JFrame frame = new JFrame("Image");
        frame.getContentPane().setLayout(new FlowLayout());
        frame.getContentPane().add(new JLabel(new ImageIcon(bufImage)));
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
1
Karthik N G