在Java中从网络摄像头捕获图像?


85

如何连续从摄像头捕获图像?

我想尝试对象识别(也许通过使用Java Media Framework)。

我当时正在考虑创建两个线程

一个线程:

  • 节点1:捕获实时图像
  • 节点2:将图片另存为“ 1.jpg”
  • 节点3:等待5秒
  • 节点4:重复...

其他线程:

  • 节点1:等到捕获图像
  • 节点2:使用“ 1.jpg”获取每个像素的颜色
  • 节点3:将数据保存在数组中
  • 节点4:重复...

2
这里是你的answer--的Java Swing程序捕获图片来自网络摄像头教程稍微修改就大功告成..
阿曼

Answers:


49

此JavaCV实现效果很好。

码:

import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.IplImage;

import java.io.File;

import static org.bytedeco.opencv.global.opencv_core.cvFlip;
import static org.bytedeco.opencv.helper.opencv_imgcodecs.cvSaveImage;

public class Test implements Runnable {
    final int INTERVAL = 100;///you may use interval
    CanvasFrame canvas = new CanvasFrame("Web Cam");

    public Test() {
        canvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
    }

    public void run() {

        new File("images").mkdir();

        FrameGrabber grabber = new OpenCVFrameGrabber(0); // 1 for next camera
        OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
        IplImage img;
        int i = 0;
        try {
            grabber.start();

            while (true) {
                Frame frame = grabber.grab();

                img = converter.convert(frame);

                //the grabbed frame will be flipped, re-flip to make it right
                cvFlip(img, img, 1);// l-r = 90_degrees_steps_anti_clockwise

                //save
                cvSaveImage("images" + File.separator + (i++) + "-aa.jpg", img);

                canvas.showImage(converter.convert(img));

                Thread.sleep(INTERVAL);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Test gs = new Test();
        Thread th = new Thread(gs);
        th.start();
    }
}

还有关于JavaCV的配置的帖子

您可以修改代码,并能够定期保存图像并进行所需的其余处理。


4
+1你摇滚!我一直在寻找一个很好的开源软件,并为Windows和Linux中的Webcam捕获提供JMF的受支持替代。这就像一个魅力!谢谢您:)
maple_shaft

2
对我不起作用,它说线程“主”中的异常java.lang.UnsatisfiedLinkError:C:\ Users \ steve \ AppData \ Local \ Temp \ javacpp213892357885346 \ jniopencv_core.dll:找不到依赖库
Stepan Yakovenko

这可以工作,但视频质量不如预期。请参阅我的答案以获得更好的视频输出质量。
syb0rg 2013年

感谢您的建议。我有兴趣在Windows上进行设置吗?我需要3Gb提取的zip吗?否则,我的程序在Linux上使用JavaCV可以正常工作。
Ilian Zapryanov

@StepanYakovenko您需要安装OpenCV。
Matthieu

33

不久前,我创建了通用Java库,该库可用于通过PC网络摄像头拍照。该API非常简单,没有功能过多,可以独立运行,但还支持其他网络摄像头驱动程序,例如OpenIMAJ,JMF,FMJ,LTI-CIVIL等,以及一些IP摄像机。

链接到该项目是https://github.com/sarxos/webcam-capture

示例代码(拍照并保存在test.jpg中):

Webcam webcam = Webcam.getDefault();
webcam.open();
BufferedImage image = webcam.getImage();
ImageIO.write(image, "JPG", new File("test.jpg"));

它也可以在Maven中央存储库中获得,也可以作为单独的ZIP获得,其中包括所有必需的依赖项和第三方JAR。


1
为了便于入门,非常值得一看。该代码对我来说很棒,希望您也:)
mrswadge

@Bartosz Firyn:您好,我正在使用您的API。真棒的工作人员!但现在我想知道是否支持变焦相机?如何使用此API缩放相机?
Java Man

@JavaMan,没有本地支持缩放。
Bartosz Firyn 2014年

2
@JavaMan,您可以通过设置自定义Painter实例在显示来自摄像机(WebcamPanel)的视图的面板上绘制,也可以使用WebcamImageTransformer功能直接在来自摄像机的图像上绘制。有关更多详细信息,请在Github上的“ Webcam Capture”项目页面上打开票证,因为我不想在Stack Overflow上对此进行详细解释(写的太多,注释中使用的字符太少)。该项目可以在这里找到github.com/sarxos/webcam-capture
Bartosz Firyn 2014年

1
@Elyas Hadizadeh,如果遇到问题,您可以随时在github.com/sarxos/webcam-capture上创建新的发行凭单,还可以在其中找到文档和示例。还请记住,这是相当熟悉Java的人的框架。如果您是Java新手,也有人愿意提供帮助,但是您必须自己学习基础知识。
Bartosz Firyn


5

是一个类似的问题,但给出了一些尚未接受的答案。其中之一提到FMJ是JMF的Java替代品。


5

这种使用JavaCV的gt_ebuddy的答案是错误的,但是我的视频输出的质量比他的答案高得多。我还添加了一些其他的随机改进(如倒闭程序时ESCCTRL+C被按下,并确保关闭该资源的程序使用正确)。

import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.KeyStroke;

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

public class HighRes extends JComponent implements Runnable {
    private static final long serialVersionUID = 1L;

    private static CanvasFrame frame = new CanvasFrame("Web Cam");
    private static boolean running = false;
    private static int frameWidth = 800;
    private static int frameHeight = 600;
    private static OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(0);
    private static BufferedImage bufImg;

    public HighRes()
    {
        // setup key bindings
        ActionMap actionMap = frame.getRootPane().getActionMap();
        InputMap inputMap = frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

        for (Keys direction : Keys.values())
        {
            actionMap.put(direction.getText(), new KeyBinding(direction.getText()));
            inputMap.put(direction.getKeyStroke(), direction.getText());
        }

        frame.getRootPane().setActionMap(actionMap);
        frame.getRootPane().setInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW, inputMap);

        // setup window listener for close action
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.addWindowListener(new WindowAdapter()
        {
            public void windowClosing(WindowEvent e)
            {
                stop();
            }
        });
    }

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

    @Override
    public void run()
    {
        try
        {

            grabber.setImageWidth(frameWidth);
            grabber.setImageHeight(frameHeight);
            grabber.start();
            while (running)
            {

                final IplImage cvimg = grabber.grab();
                if (cvimg != null)
                {

                    // cvFlip(cvimg, cvimg, 1); // mirror

                    // show image on window
                    bufImg = cvimg.getBufferedImage();
                    frame.showImage(bufImg);
                }
            }
            grabber.stop();
            grabber.release();
            frame.dispose();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

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

    public void stop()
    {
        running = false;
    }

    private class KeyBinding extends AbstractAction {

        private static final long serialVersionUID = 1L;

        public KeyBinding(String text)
        {
            super(text);
            putValue(ACTION_COMMAND_KEY, text);
        }

        @Override
        public void actionPerformed(ActionEvent e)
        {
            String action = e.getActionCommand();
            if (action.equals(Keys.ESCAPE.toString()) || action.equals(Keys.CTRLC.toString())) stop();
            else System.out.println("Key Binding: " + action);
        }
    }
}

enum Keys
{
    ESCAPE("Escape", KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0)),
    CTRLC("Control-C", KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK)),
    UP("Up", KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0)),
    DOWN("Down", KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0)),
    LEFT("Left", KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0)),
    RIGHT("Right", KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0));

    private String text;
    private KeyStroke keyStroke;

    Keys(String text, KeyStroke keyStroke)
    {
        this.text = text;
        this.keyStroke = keyStroke;
    }

    public String getText()
    {
        return text;
    }

    public KeyStroke getKeyStroke()
    {
        return keyStroke;
    }

    @Override
    public String toString()
    {
        return text;
    }
}


3

我已经在视频会议应用程序上使用了JMF,它在两台笔记本电脑上都能很好地工作:一台带有集成的网络摄像头,另一台带有旧的USB网络摄像头。它要求事先安装和配置JMF,但是一旦完成,您就可以很容易地通过Java代码访问硬件。


3

您可以尝试Marvin Framework。它提供了与相机配合使用的界面。此外,它还提供了一组实时视频处理功能,例如对象跟踪和过滤。

看一看!

实时视频处理演示:http :
//www.youtube.com/watch?v=D5mBt0kRYvk

您可以使用以下来源。只需每5秒使用MarvinImageIO.saveImage()保存一帧。

网络摄像头视频演示:

public class SimpleVideoTest extends JFrame implements Runnable{

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

    public SimpleVideoTest(){
        super("Simple Video Test");
        videoAdapter = new MarvinJavaCVAdapter();
        videoAdapter.connect(0);
        videoPanel = new MarvinImagePanel();
        add(videoPanel);
        new Thread(this).start();
        setSize(800,600);
        setVisible(true);
    }
    @Override
    public void run() {
        while(true){
            // Request a video frame and set into the VideoPanel
            image = videoAdapter.getFrame();
            videoPanel.setImage(image);
        }
    }
    public static void main(String[] args) {
        SimpleVideoTest t = new SimpleVideoTest();
        t.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

对于那些只想拍照的人:

WebcamPicture.java

public class WebcamPicture {
    public static void main(String[] args) {
        try{
            MarvinVideoInterface videoAdapter = new MarvinJavaCVAdapter();
            videoAdapter.connect(0);
            MarvinImage image = videoAdapter.getFrame();
            MarvinImageIO.saveImage(image, "./res/webcam_picture.jpg");
        } catch(MarvinVideoInterfaceException e){
            e.printStackTrace();
        }
    }
}

2

http://grack.com/downloads/school/enel619.10/report/java_media_framework.html

将播放器与Swing一起使用

该播放器也可以轻松地在Swing应用程序中使用。以下代码创建一个基于Swing的电视捕获程序,并将视频输出显示在整个窗口中:

import javax.media.*;
import javax.swing.*;
import java.awt.*;
import java.net.*;
import java.awt.event.*;
import javax.swing.event.*;

public class JMFTest extends JFrame {
    Player _player;
    JMFTest() {
        addWindowListener( new WindowAdapter() {
            public void windowClosing( WindowEvent e ) {
                _player.stop();
                _player.deallocate();
                _player.close();
                System.exit( 0 );
            }
        });
          setExtent( 0, 0, 320, 260 );
        JPanel panel = (JPanel)getContentPane();
        panel.setLayout( new BorderLayout() );
        String mediaFile = "vfw://1";
        try {
            MediaLocator mlr = new MediaLocator( mediaFile );
            _player = Manager.createRealizedPlayer( mlr );
            if (_player.getVisualComponent() != null)
            panel.add("Center", _player.getVisualComponent());
            if (_player.getControlPanelComponent() != null)
            panel.add("South", _player.getControlPanelComponent());
        }
        catch (Exception e) {
            System.err.println( "Got exception " + e );
        }
    }

    public static void main(String[] args) {
        JMFTest jmfTest = new JMFTest();
        jmfTest.show();
    }
}

2

我使用了Webcam Capture API ...可以从此http://webcam-capture.sarxos.pl/下载

        webcam = Webcam.getDefault();
        webcam.open();

        if (webcam.isOpen()) { //if web cam open 
            BufferedImage image = webcam.getImage();
            JLabel imageLbl = new JLabel();
            imageLbl.setSize(640, 480);             //show captured image
            imageLbl.setIcon(new ImageIcon(image));

            int showConfirmDialog = JOptionPane.showConfirmDialog(null, imageLbl, "Image Viewer", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, new ImageIcon(""));

            if (showConfirmDialog == JOptionPane.YES_OPTION) {
                JFileChooser chooser = new JFileChooser();
                chooser.setDialogTitle("Save Image");
                chooser.setFileFilter(new FileNameExtensionFilter("IMAGES ONLY", "png", "jpeg", "jpg")); //this file extentions are shown
                int showSaveDialog = chooser.showSaveDialog(this);
                if (showSaveDialog == 0) {                  //if pressed 'Save' button
                    String filePath = chooser.getCurrentDirectory().toString().replace("\\", "/");
                    String fileName = chooser.getSelectedFile().getName(); //get user entered file name to save
                    ImageIO.write(image, "PNG", new File(filePath + "/" + fileName + ".png"));

                }
            }
        }

您应该提供一些解释以及代码
fen1x

1
谢谢。它轻巧,而javacv则对我有用。
Lucke

1

Java通常不喜欢访问硬件,因此,正如goldenmean所说,您将需要某种驱动程序。我已经在笔记本电脑上找到了捕捉图片的命令行程序来完成此操作。然后,这与Goldenmean解释的相同;您可以从Java程序中的takepicture()例程中运行命令行程序,其余代码也可以相同地运行。

除了将像素值读取到数组中以外,将文件保存到BMP(已经差不多是该格式),然后再使用标准Java图像库,可能会更好。

使用命令行程序会给您的程序增加一个依赖性,并使它的可移植性降低,但是网络摄像头也是如此,对吗?


1

使用FMJ推荐用于多媒体相对Java应用程序。


0

我相信网络摄像头随附的网络摄像头应用程序软件,或者您本机的Windows网络摄像头软件可以在打开网络摄像头后(例如,如果需要外部电源)以批处理脚本(Windows / DOS脚本)运行供应)。在bacth脚本中,您可以添加适当的延迟以在特定时间段后捕获。并继续循环执行捕获命令。

我想这应该是可能的

-广告


0

处理过程中有一个很好的接口,这是一种为图形设计的pidgin java。它被用于某些图像识别工作,例如该链接。

根据您需要的内容,您也许可以加载在Java中使用的视频库,或者如果您只是在玩它,则可以使用处理本身来获取它。


0

FMJ可以做到这一点,它使用的支持库LTI-CIVIL也可以做到这一点。两者都在sourceforge上。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.