Главная > Soft > Определение движения на java с помощью вебкамеры и OpenCV

Определение движения на java с помощью вебкамеры и OpenCV

После попыток получить картинку с помощью Arduino, возник вопрос, а как сделать то же самое, но на обычном компьютере. Пришлось перебрать несколько вариантов и остановиться на библиотеке OpenCV, которая в отличие от java media framework, активно развивается.

OpenCV and Java

Библиотека оказалась полностью написана на c++, имеет реализации для разных платформ и предоставляет обертку для работы из Java через native интерфес.

Если у вас нет опыта работы с этом библеотекой, я бы советовал начать с добавления opencv в вашу IDE. Этот шаг приводиться не будет, т.к. он достаточно хорошо описан в документации. Далее можно попробовать получить картинку с камеры. После этого можно приступать к дальнейшему чтению статьи.

OpenCV не имеет готовых алгоритмов для определения движения по картинкам, но нужный функционал можно получить благодаря богатому набору функций компьютерного зрения.

Идея в алгоритме ниже заключается в обработке двух порядковых изображений. Сначала они сглаживаются. Потом между ними вычисляется разность, которая переводится в градацию серого. Далее разность преобразуется в высококонтрастное изображение. Если движение нет, то результирующее изображение будет полностью черным. Если движение было, то результирующее изобрадение будет иметь белые пятна в местах, где что-то двигалось. Для обнаружения белых пятен используется функция поиска конуров. Этом позволяет в дальнейшем выделить эти области.

Разность изображений

Разность изображений

Ниже приведён этот алгоритм для OpenCV 3.1.0.

package info.privateblog;
import java.util.ArrayList;
import java.util.List;

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.Videoio;

public class OpenCVFaceDetected {
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);    
        VideoCapture camera = new VideoCapture(0);    
        camera.set(Videoio.CV_CAP_PROP_FRAME_WIDTH, 1280);    
        camera.set(Videoio.CV_CAP_PROP_FRAME_HEIGHT, 720);    
            
        if(!camera.isOpened()){    
            System.out.println("Error");    
        }    
        else {    
            int sensivity = 30;  
            double maxArea = 30;  
            int index = 0;    
            Mat frame = new Mat(720, 1280, CvType.CV_8UC3);    
            Mat frame_current = new Mat(720, 1280, CvType.CV_8UC3);    
            Mat frame_previous = new Mat(720, 1280, CvType.CV_8UC3);    
            Mat frame_result = new Mat(720, 1280, CvType.CV_8UC3);    
            Size size = new Size(3, 3);
            Mat v = new Mat();  
            Scalar scalar1 = new Scalar(0, 0, 255);
            Scalar scalar2 = new Scalar(0, 255, 0);
  
            while(true){    
                if (camera.read(frame)){    
                    frame.copyTo(frame_current);  
                      
                    Imgproc.GaussianBlur(frame_current, frame_current, size, 0);  
                      
                    if (index > 1) {  
                        Core.subtract(frame_previous, frame_current, frame_result);  
  
                        Imgproc.cvtColor(frame_result, frame_result, Imgproc.COLOR_RGB2GRAY);  
                          
                        Imgproc.threshold(frame_result, frame_result, sensivity, 255, Imgproc.THRESH_BINARY);      
                          
                        List<MatOfPoint>contours = new ArrayList<MatOfPoint>();  
                        Imgproc.findContours(frame_result, contours, v, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);  
                        v.release();  
                          
                          
                        boolean found = false;  
                        for(int idx = 0; idx < contours.size(); idx++) {                            
                    		Mat contour = contours.get(idx);                            
                    		double contourarea = Imgproc.contourArea(contour);                          
                    		if(contourarea > maxArea) {  
                                found = true;  
  
                                Rect r = Imgproc.boundingRect(contours.get(idx));  
                                Imgproc.drawContours(frame, contours, idx, scalar1);  
                                Imgproc.rectangle(frame, r.br(), r.tl(), scalar2, 1);  
                            }  
                    		contour.release();
	                    }
                          
                        if (found) {  
                            System.out.println("Moved");  
                            Imgcodecs.imwrite("new/" + (sdf.format(new Date())) + ".jpg", frame);    
                        }  
                    }  
                      
                    index++;  
                    
                    frame_current.copyTo(frame_previous); 
                    frame.release();
                    frame_result.release();
                    frame_current.release();
                    
                    try {  
                      Thread.currentThread().sleep(500);  
                    } catch (InterruptedException e) {}  
                }    
            }       
        }    
        camera.release();  
	}
}

Меняя sensivity и maxArea можно менять чувствительность алгоритма.

OpenCV и обнаружение движения

Categories: Soft Tags: , ,
  1. Константин
    13 Март 2016 в 03:25 | #1

    Подскажите пожалуйста русскоязычные ресурсы с описанием возможностей библиотеки java opancv кроме javadoc на сайте разработчиков. Или как научится пользоваться данной библиотекой простому смертному)

  2. Admin
    13 Март 2016 в 18:49 | #2

    Сейчас сам активно ищу хоть что-то. Если не получится, придётся читать примеры на c++ и пытаться портировать на java. Она ведь только оболочка. Пока отличной книгой выглядит «OReilly Learning OpenCV».

  1. Пока что нет уведомлений.