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?
le codage JPEG est intéressant, mais il y a quelques problèmes:
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; }
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.
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.
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();
}
}