使用Java中的网络摄像头捕获视频 [英] Capture video using webcam in Java

查看:3412
本文介绍了使用Java中的网络摄像头捕获视频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从java应用程序中捕获视频屏幕截图。我已经下载了 sarxos / webcam-capture 库。我已将可执行jar添加到我的项目中。这有点乱。我想从我创建的简单javafx接口捕获视频。问题是在安装了lib和slf4后,它还需要安装xuggle。我在路径中添加了xuggle,我的代码如下:

I am trying to capture video screenshot from a java application. I have donwloaded the sarxos/webcam-capture library. I have add to my project the executable jar. It is a little bit mess. I want to capture video from a simple javafx interface that I have created. The issue is that after installing the lib and slf4 then it required to install also xuggle. I add xuggle in the path and my code is the following:

File file = new File("output.ts");

IMediaWriter writer = ToolFactory.makeWriter(file.getName());
Dimension size = WebcamResolution.QVGA.getSize();

writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, size.width, size.height);

Webcam webcam = Webcam.getDefault();
webcam.setViewSize(size);
webcam.open(true);

long start = System.currentTimeMillis();

for (int i = 0; i < 50; i++) {

    System.out.println("Capture frame " + i);

    BufferedImage image = ConverterFactory.convertToType(webcam.getImage(), BufferedImage.TYPE_3BYTE_BGR);
    IConverter converter = ConverterFactory.createConverter(image, IPixelFormat.Type.YUV420P);

    IVideoPicture frame = converter.toPicture(image, (System.currentTimeMillis() - start) * 1000);
    frame.setKeyFrame(i == 0);
    frame.setQuality(0);

    writer.encodeVideo(0, frame);

    // 10 FPS
    Thread.sleep(100);
}

writer.close();

System.out.println("Video recorded in file: " + file.getAbsolutePath());

但是我收到以下信息:

Caused by: java.lang.UnsatisfiedLinkError: no xuggle-ferry in java.library.path

EDIT2 我也尝试过jxcapture库。我在项目中添加了所有必需的库,我运行以下代码:在这里输入链接描述,代码工作正常我设法存储视频,但最后我收到以下错误:

EDIT2 I also tried the jxcapture library. I add in my project all the necessary libs I run the following code: enter link description here, the code worked fine I manage to store the video, however in the end I am receiving the following error:


8614 [JNIWrapper.ShutdownHook]错误com.jniwrapper.NativeResourceCollector -
com.jniwrapper.FunctionExecutionException:回调参数类型或其计数不正确
at com.jniwrapper.Function.invokeVirtualFunc(Native Method)

8614 [JNIWrapper.ShutdownHook] ERROR com.jniwrapper.NativeResourceCollector - com.jniwrapper.FunctionExecutionException: Callback parameter types or their count are not correct at com.jniwrapper.Function.invokeVirtualFunc(Native Method)

知道这个错误是什么意思吗?什么是JNIWrapper.ShutdownHook?我尝试了3台不同的机器中的代码,这只发生在其中一台机器上?如何处理此异常?

Any idea what this error is about?? What is JNIWrapper.ShutdownHook? I tried the code in 3 different machines and this is happened just to one of them? How can I handle this exception?

EDIT3:我尝试了@whitesite提案EDIT3。 gui开始了,我有两个按钮启动和停止启动按钮打开相机,当我试图停止时,我收到以下内容:

I tried @whitesite proposal EDIT3. The gui started and I have two buttons start and stop the start button opened the camera and when I tried to stop I received the following:


java.lang.NullPointerException:参数0的指针地址为NULL。
at org.bytedeco.javacpp.opencv_videoio $ VideoWriter.write(Native Method)
at org.bytedeco.javacv.OpenCVFrameRecorder.record(OpenCVFrameRecorder.java:105)
at Test1.lambda $ 0 (Test1.java:52)
at java.lang.Thread.run(Unknown Source)

java.lang.NullPointerException: Pointer address of argument 0 is NULL. at org.bytedeco.javacpp.opencv_videoio$VideoWriter.write(Native Method) at org.bytedeco.javacv.OpenCVFrameRecorder.record(OpenCVFrameRecorder.java:105) at Test1.lambda$0(Test1.java:52) at java.lang.Thread.run(Unknown Source)


推荐答案

好的,这就是我使用这个 JavaCV库及其示例所得到的:

Ok, that's what I got using this JavaCV library and their examples:

public class Test extends Application {

public void start(Stage primaryStage) throws Exception {

    OpenCVFrameGrabber capture = OpenCVFrameGrabber.createDefault(0);
    capture.start();

    OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
    Java2DFrameConverter javaConverter = new Java2DFrameConverter();

    VBox root = new VBox();
    Canvas canvas = new Canvas();
    canvas.setHeight(capture.getImageHeight());
    canvas.setWidth(capture.getImageWidth());
    root.getChildren().add(canvas);
    Scene scene = new Scene(root, capture.getImageWidth(), capture.getImageHeight());

    primaryStage.setTitle("Live video");
    primaryStage.setScene(scene);
    primaryStage.show();

    Thread videoProcessor = new Thread(() -> {
        File output = new File("C:/Work/test.avi");
        OpenCVFrameRecorder recorder = new OpenCVFrameRecorder(output, capture.getImageWidth(), capture.getImageHeight());
        try {
            recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G'));
            recorder.start();
            while (true) {
                if(Thread.currentThread().isInterrupted()){
                    break;
                }
                Frame frame = capture.grab();
                Platform.runLater(()->{
                    BufferedImage image = javaConverter.getBufferedImage(frame, 1.0, false, null);
                    canvas.getGraphicsContext2D().drawImage(SwingFXUtils.toFXImage(image, null),0,0);
                });
                recorder.record(frame);
            }
            recorder.stop();
            capture.release();
            recorder.release();
        } catch (Exception e) {
            e.printStackTrace();
        }
    });

    primaryStage.setOnCloseRequest(e->{
        videoProcessor.interrupt();
    });

    videoProcessor.start();

}

public static void main(String[] args) throws Exception {
    launch(args);
}

}

它从网络摄像头捕获视频实时翻译并同时写入文件。您需要使用maven或手动安装以及来自二进制zip存档的所有jar来在classpath中包含它们的库。也许你不需要所有这些,但我没有深入挖掘。

您可以使用设置并调查示例和来源。从我所看到的它是非常强大的库。

编辑

只是视频处理部分:

It captures video from web cam and translates it live and in the same time writes to file. You need to include their library in classpath using maven or manual installation and also all the jars from binary zip archive. Maybe you don't need all of them, but I did't dig deep.
You can play with settings and investigate examples and sources. From what I've seen it's pretty powerful library.
Edit
Just video processing part:

Thread videoProcessor = new Thread(() -> {
        OpenCVFrameGrabber capture = null;
        FrameRecorder recorder = null;
        try {

            File output = new File("C:/Work/test2.avi");
            capture = OpenCVFrameGrabber.createDefault(0);
            capture.start();
            recorder = FrameRecorder.createDefault(output, capture.getImageWidth(), capture.getImageHeight());
            recorder.setFrameRate(8);
            recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G'));
            recorder.start();
            long l = System.currentTimeMillis();
            while (true) {
                if(Thread.currentThread().isInterrupted()){
                    break;
                }
                recorder.record(capture.grab());

            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                recorder.stop();
                capture.release();
                recorder.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });

您需要启动流程 videoProcessor.start()某处然后中断它以停止录制 videoProcessor.interrupt()。您可能还需要设置适当的刻录机帧速率以将其调整为相机fps。

编辑2

输出可用设备的代码:

You need to start process videoProcessor.start() somewhere and then interrupt it to stop recording videoProcessor.interrupt(). You might also need to set proper recorder frame rate to adjust it to your camera fps.
Edit 2
Code to output available devices:

int n = org.bytedeco.javacpp.videoInputLib.videoInput.listDevices();
for (int i = 0; i < n; i++) {
    System.out.println(i + " = " + org.bytedeco.javacpp.videoInputLib.videoInput.getDeviceName(i));
}  

编辑3

如果摄像头捕获工作,你可以使用它来捕获图像并使用javaCV将这些图像记录到视频文件中(就像你在问题中的exapmle,只是javaCV而不是xuggler)。这是一个小型的javafx应用程序,它有两个按钮:'Start'启动videoProcessing线程捕获视频,'Stop'中断此线程:

Edit 3
If webcam-capture works, than you can use it to capture images and use javaCV to record these images into videofile (pretty much like exapmle in youe question, just javaCV instead of xuggler). This is a small javafx app, which has two buttons: 'Start' starts the videoProcessing thread to capture video and 'Stop' interrupts this thread:

import com.github.sarxos.webcam.Webcam;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.bytedeco.javacpp.opencv_videoio;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameRecorder;


import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.io.File;

public class Test1 extends Application {

public void start(Stage primaryStage) throws Exception {

    final double FPS = 25;
    final int WIDTH = 640;
    final int HEIGHT = 480;
    Webcam webcam = Webcam.getDefault();
    webcam.setViewSize(new Dimension(WIDTH, HEIGHT));

    Java2DFrameConverter javaConverter = new Java2DFrameConverter();

    VBox root = new VBox();
    Button b1 = new Button("Start");
    Button b2 = new Button("Stop");

    root.getChildren().addAll(b1, b2);
    Scene scene = new Scene(root, 300,200);
    primaryStage.setTitle("Test");
    primaryStage.setScene(scene);

    Runnable r = () -> {
        File output = new File("C:/Work/test.avi");
        OpenCVFrameRecorder recorder = new OpenCVFrameRecorder(output, WIDTH, HEIGHT);
        recorder.setFrameRate(FPS);
        try {
            recorder.setVideoCodec(opencv_videoio.CV_FOURCC((byte) 'M', (byte) 'J', (byte) 'P', (byte) 'G'));
            recorder.start();
            webcam.open();
            while (true) {
                if(Thread.currentThread().isInterrupted()){
                    break;
                }
                BufferedImage image = webcam.getImage();
                recorder.record(javaConverter.getFrame(image));
                try {
                    Thread.sleep(1000 / (long)FPS);
                } catch (InterruptedException ie) {
                    break;
                }
            }
            recorder.stop();
            recorder.release();
            webcam.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    };

    b1.setOnAction(e->{
        Thread t = new Thread(r);
        t.start();
        b2.setOnAction(e2->t.interrupt());
    });

    primaryStage.show();
}

public static void main(String[] args) throws Exception {
    launch(args);
}

}

这篇关于使用Java中的网络摄像头捕获视频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆