9.0 Practical Applications: Video I/O and Object Detection
This final practical module is the culmination of our studies. Here, we will apply fundamental concepts to solve real-world problems. This section will demonstrate how to capture and process a live video stream from a camera and then perform a classic computer vision task: detecting human faces in both static images and real-time video. This is an excellent opportunity to see how the building blocks we’ve learned can be assembled into something truly interactive and powerful.
9.1 Interfacing with Cameras for Real-Time Video
The VideoCapture class from the org.opencv.videoio package is the primary tool for interacting with cameras and video files. It provides a simple interface to open a camera device and capture frames from it one by one.
The process for capturing a single frame from a camera can be broken down into these steps:
- Load the OpenCV native library: As always, this is the first step.
- Instantiate VideoCapture: Create an object of the VideoCapture class. Passing 0 to the constructor typically opens the default system camera.
- Capture a frame: Use the read() method, which captures the next available frame from the camera and stores it in a provided Mat object.
The following example captures a single snapshot from the camera, displays it in a JavaFX window, and saves the frame to a file.
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.stage.Stage;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.videoio.VideoCapture;
public class CameraSnapshotJavaFX extends Application {
private Mat matrix = null;
@Override
public void start(Stage stage) {
WritableImage writableImage = capureSnapShot();
saveImage();
ImageView imageView = new ImageView(writableImage);
imageView.setFitHeight(400);
imageView.setFitWidth(600);
imageView.setPreserveRatio(true);
Group root = new Group(imageView);
Scene scene = new Scene(root, 600, 400);
stage.setTitle(“Camera Snapshot”);
stage.setScene(scene);
stage.show();
}
public WritableImage capureSnapShot() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture capture = new VideoCapture(0);
Mat matrix = new Mat();
WritableImage writableImage = null;
if (capture.isOpened()) {
if (capture.read(matrix)) {
BufferedImage image = new BufferedImage(matrix.width(), matrix.height(), BufferedImage.TYPE_3BYTE_BGR);
WritableRaster raster = image.getRaster();
DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer();
byte[] data = dataBuffer.getData();
matrix.get(0, 0, data);
this.matrix = matrix;
writableImage = SwingFXUtils.toFXImage(image, null);
}
}
capture.release();
return writableImage;
}
public void saveImage() {
String file = “path/to/your/snapshot.jpg”;
Imgcodecs.imwrite(file, matrix);
}
public static void main(String args[]) {
launch(args);
}
}
9.2 Object Detection using Cascade Classifiers: Face Detection
Object detection is the task of finding instances of specific objects in an image. OpenCV provides a robust method for this using Cascade Classifiers. This technique uses pre-trained models, typically stored in XML files, that have learned the visual features of a particular object. We will use a classifier pre-trained to detect frontal faces.
Face Detection in a Static Image
The process for detecting faces in a static image involves three key steps:
- Load the native library.
- Instantiate CascadeClassifier: Create an object of this class, passing the path to the classifier XML file (e.g., lbpcascade_frontalface.xml) to its constructor. These XML files are included with the OpenCV distribution.
- Detect faces with detectMultiScale(): This method scans the input Mat to find objects. Its output is a MatOfRect, which contains Rect objects, each representing the bounding box of a detected face. The parameters allow you to control the sensitivity of the detection, such as the minimum size of faces to detect.
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
public class FaceDetectionImage {
public static void main (String[] args) {
System.loadLibrary( Core.NATIVE_LIBRARY_NAME );
String imagePath = “path/to/your/face_image.jpg”;
Mat src = Imgcodecs.imread(imagePath);
String xmlFile = “path/to/your/opencv/sources/data/lbpcascades/lbpcascade_frontalface.xml”;
CascadeClassifier classifier = new CascadeClassifier(xmlFile);
MatOfRect faceDetections = new MatOfRect();
classifier.detectMultiScale(src, faceDetections);
System.out.println(String.format(“Detected %s faces”, faceDetections.toArray().length));
for (Rect rect : faceDetections.toArray()) {
Imgproc.rectangle(
src,
new Point(rect.x, rect.y),
new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 0, 255),
3
);
}
Imgcodecs.imwrite(“path/to/your/face_detection_output.jpg”, src);
System.out.println(“Image Processed”);
}
}
The logic here is straightforward: after loading the pre-trained classifier and the image, detectMultiScale finds the faces. We then iterate through the returned rectangles and use Imgproc.rectangle() to draw a red box around each detected face on the original image before saving the result.
Face Detection in Live Video
To perform face detection on a live video stream, we simply combine the techniques from the previous two sections. We create a main loop that continuously:
- Captures a frame from the camera using VideoCapture.
- Runs the detectMultiScale() method on the captured frame.
- Iterates through the resulting MatOfRect and draws rectangles on the frame.
- Displays the annotated frame in a GUI window.
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.stage.Stage;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
public class FaceDetectionJavaFX extends Application {
private Mat matrix = null;
@Override
public void start(Stage stage) {
WritableImage writableImage = captureFrame();
ImageView imageView = new ImageView(writableImage);
imageView.setFitHeight(400);
imageView.setFitWidth(600);
imageView.setPreserveRatio(true);
Group root = new Group(imageView);
Scene scene = new Scene(root, 600, 400);
stage.setTitle(“Live Face Detection”);
stage.setScene(scene);
stage.show();
}
public WritableImage captureFrame() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture capture = new VideoCapture(0);
Mat matrix = new Mat();
WritableImage writableImage = null;
if (capture.read(matrix)) {
String xmlFile = “path/to/your/opencv/sources/data/lbpcascades/lbpcascade_frontalface.xml”;
CascadeClassifier classifier = new CascadeClassifier(xmlFile);
MatOfRect faceDetections = new MatOfRect();
classifier.detectMultiScale(matrix, faceDetections);
System.out.println(String.format(“Detected %s faces”, faceDetections.toArray().length));
for (Rect rect : faceDetections.toArray()) {
Imgproc.rectangle(
matrix,
new Point(rect.x, rect.y),
new Point(rect.x + rect.width, rect.y + rect.height),
new Scalar(0, 0, 255),
3
);
}
BufferedImage image = new BufferedImage(matrix.width(), matrix.height(), BufferedImage.TYPE_3BYTE_BGR);
WritableRaster raster = image.getRaster();
DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer();
byte[] data = dataBuffer.getData();
matrix.get(0, 0, data);
this.matrix = matrix;
writableImage = SwingFXUtils.toFXImage(image, null);
}
capture.release();
return writableImage;
}
public static void main(String args[]) {
launch(args);
}
}
The power of combining these fundamental techniques allows for the creation of sophisticated and interactive computer vision applications.