Line cross pedestrian detection with OpenCV and Java

Before you start you can check out Compiling/Building OpenCV under Ubuntu/Debian

Create a package called detector and inside create a class called LineCrossPedestrianDetector:

package detector;

import javafx.scene.shape.Rectangle;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.HOGDescriptor;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.Videoio;

import javax.swing.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;

public class LineCrossPedestrianDetector {

    // initializing and assigning the pedestrian detector
    private HOGDescriptor hogDetector = new HOGDescriptor();

    // initializing and assigning the "containers" which will hold information about detected the pedestrians
    private MatOfRect detectedPedestrians = new MatOfRect();

    private MatOfDouble pedestriansWeights = new MatOfDouble();

    public static void main(String[] args) {
        // load OpenCV library
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

        // initialize and assign the detector
        LineCrossPedestrianDetector detector = new LineCrossPedestrianDetector();
        // start detecting
        detector.detect();
    }

    private void detect() {
        // initialize and assign the basic image container
        Mat mat = new Mat();
        // initialize and assign which camera to use, on most laptops index - 0 is the main laptop camera
        VideoCapture camera = new VideoCapture(0);
        // get the resolution of the the camera
        final Size frameSize = new Size(camera.get(Videoio.CAP_PROP_FRAME_WIDTH), camera.get(Videoio.CAP_PROP_FRAME_HEIGHT));

        JFrame frame = new JFrame();
        // Make X close the window
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        JLabel panel = new JLabel();
        frame.setContentPane(panel);
        frame.setSize((int) frameSize.width, (int) frameSize.height);
        frame.setVisible(true);

        // when the program stops (Pressed X button, closed from the IDE and etc) makes sure that the image container and the video capture are released
        Runtime.getRuntime().addShutdownHook(new ShutdownThread(mat, camera));

        // the start point for the line
        Point lineStartPoint = new Point(0, 200);

        // the end point
        Point lineEndPoint = new Point(frameSize.width, 200);

        // while the camera is opened and is "reading" video
        while (camera.isOpened() && camera.read(mat)) {
            hogDetector.setSVMDetector(HOGDescriptor.getDefaultPeopleDetector());
            // detect the pedestrians
            hogDetector.detectMultiScale(mat, detectedPedestrians, pedestriansWeights);

            // draw the line
            Imgproc.line(mat, lineStartPoint, lineEndPoint, new Scalar(255, 12, 0), 1);

            for (Rect pedestrian : detectedPedestrians.toArray()) {
                Rectangle rectangle = new Rectangle(pedestrian.x + pedestrian.width / 4, pedestrian.y + pedestrian.height / 4, pedestrian.width - pedestrian.width / 2, pedestrian.height - pedestrian.height / 2 - pedestrian.height / 3);
                boolean intersected = isIntersected(new Point(rectangle.getX(), rectangle.getY()), new Point(rectangle.getX(), rectangle.getY() + rectangle.getHeight()), lineStartPoint, lineEndPoint);
                if (intersected) {
                    System.out.println("Pedestrian crossed the line");
                }
            }

            // converts the basic image container to image
            BufferedImage bufferedImage = mat2BufferedImage(mat);
            if (bufferedImage == null) {
                continue;
            }
            // sets the image
            panel.setIcon(new ImageIcon(bufferedImage));
            // refreshes the panel in the frame
            panel.repaint();
        }
    }

    private BufferedImage mat2BufferedImage(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
        if(m.cols() == 0 && m.rows() == 0){
            return null;
        }
        BufferedImage img = new BufferedImage(m.cols(), m.rows(), type);
        final byte[] targetPixels = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
        System.arraycopy(b, 0, targetPixels, 0, b.length);
        return img;
    }

    private boolean isIntersected(Point start1, Point end1, Point start2, Point end2) {
        Point dir1 = new Point(end1.x - start1.x, end1.y - start1.y);
        Point dir2 = new Point(end2.x - start2.x, end2.y - start2.y);

        double a1 = -dir1.y;
        double b1 = +dir1.y;
        double d1 = -(a1 * start1.x + b1 * start1.y);

        double a2 = -dir2.y;
        double b2 = +dir2.x;
        double d2 = -(a2 * start2.x + b2 * start2.y);

        double line2_start = a2 * start1.x + b2 * start1.y + d2;
        double line2_end = a2 * end1.x + b2 * end1.y + d2;

        double line1_start = a1 * start2.x + b1 * start2.y + d1;
        double line1_end = a1 * end2.x + b1 * end2.y + d1;

        return !(line2_start * line2_end >= 0 || line1_start * line1_end >= 0);
    }

    private class ShutdownThread extends Thread {

        private Mat mat;
        private VideoCapture videoCapture;

        public ShutdownThread(Mat mat, VideoCapture videoCapture) {
            this.mat = mat;
            this.videoCapture = videoCapture;
        }

        @Override
        public void run() {
            super.run();
            mat.release();
            videoCapture.release();
        }
    }
}



If you have any questions or suggestions, feel free to leave a comment.