Skip to content

Commit 0fda652

Browse files
committed
cv::Mat OpenCV en JavaFX ImageView
1 parent 772d316 commit 0fda652

File tree

3 files changed

+110
-40
lines changed

3 files changed

+110
-40
lines changed

JavaFX-OpenCV/Readme.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
# OpenCV & JavaFX
2-
Interacción de una aplicación **JavaFX** con la librería **OpenCV**, explica como convertir un objeto *org.opencv.core.Mat* a *javafx.scene.image.Image* para poder mostrarlo en un control ImageView.
2+
Interacción de una aplicación *JavaFX* con la librería *OpenCV*, explica como convertir un objeto *org.opencv.core.Mat* a *javafx.scene.image.Image* para poder mostrarlo en un control ImageView.
33

4-
Este proyecto no incluye la librería OpenCV, por lo que devemos descargala y copiar la carpeta /opencv/build/java dentro de la carpeta de proyecto /JavaFX-OpenCV/lib
4+
Además creamos un ScheduledService<Image> para obtener priodicamente en segundo plano una captura de la cámara, esto nos permite mostrar una secuencia fluida de video.
5+
6+
Este proyecto no incluye la librería OpenCV, por lo que debemos descárgala y copiar la carpeta **/opencv/build/java** dentro de la carpeta de proyecto **/JavaFX-OpenCV/lib**.
7+
8+
Puedes encontrar más información y otros tutoriales en: [Tutoriales JavaFX](http://acodigo.blogspot.com/p/tutorial-opencv.html)
+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* To change this license header, choose License Headers in Project Properties.
3+
* To change this template file, choose Tools | Templates
4+
* and open the template in the editor.
5+
*/
6+
package carmelo;
7+
8+
import java.io.ByteArrayInputStream;
9+
import java.util.Objects;
10+
import java.util.function.Function;
11+
import javafx.concurrent.Task;
12+
import javafx.scene.image.Image;
13+
import org.opencv.core.Mat;
14+
import org.opencv.core.MatOfByte;
15+
import org.opencv.imgcodecs.Imgcodecs;
16+
import org.opencv.videoio.VideoCapture;
17+
18+
/**
19+
*
20+
* @author Carmelo Marin Abrego
21+
*/
22+
public class CameraTask extends Task<Image> {
23+
24+
private final VideoCapture capture;
25+
private final Function<Mat, Mat> imgproc;
26+
27+
public CameraTask(VideoCapture capture, Function<Mat, Mat> imgproc) {
28+
this.capture = Objects.requireNonNull(capture);
29+
this.imgproc = Objects.requireNonNull(imgproc);
30+
}
31+
32+
@Override
33+
protected Image call() throws Exception {
34+
35+
// omitir si la camara no esta abierta
36+
if (!capture.isOpened()) {
37+
return null;
38+
}
39+
40+
// obtiene la captura de la camara, lo almacena el frame
41+
Mat frame = new Mat();
42+
capture.read(frame);
43+
44+
// verificar si es una captura valida
45+
if (!frame.empty()) {
46+
// procesar y convertir la imagen
47+
Mat dst = imgproc.apply(frame);
48+
return createImageFromMat(dst);
49+
}
50+
51+
return null;
52+
}
53+
54+
// convertir cv::Mat a javafx.scene.image.Image
55+
private Image createImageFromMat(Mat src) {
56+
MatOfByte dst = new MatOfByte();
57+
Imgcodecs.imencode(".bmp", src, dst);
58+
return new Image(new ByteArrayInputStream(dst.toArray()));
59+
}
60+
61+
}

JavaFX-OpenCV/src/carmelo/JavaFXOpenCV.java

+43-38
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
*/
66
package carmelo;
77

8-
import java.io.ByteArrayInputStream;
9-
import javafx.animation.AnimationTimer;
108
import javafx.application.Application;
9+
import javafx.concurrent.ScheduledService;
10+
import javafx.concurrent.Task;
11+
import javafx.concurrent.WorkerStateEvent;
1112
import javafx.event.ActionEvent;
1213
import javafx.geometry.Insets;
1314
import javafx.scene.Scene;
@@ -17,14 +18,12 @@
1718
import javafx.scene.layout.VBox;
1819
import javafx.stage.Stage;
1920
import javafx.stage.WindowEvent;
21+
import javafx.util.Duration;
2022
import org.opencv.core.Core;
2123
import org.opencv.core.Mat;
22-
import org.opencv.core.MatOfByte;
2324
import org.opencv.core.Size;
24-
import org.opencv.imgcodecs.Imgcodecs;
2525
import org.opencv.imgproc.Imgproc;
2626
import org.opencv.videoio.VideoCapture;
27-
import org.opencv.videoio.Videoio;
2827

2928
/**
3029
*
@@ -38,34 +37,32 @@ public class JavaFXOpenCV extends Application {
3837

3938
private VideoCapture capture;
4039
private ImageView imageView;
41-
private AnimationTimer timer;
40+
private ScheduledService<Image> service;
4241

4342
@Override
4443
public void start(Stage primaryStage) {
4544

46-
timer = new AnimationTimer() {
45+
capture = new VideoCapture();
46+
47+
// servicio que ejecutar la captura periodicamente
48+
service = new ScheduledService<Image>() {
4749
@Override
48-
public void handle(long now) {
49-
if (capture.isOpened()) {
50-
Mat frame = new Mat();
51-
capture.read(frame);
52-
if (!frame.empty()) {
53-
54-
Mat dst = new Mat();
55-
56-
Imgproc.cvtColor(frame, dst, Imgproc.COLOR_BGR2GRAY);
57-
Imgproc.GaussianBlur(dst, dst, new Size(7, 7), 1.5, 1.5);
58-
Imgproc.Canny(dst, dst, 0, 30, 3, false);
59-
60-
imageView.setImage(createImageFromMat(dst));
61-
}
62-
}
50+
protected Task<Image> createTask() {
51+
// crear un CameraTask usando el VideoCapture y
52+
// el metodo para procesar la imagen idicado JavaFXOpenCV.this::procesarImagen
53+
return new CameraTask(capture, JavaFXOpenCV.this::procesarImagen);
6354
}
6455
};
6556

57+
// ejecutar el servicio cada 33.3 ms
58+
service.setPeriod(Duration.millis(33.333333));
59+
60+
// al finalizar cada ejecucion ejecutar el metodo this::ready
61+
service.setOnReady(this::ready);
62+
6663
imageView = new ImageView();
67-
imageView.setFitHeight(320);
68-
imageView.setFitWidth(460);
64+
imageView.setFitHeight(600);
65+
imageView.setFitWidth(800);
6966

7067
Button btn = new Button();
7168
btn.setText("Iniciar Camara");
@@ -81,32 +78,40 @@ public void handle(long now) {
8178
primaryStage.setScene(scene);
8279
primaryStage.sizeToScene();
8380
primaryStage.setOnCloseRequest(this::stop);
81+
primaryStage.setResizable(false);
8482

8583
primaryStage.show();
8684
}
8785

88-
private void start(ActionEvent e) {
89-
if (capture == null) {
90-
capture = new VideoCapture();
91-
capture.set(Videoio.CAP_PROP_FRAME_WIDTH, 460);
92-
capture.set(Videoio.CAP_PROP_FRAME_HEIGHT, 320);
86+
private Mat procesarImagen(Mat src) {
87+
Mat dst = new Mat();
88+
89+
Imgproc.cvtColor(src, dst, Imgproc.COLOR_BGR2GRAY);
90+
Imgproc.GaussianBlur(dst, dst, new Size(7, 7), 1.5, 1.5);
91+
Imgproc.Canny(dst, dst, 0, 30, 3, false);
92+
93+
return dst;
94+
}
95+
96+
private void ready(WorkerStateEvent worker) {
97+
Image image = (Image) worker.getSource().getValue();
98+
if (image != null) {
99+
imageView.setImage(image);
93100
}
101+
}
94102

95-
capture.open(0);
96-
timer.start();
103+
private void start(ActionEvent e) {
104+
if (!capture.isOpened() && !service.isRunning()) {
105+
capture.open(0);
106+
service.start();
107+
}
97108
}
98109

99110
private void stop(WindowEvent e) {
100-
timer.stop();
111+
service.cancel();
101112
capture.release();
102113
}
103114

104-
private Image createImageFromMat(Mat src) {
105-
MatOfByte dst = new MatOfByte();
106-
Imgcodecs.imencode(".bmp", src, dst);
107-
return new Image(new ByteArrayInputStream(dst.toArray()));
108-
}
109-
110115
/**
111116
* @param args the command line arguments
112117
*/

0 commit comments

Comments
 (0)