从实时视频设备捕获图像以供基于 Java 的应用程序使用的最佳方法是啥?
Posted
技术标签:
【中文标题】从实时视频设备捕获图像以供基于 Java 的应用程序使用的最佳方法是啥?【英文标题】:What is the best method to capture images from a live video device for use by a Java-based application?从实时视频设备捕获图像以供基于 Java 的应用程序使用的最佳方法是什么? 【发布时间】:2010-09-12 01:32:46 【问题描述】:我正在研究用于半实时检测某些场景的图像处理问题。我的目标是让实时视频以我的 Java 代码中的 Motion JPEG 帧的形式出现在我的 Java 代码中不知何故。
我对@987654321@ 很熟悉,但遗憾的是,我认为我们可以认为这是一个有效死的 API。我也熟悉Axis boxes,虽然我真的很喜欢他们的解决方案,但如果我对我的特定兴趣点提出任何批评性反馈,我将不胜感激。
为了本次讨论的目的,这就是我对“最佳”的定义:
延迟 - 如果我使用此视频流控制摄像头,我希望尽可能将往返延迟保持在 100 毫秒以下。这是从我的控制输入到我看到可见变化之间的时间来衡量的。稍后编辑:要记住的另一件事是相机控制可能是手动和自动(事件触发器)的组合。我们需要立即查看这些图片,即使高质量的 Feed 是单独存档的。 免费/开源总比不免费好。 可调整的编解码器参数 - 我需要能够针对某些情况调整编解码器。有时,高速低分辨率流实际上更容易处理。 “集成”与 Java - 将此解决方案与我的代码挂钩有多麻烦?我是否通过套接字发送数据包?点击网址?安装 Direct3D/JNI 组合? Windows / Linux / 两者? - 我更喜欢与操作系统无关的解决方案,因为我必须提供多种操作系统,但可能有一种解决方案对其中一种而言是最佳的,而对另一种则不是。注意:我知道其他图像/视频捕获编解码器,这不是这个问题的重点。由于帧精度的损失,我对流 API(例如 MPEG4)特别不感兴趣。但是,如果我的问题有提供另一个帧精确数据流的解决方案,请加入。
跟进这个问题:在这一点上,我强烈倾向于购买诸如Axis video encoders 之类的设备,而不是尝试在软件中或直接在 PC 上捕获视频。但是,如果有人有其他选择,我很乐意听到。
【问题讨论】:
【参考方案1】:这个 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();
还有来自Camera的post on viewing live video和configuration for JavaCV :
我认为这将满足您的要求。
【讨论】:
有趣 - 有没有关于图像采集卡延迟的数据? 我没有计算或找到这样的数据。但看起来不错。在此视频youtube.com/watch?v=r02no-zIBnI 中,我在 JFrame 中显示捕获的图像 (IplImage img = grabber.grab())。【参考方案2】:FMJ 绝对可以捕获视频并将其转换为 MJPEG 帧。
【讨论】:
【参考方案3】:关于JMF的死亡,你知道FMJ implementation吗?我不知道它是否称得上是“最佳”解决方案,但它可能值得加入讨论。
【讨论】:
最后一次更新似乎是很久以前的事了:sourceforge.net/project/showfiles.php?group_id=161490 自 2007 年以来已经死掉的 API 可能对我们没有帮助。不过还是谢谢。【参考方案4】:下面显示了一个使用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);
另一个example 应用多种算法进行实时视频处理。
【讨论】:
这很有趣 - 你能谈谈我上面的延迟要求吗? 延迟取决于应用程序的硬件、摄像头和视频分辨率。不过,我认为这是可行的。看看这个实时视频处理demo。它展示了这个框架的实际效果。 marvinproject.org 链接已失效。你能更新一下吗?看起来你是那个不错的图书馆的作者,所以你可能想说:) @Matthieu 感谢您的报告。【参考方案5】:这是我的 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;
【讨论】:
【参考方案6】:你看过Processing.org吗?它基本上是一个用于开发“艺术”应用程序和物理计算平台的简化应用程序框架,但它是基于 Java 的,您可以深入挖掘底层的“真正”Java。
想到的原因是有几个视频libraries 用于处理,它们基本上是 Java 组件(至少我认为它们是 - 该站点包含您可能需要的所有技术信息)。在 Eclipse IDE 中使用处理库和工具有一个tutorial。还有很多examples关于视频采集和处理的。
即使您不能直接使用这些库,Processing 也是一种用于制定算法的出色语言/环境。那里有几个很好的图像和视频捕获以及实时处理示例。
【讨论】:
以上是关于从实时视频设备捕获图像以供基于 Java 的应用程序使用的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章
如何从 android 的视频视图中显示的 ip 摄像头的流式视频中捕获图像