2015-01-03 16 views
6

Vorrei visualizzare gli oggetti Mat da OpenCV direttamente con JavaFX. Ho visto che è possibile convertire un oggetto Mat in un BufferedImage. Ma per quanto ne so non è possibile visualizzare uno BufferedImage con JavaFX, quindi dovrebbe avvenire un'altra conversione.Display OpenCV Mat con JavaFX

C'è un modo per direttamente convertirlo in una struttura dati che è visualizzabile da JavaFX?

+0

Probabilmente è possibile convertire direttamente in FX, usando un 'WritableImage'. O copiando pixel dal 'Mat' al' PixelWriter' di 'WritableImage', oppure implementando un' PixelReader' supportato dal 'Mat', e usatelo direttamente per creare un'istanza di' WritableImage'. – haraldK

risposta

6

Ho trovato un modo diretto per convertire un oggetto Mat in un oggetto JavaFX Image.

MatOfByte byteMat = new MatOfByte(); 
Highgui.imencode(".bmp", mat, byteMat); 
return new Image(new ByteArrayInputStream(byteMat.toArray())); 

È anche possibile codificare per .jpg ma .bmp è più veloce.

+0

Perché il mio OpenCV non viene fornito con la libreria/classe HighGUI? –

+1

Ho usato "Imgcodecs.imencode" invece e ha funzionato –

2

Il modo più stupido per farlo è quello di convertire il Mat ad un BufferedImage, e poi che a un Image in modo che possa essere visualizzato all'interno di un ImageView:

Mat >> BufferedImage >> Image >> ImageView 

Supponendo che si sa come fare la prima la conversione, il resto sarebbe qualcosa di simile a questo:

import javafx.embed.swing.SwingFXUtils; 
import javafx.scene.image.Image; 
import javafx.scene.image.ImageView; 

Image image = SwingFXUtils.toFXImage(bufImage, null); 

ImageView imgView = new ImageView(); 
imgView.setImage(image); 

non ho ancora testato il codice, ma questa è l'idea generale.

2

La risposta di TomTom è stata molto utile e ha risolto il problema, ma Highgui non ha più alcun binding in java.

Come di OpenCV 3.0.0, il codice up-to-date è più simile a:

MatOfByte byteMat = new MatOfByte(); 
Imgcodecs.imencode(".bmp", mat, byteMat); 
return new Image(new ByteArrayInputStream(byteMat.toArray())); 
+0

La tua risposta è la soluzione per OpenCV versione 3. Le versioni precedenti utilizzano Highgui. – Roland

+0

Grazie per la precisione, ho appena modificato e corretto la mia risposta. – deb0ch

0

Invece di codifica e decodifica per ottenere l'array di byte è necessario, si può semplicemente dichiarare un array e l'uso il metodo get. Questo è un codice Scala, ma eventualmente è intelligibile:

val arr = new Array[Byte](w * h * 3) 
mat.get(0, 0, arr) 
pw.setPixels(0, 0, w, h, PixelFormat.getByteRgbInstance, arr, 0, w * 3) 

Questo codice dichiara l'array arr di tipo byte[] con la dimensione corrispondente a un'immagine di h da w e 3 canali. Quindi i dati vengono copiati dall'oggetto mat nell'array e passati al metodo setPixels dall'oggetto PixelWriterpw.