从实时视频设备中捕获图像以供基于Java的应用程序使用的最佳方法是什么?

25
我正在研究一种半实时检测特定情景的图像处理问题。我的目标是以某种方式将实时视频作为Motion JPEG帧传递到我的Java代码中。
我熟悉Java媒体框架,但不幸的是,我认为它是一个已经死亡的API。我也熟悉Axis boxes,虽然我非常喜欢他们的解决方案,但我希望能够得到有关我感兴趣的具体要点的任何批判性反馈。
以下是我在本次讨论中定义“最佳”的方式:
  • 延迟 - 如果我使用这个视频流控制相机,希望往返延迟时间尽可能少于100毫秒。这是指从我的控制输入到我看到可见变化的时间。编辑后补充:需要注意的另一件事是相机控制可能是手动和自动(事件触发)的组合。即使高质量的视频流被单独存档,我们也需要立即看到这些图片。
  • 成本 - 免费/开源比非免费更好。
  • 可调节编解码器参数 - 我需要能够为特定情况调整编解码器。有时,高速低分辨率的流实际上更容易处理。
  • "集成"Java - 将此解决方案与我的代码连接起来需要多大麻烦?我是通过套接字发送数据包吗?还是访问URL?还是安装Direct3D/JNI组合?
  • Windows/Linux/两者都支持? - 我希望有一个操作系统不可知的解决方案,因为我必须交付给几种不同的操作系统,但可能有一种解决方案对其中一种操作系统最优。

注意:我知道其他图像/视频捕获编解码器,但这不是本问题的重点。由于丢失帧的精度,我特别不感兴趣流API(例如MPEG4)。但是,如果有一个解决方案可以提供另一个帧精确的数据流,请加入讨论。

针对这个问题的后续:目前,我强烈倾向于购买像Axis视频编码器这样的电器,而不是尝试直接在软件或PC上捕获视频。然而,如果有其他选择,我很想听听它们。

6个回答

7
这个JavaCV实现很好。 代码:
import com.googlecode.javacv.OpenCVFrameGrabber;

import com.googlecode.javacv.cpp.opencv_core.IplImage;
import static com.googlecode.javacv.cpp.opencv_highgui.*;

public class CaptureImage {
    private static void captureFrame() {
        // 0-default camera, 1 - next...so on
        final OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
        try {
            grabber.start();
            IplImage img = grabber.grab();
            if (img != null) {
                cvSaveImage("capture.jpg", img);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        captureFrame();
    }
}

还有一篇有关从摄像头查看实时视频的文章,以及JavaCV的配置:

我认为这将满足您的要求。


有趣 - 是否有关于帧抓取器延迟的数据可用? - Bob Cross
我还没有计算或找到这样的数据,但看起来不错。在这个视频http://www.youtube.com/watch?v=r02no-zIBnI中,我正在JFrame中显示捕获的图像(IplImage img = grabber.grab())。 - gtiwari333

3

FMJ可以轻松捕获视频并将其转换为MJPEG帧。


2
关于JMF的停用,你是否知道FMJ实现?我不知道它是否符合“最佳”解决方案,但是将其加入讨论可能是值得的。

最后一次更新似乎是相当久以前了:http://sourceforge.net/project/showfiles.php?group_id=161490 自从2007年以来就已经死亡的API可能不会对我们有所帮助。无论如何,还是谢谢。 - Bob Cross

1
以下是使用Marvin Framework的非常简单的实现。使用Marvin,您可以轻松地添加实时视频处理。
import javax.swing.JFrame;
import marvin.gui.MarvinImagePanel;
import marvin.image.MarvinImage;
import marvin.video.MarvinJavaCVAdapter;
import marvin.video.MarvinVideoInterface;

public class SimpleVideoTest extends JFrame implements Runnable{

    private MarvinVideoInterface    videoAdapter;
    private MarvinImage             image;
    private MarvinImagePanel        videoPanel;

    public SimpleVideoTest(){
        super("Simple Video Test");

        // Create the VideoAdapter and connect to the camera
        videoAdapter = new MarvinJavaCVAdapter();
        videoAdapter.connect(0);

        // Create VideoPanel
        videoPanel = new MarvinImagePanel();
        add(videoPanel);

        // Start the thread for requesting the video frames 
        new Thread(this).start();

        setSize(800,600);
        setVisible(true);
    }

    public static void main(String[] args) {
        SimpleVideoTest t = new SimpleVideoTest();
        t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void run() {
        while(true){
            // Request a video frame and set into the VideoPanel
            image = videoAdapter.getFrame();
            videoPanel.setImage(image);
        }
    }
}

另一个示例,应用多种算法进行实时视频处理。


这很有趣 - 你能谈谈我上面的延迟要求吗? - Bob Cross
延迟将取决于您的应用程序硬件、相机和视频分辨率。不过,我认为这是可行的。请看一下这个实时视频处理演示。它展示了这个框架的实际效果。 - Gabriel Archanjo
marvinproject.org的链接已经失效了,你能否更新一下呢?看起来你是那个不错库的作者,所以你可能想要说一下 :) - Matthieu
@Matthieu 感谢您的报告。 - Gabriel Archanjo

0

这是我的JavaCV实现,具有高分辨率视频输出,并且与其他解决方案相比没有明显的帧速率下降(只有当我的网络摄像头重新对焦时,我才会注意到轻微的下降,但仅持续片刻)。

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

import javax.swing.JFrame;

import com.googlecode.javacv.CanvasFrame;
import com.googlecode.javacv.OpenCVFrameGrabber;
import com.googlecode.javacv.OpenCVFrameRecorder;
import com.googlecode.javacv.cpp.opencv_core.IplImage;

public class Webcam implements Runnable {

    IplImage image;
    static CanvasFrame frame = new CanvasFrame("Web Cam");
    public static boolean running = false;

    public Webcam()
    {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void run()
    {
        try
        {
            grabber.setImageWidth(800);
            grabber.setImageHeight(600);
            grabber.start();
            while (running)
            {
                IplImage cvimg = grabber.grab();
                BufferedImage image;
                if (cvimg != null)
                {
                    // opencv_core.cvFlip(cvimg, cvimg, 1); // mirror
                    // show image on window
                    image = cvimg.getBufferedImage();
                    frame.showImage(image);
                }
            }
            grabber.stop();
            frame.dispose();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    public static void main(String... args)
    {
        Webcam webcam = new Webcam();
        webcam.start();
    }

    public void start()
    {
        new Thread(this).start();
        running = true;
    }

    public void stop()
    {
        running = false;
    }
}

-1

你有没有看过Processing.org?它基本上是一个简化的应用程序框架,用于开发“艺术”应用和物理计算平台,但它是基于Java的,你可以深入到“真正”的Java底层。

它让我想起来的原因是,Processing有几个视频,基本上是Java组件(至少我认为是 - 网站上有你可能需要的所有技术信息)。有一个教程介绍如何在Eclipse IDE中使用Processing库和工具。还有许多关于视频捕获和处理的示例

即使你不能直接使用这些库,Processing也是一个很好的语言/环境来解决算法问题。那里有几个很好的图像和视频捕获以及实时处理的示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接