จับภาพจากเว็บแคมใน Java?


85

ฉันจะจับภาพจากเว็บแคมอย่างต่อเนื่องได้อย่างไร?

ฉันต้องการทดลองเกี่ยวกับการจดจำวัตถุ (โดยอาจใช้ java media framework)

ฉันคิดจะสร้างสองกระทู้

หนึ่งหัวข้อ:

  • โหนด 1: จับภาพสด
  • โหนด 2: บันทึกรูปภาพเป็น "1.jpg"
  • โหนด 3: รอ 5 วินาที
  • โหนด 4: ทำซ้ำ ...

หัวข้ออื่น ๆ :

  • โหนด 1: รอจนกว่าภาพจะถูกจับ
  • โหนด 2: การใช้ "1.jpg" รับสีจากทุกพิกเกิล
  • โหนด 3: บันทึกข้อมูลในอาร์เรย์
  • โหนด 4: ทำซ้ำ ...

2
นี่คือคำตอบของคุณ - โปรแกรม Java Swing สำหรับจับภาพจากเว็บแคมสอนแก้ไขเล็กน้อยแล้วเสร็จ ..
Aman

คำตอบ:


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 คุณร็อค! ฉันกำลังมองหาโอเพ่นซอร์สที่ดีและรองรับทางเลือกอื่นแทน JMF สำหรับการจับภาพเว็บแคมทั้งใน Windows และ Linux งานนี้เหมือนมีเสน่ห์! ขอบคุณ :)
maple_shaft

2
ไม่ได้ผลสำหรับฉันมันบอกว่า Exception ในเธรด "main" java.lang.Uns SatisfiedLinkError: C: \ Users \ steve \ AppData \ Local \ Temp \ javacpp213892357885346 \ jniopencv_core.dll: ไม่พบไลบรารีที่พึ่งพา
Stepan Yakovenko

วิธีนี้จะได้ผล แต่คุณภาพของวิดีโอไม่ดีเท่าที่ควร ดูคำตอบของฉันสำหรับคุณภาพเอาต์พุตวิดีโอที่ดีขึ้น
syb0rg

ขอบคุณสำหรับข้อเสนอแนะ ฉันสนใจวิธีตั้งค่าบน Windows หรือไม่? ฉันต้องการซิปที่แตกไฟล์ 3Gb หรือไม่? มิฉะนั้นโปรแกรมของฉันการใช้ JavaCV บน Linux ก็ใช้ได้ดี
Ilian Zapryanov

@StepanYakovenko คุณต้องติดตั้ง OpenCV
Matthieu

33

เมื่อไม่นานมานี้ฉันได้สร้างไลบรารี Java ทั่วไปซึ่งสามารถใช้ถ่ายภาพด้วยเว็บแคมของพีซี 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 Central Repository หรือเป็น ZIP แยกต่างหากซึ่งรวมถึงการอ้างอิงที่จำเป็นทั้งหมดและ JAR ของบุคคลที่สาม


1
เพื่อความสะดวกในการเริ่มต้นสิ่งนี้ควรค่าแก่การดู รหัสใช้งานได้ดีสำหรับฉันหวังว่าคุณจะเช่นกัน :)
mrswadge

@Bartosz Firyn: สวัสดีฉันกำลังทำงานกับ API ของคุณ สุดยอดฝีมือ! แต่ตอนนี้อยากรู้ว่ารองรับการซูมกล้องหรือเปล่า? วิธีซูมกล้องโดยใช้ API นี้
Java Man

@JavaMan ไม่มีการรองรับการซูมแบบเนทีฟ
Bartosz Firyn

2
@JavaMan คุณสามารถวาดบนแผงที่แสดงมุมมองจากกล้อง (WebcamPanel) โดยการตั้งค่าอินสแตนซ์ Painter ที่คุณกำหนดเองหรือโดยตรงบนภาพที่มาจากกล้องโดยใช้คุณสมบัติ WebcamImageTransformer สำหรับรายละเอียดเพิ่มเติมโปรดเปิดตั๋วในหน้าโครงการ Webcam Capture บน Github เนื่องจากฉันไม่ต้องการอธิบายรายละเอียดใน Stack Overflow ที่นี่ (เขียนมากเกินไปและมีอักขระน้อยเกินไปที่จะใช้ในความคิดเห็น) สามารถดูโครงการได้ที่นี่github.com/sarxos/webcam-capture
Bartosz Firyn

1
@Elyas Hadizadeh ในกรณีที่มีปัญหาคุณสามารถสร้างตั๋วปัญหาใหม่ได้ตลอดเวลาที่github.com/sarxos/webcam-captureซึ่งคุณสามารถค้นหาเอกสารและตัวอย่างได้ โปรดทราบด้วยว่านี่เป็นกรอบสำหรับผู้ที่ค่อนข้างคุ้นเคยกับ Java ในกรณีที่คุณเป็น Java ใหม่ก็มีคนยินดีช่วยเหลือเช่นกัน แต่คุณต้องเรียนรู้พื้นฐานด้วยตัวคุณเอง
Bartosz Firyn


5

นี่คือคำถามที่คล้ายกันกับคำตอบบางส่วนที่ยังไม่เป็นที่ยอมรับ หนึ่งในนั้นกล่าวถึงFMJเป็นทางเลือก java สำหรับ JMF


5

คำตอบแบบนี้ออกไปจาก gt_ebuddy โดยใช้ JavaCV แต่เอาต์พุตวิดีโอของฉันมีคุณภาพสูงกว่าคำตอบของเขา ฉันยังได้เพิ่มการปรับปรุงแบบสุ่มอื่น ๆ (เช่นปิดโปรแกรมเมื่อESCและCTRL+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

คุณสามารถลองมาร์วินกรอบ มีอินเทอร์เฟซสำหรับทำงานร่วมกับกล้องถ่ายรูป นอกจากนี้ยังมีชุดคุณสมบัติการประมวลผลวิดีโอแบบเรียลไทม์เช่นการติดตามวัตถุและการกรอง

ลองดูสิ!

การสาธิตการประมวลผลวิดีโอแบบเรียลไทม์:
http://www.youtube.com/watch?v=D5mBt0kRYvk

คุณสามารถใช้แหล่งข้อมูลด้านล่าง เพียงบันทึกเฟรมโดยใช้MarvinImageIO.saveImage ()ทุกๆ 5 วินาที

การสาธิตวิดีโอเว็บแคม:

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 เช่นกัน รหัสต่อไปนี้จะสร้างโปรแกรมจับภาพทีวีแบบสวิงพร้อมเอาต์พุตวิดีโอที่แสดงในหน้าต่างทั้งหมด:

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 ซึ่งเกือบจะเป็นรูปแบบนั้นอยู่แล้วจากนั้นใช้ไลบรารีรูปภาพจาวามาตรฐาน

การใช้โปรแกรมบรรทัดคำสั่งเพิ่มการพึ่งพาโปรแกรมของคุณและทำให้พกพาได้น้อยลง แต่เว็บแคมก็เช่นกันใช่ไหม?



0

ฉันเชื่อว่าซอฟต์แวร์แอปพลิเคชันเว็บแคมที่มาพร้อมกับเว็บแคมหรือซอฟต์แวร์เว็บแคมของ Windows ของคุณสามารถเรียกใช้ในสคริปต์แบตช์ (สคริปต์ windows / dos) หลังจากเปิดเว็บแคม (เช่นหากต้องการใช้พลังงานจากภายนอก จัดหา). ในสคริปต์ bacth คุณสามารถเพิ่มการหน่วงเวลาที่เหมาะสมเพื่อจับภาพหลังจากช่วงเวลาหนึ่ง และดำเนินการคำสั่ง capture ต่อไปแบบวนซ้ำ

ฉันเดาว่าน่าจะเป็นไปได้

-AD


0

มีอินเทอร์เฟซที่ดีมากสำหรับสิ่งนี้ในการประมวลผลซึ่งเป็นพิดจิ้น java ที่ออกแบบมาสำหรับกราฟิก มันถูกนำไปใช้ในงานจดจำภาพบางอย่างเช่นลิงก์นั้น

ขึ้นอยู่กับสิ่งที่คุณต้องการคุณอาจสามารถโหลดไลบรารีวิดีโอที่ใช้ใน java ได้หรือถ้าคุณแค่เล่นกับมันคุณอาจสามารถรับได้โดยใช้การประมวลผลเอง


0

FMJ สามารถทำสิ่งนี้ได้เช่นเดียวกับไลบรารีที่รองรับที่ใช้ LTI-CIVIL ทั้งสองอยู่ใน sourceforge


0

ลองใช้ JMyron วิธีการใช้เว็บแคมใช้ Java ฉันคิดว่าการใช้ JMyron เป็นวิธีที่ง่ายที่สุดในการเข้าถึงเว็บแคมโดยใช้ java ฉันพยายามใช้กับโปรเซสเซอร์ 64 บิต แต่เกิดข้อผิดพลาด แม้ว่าจะใช้งานได้ดีกับโปรเซสเซอร์ 32 บิต

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.