【问题标题】:Web Cam access using JavaFX使用 JavaFX 访问网络摄像头
【发布时间】:2015-09-15 09:41:40
【问题描述】:

我一直在寻找从 java 或 javaFX 应用程序访问内置网络摄像头的解决方案。我已经看到很多其他帖子指向 OpenCV 和 JavaCV、Sarxos 的库以及其他一些库。 我遇到了一些困难,例如较新版本的 OpenCV 无法使用发布在各个站点上的旧代码,以及使用 OpenCV 3.0 的较新代码很难找到或无法满足我的需要,这只是一个客户应用程序,可以节省从网络摄像头拍摄的图像到变量(或文件)。 希望有人能指出我正确的方向。 提前致谢

【问题讨论】:

    标签: java opencv javafx webcam


    【解决方案1】:

    你很幸运。上周末我玩弄了 OpenCV,遇到了和你一样的问题。这是有关如何执行此操作的示例。该示例打开相机,使用 AnimationTimer(有点矫枉过正,但它是原型设计的快速解决方案)定期抓取 mat 图像,将 mat 图像转换为 JavaFX 图像,执行面部检测并将其绘制在画布上。

    这是你需要的:

    下载OpenCV,例如。 G。在我的情况下,Windows版本。将 opencv-3.0.0.exe 重命名为 opencv-3.0.0.exe.zip 并打开。提取 build/java 的内容。

    创建一个新的 JavaFX 项目。将 jar 和 dll 放入 lib 文件夹,例如。 g.:

    lib/opencv-300.jar
    lib/x64/opencv_java300.dll
    

    将 jar 添加到您的构建路径。

    在您的 src 文件夹中创建一个路径 opencv/data/lbpcascades 并将文件 lbpcascade_frontalface.xml 放在那里(在 etc/lbpcascades 中找到)。这只是用于人脸检测,您可以在不需要时取消注释代码。

    创建应用类,代码:

    import java.io.ByteArrayInputStream;
    import java.lang.reflect.Field;
    import java.net.URISyntaxException;
    import java.nio.file.Paths;
    import java.util.ArrayList;
    import java.util.List;
    
    import javafx.animation.AnimationTimer;
    import javafx.application.Application;
    import javafx.event.EventHandler;
    import javafx.geometry.Rectangle2D;
    import javafx.scene.Group;
    import javafx.scene.Scene;
    import javafx.scene.canvas.Canvas;
    import javafx.scene.canvas.GraphicsContext;
    import javafx.scene.image.Image;
    import javafx.scene.paint.Color;
    import javafx.stage.Stage;
    import javafx.stage.WindowEvent;
    
    import org.opencv.core.Core;
    import org.opencv.core.Mat;
    import org.opencv.core.MatOfByte;
    import org.opencv.core.MatOfRect;
    import org.opencv.core.Rect;
    import org.opencv.imgcodecs.Imgcodecs;
    import org.opencv.objdetect.CascadeClassifier;
    import org.opencv.videoio.VideoCapture;
    
    public class Camera extends Application {
    
        private static final int SCENE_W = 640;
        private static final int SCENE_H = 480;
    
        CascadeClassifier faceDetector;
        VideoCapture videoCapture;
    
        Canvas canvas;
        GraphicsContext g2d;
        Stage stage;
        AnimationTimer timer;
    
        @Override
        public void start(Stage stage) {
    
            this.stage = stage;
    
            initOpenCv();
    
            canvas = new Canvas(SCENE_W, SCENE_H);
            g2d = canvas.getGraphicsContext2D();
            g2d.setStroke(Color.GREEN);
    
            Group group = new Group(canvas);
    
            Scene scene = new Scene(group, SCENE_W, SCENE_H);
    
            stage.setScene(scene);
            stage.setResizable(false);
            stage.show();
    
            timer = new AnimationTimer() {
    
                Mat mat = new Mat();
    
                @Override
                public void handle(long now) {
    
                    videoCapture.read(mat);
    
                    List<Rectangle2D> rectList = detectFaces(mat);
    
                    Image image = mat2Image(mat);
    
                    g2d.drawImage(image, 0, 0);
    
                    for (Rectangle2D rect : rectList) {
                        g2d.strokeRect(rect.getMinX(), rect.getMinY(), rect.getWidth(), rect.getHeight());
                    }
    
                }
            };
            timer.start();
    
        }
    
        public List<Rectangle2D> detectFaces(Mat mat) {
    
            MatOfRect faceDetections = new MatOfRect();
            faceDetector.detectMultiScale( mat, faceDetections);
    
            System.out.println(String.format("Detected %s faces", faceDetections.toArray().length));
    
            List<Rectangle2D> rectList = new ArrayList<>();
            for (Rect rect : faceDetections.toArray()) {
    
                int x = rect.x;
                int y = rect.y;
                int w = rect.width;
                int h = rect.height;
    
                rectList.add(new Rectangle2D(x, y, w, h));
            }
    
            return rectList;
        }
    
        private void initOpenCv() {
    
            setLibraryPath();
    
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    
            videoCapture = new VideoCapture();
            videoCapture.open(0);
    
            System.out.println("Camera open: " + videoCapture.isOpened());
    
            stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
                public void handle(WindowEvent we) {
    
                    timer.stop();
                    videoCapture.release();
    
                    System.out.println("Camera released");
    
                }
            });
    
            faceDetector = new CascadeClassifier(getOpenCvResource(getClass(), "/opencv/data/lbpcascades/lbpcascade_frontalface.xml"));
    
        }
    
        public static Image mat2Image(Mat mat) {
            MatOfByte buffer = new MatOfByte();
            Imgcodecs.imencode(".png", mat, buffer);
            return new Image(new ByteArrayInputStream(buffer.toArray()));
        }
    
        private static void setLibraryPath() {
    
            try {
    
                System.setProperty("java.library.path", "lib/x64");
    
                Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
                fieldSysPath.setAccessible(true);
                fieldSysPath.set(null, null);
    
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new RuntimeException(ex);
            }
    
        }
    
        public static String getOpenCvResource(Class<?> clazz, String path) {
            try {
                return Paths.get( clazz.getResource(path).toURI()).toString();
            } catch (URISyntaxException e) {
                throw new RuntimeException(e);
            }
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    当然,一旦你有了 JavaFX 图像,你就可以做任何你想做的事情(例如保存)。

    【讨论】:

    • 非常感谢 Roland,这是一个很好的回应。我会让你知道我是怎么过的。再次感谢
    【解决方案2】:

    对于sarxos,伪代码,我不能发布整个类:

    import com.sleepingdumpling.jvideoinput.Device;
    import com.sleepingdumpling.jvideoinput.VideoFrame;
    import com.sleepingdumpling.jvideoinput.VideoInput;
    
    Device choosenDevice;
    for (Device device : VideoInput.getVideoDevices()) {
    // select your choosenDevice webcam  here
    if (isMyWebcam(device)) {
    choosenDevice = device;
    break;
    
    }
    }
    // eg. VideoInput(640,480,25,choosenDevice );
    VideoInput videoInput = new VideoInput(frameWidth, frameHeigth,
                                    frameRate, choosenDevice );
    VideoFrame vf = null;
    while (grabFrames) {
                vf = videoInput.getNextFrame(vf);
                if (vf != null) {
                    frameReceived(vf.getRawData());
                    // or vf.getBufferedImage();
                }
    
    }
    videoInput.stopSession();
    

    【讨论】:

    • 谢谢 Krzysztof,我会试试这个方法。感谢回复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多