Catturare l'immagine dalla webcam in Java?


85

Come posso acquisire continuamente immagini da una webcam?

Voglio sperimentare con il riconoscimento degli oggetti (magari usando java media framework).

Stavo pensando di creare due thread

un filo:

  • Nodo 1: cattura l'immagine dal vivo
  • Nodo 2: salva immagine come "1.jpg"
  • Nodo 3: attendere 5 secondi
  • Nodo 4: ripeti ...

altro thread:

  • Nodo 1: attendere che l'immagine venga acquisita
  • Nodo 2: usando "1.jpg" ottieni i colori da ogni pixle
  • Nodo 3: salva i dati in array
  • Nodo 4: ripeti ...

2
Ecco la tua risposta - Programma Java Swing per acquisire immagini dal tutorial della webcam Modificalo leggermente e il gioco è fatto ..
Aman

Risposte:


49

Questa implementazione JavaCV funziona bene.

Codice:

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();
    }
}

C'è anche un post sulla configurazione per JavaCV

È possibile modificare i codici ed essere in grado di salvare le immagini a intervalli regolari e fare il resto dell'elaborazione desiderata.


4
+1 Sei forte! Stavo cercando una buona alternativa open source e supportata a JMF per l'acquisizione di webcam sia in Windows che in Linux. Funziona a meraviglia! Grazie :)
maple_shaft

2
Non funziona per me, dice Eccezione nel thread "main" java.lang.UnsatisfiedLinkError: C: \ Users \ steve \ AppData \ Local \ Temp \ javacpp213892357885346 \ jniopencv_core.dll: Impossibile trovare le librerie dipendenti
Stepan Yakovenko

Funzionerà, ma la qualità del video non è buona come dovrebbe essere. Vedi la mia risposta per una migliore qualità dell'output video.
syb0rg

Grazie per il suggerimento. Mi interessa come impostarlo su Windows? Ho bisogno della zip estratta 3Gb? Altrimenti il ​​mio programma, usando JavaCV su Linux, funziona bene.
Ilian Zapryanov

@StepanYakovenko hai bisogno di OpenCV installato.
Matthieu

33

Qualche tempo fa ho creato una libreria Java generica che può essere utilizzata per scattare foto con una webcam per PC. L'API è molto semplice, non sovraccarica, può funzionare da sola, ma supporta anche driver webcam aggiuntivi come OpenIMAJ, JMF, FMJ, LTI-CIVIL, ecc. E alcune telecamere IP.

Il collegamento al progetto è https://github.com/sarxos/webcam-capture

Codice di esempio (scatta una foto e salva in test.jpg):

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

È anche disponibile in Maven Central Repository o come ZIP separato che include tutte le dipendenze richieste e JAR di terze parti.


1
Per facilitare l'inizio, vale la pena dare un'occhiata. Il codice ha funzionato alla grande per me, spero anche tu :)
mrswadge

@ Bartosz Firyn: ciao sto lavorando con la tua API. lavoro fantastico! ma ora voglio sapere se lo zoom in fotocamera è supportato o no? come zoomare la fotocamera utilizzando questa API?
Java Man

@JavaMan, non c'è supporto nativo per lo zoom.
Bartosz Firyn

2
@JavaMan, puoi disegnare sul pannello che mostra la vista dalla telecamera (WebcamPanel) impostando la tua istanza Painter personalizzata, o direttamente sull'immagine che proviene dalla telecamera usando la funzione WebcamImageTransformer. Per maggiori dettagli si prega di aprire il ticket nella pagina del progetto Webcam Capture su Github poiché non voglio spiegarlo in dettaglio qui su Stack Overflow (troppo da scrivere e troppo pochi caratteri da usare nei commenti). Il progetto può essere trovato qui github.com/sarxos/webcam-capture
Bartosz Firyn

1
@Elyas Hadizadeh, in caso di problemi puoi sempre creare un nuovo ticket di emissione su github.com/sarxos/webcam-capture dove puoi anche trovare documentazione ed esempi. Tieni anche presente che questo è un framework per persone che hanno familiarità con Java. Nel caso tu sia un novellino di Java, ci sono anche persone disposte ad aiutarti, ma devi imparare le basi da solo.
Bartosz Firyn


5

Ecco una domanda simile con alcune risposte - ma non accettate. Uno di loro menziona FMJ come alternativa java a JMF.


5

Questo tipo di risposta di gt_ebuddy utilizza JavaCV, ma il mio output video ha una qualità molto superiore rispetto alla sua risposta. Ho anche aggiunto alcuni altri miglioramenti casuali (come ad esempio la chiusura del programma quando ESCe CTRL+Cvengono premuti, e fare in modo di chiudere le risorse gli usi programma in modo corretto).

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

Ho utilizzato JMF su un'applicazione di videoconferenza e ha funzionato bene su due laptop: uno con webcam integrata e un altro con una vecchia webcam USB. Richiede che JMF sia installato e configurato in anticipo, ma una volta terminato è possibile accedere all'hardware tramite codice Java abbastanza facilmente.


3

Puoi provare Marvin Framework . Fornisce un'interfaccia per lavorare con le telecamere. Inoltre, fornisce anche una serie di funzioni di elaborazione video in tempo reale, come il monitoraggio e il filtraggio degli oggetti.

Guarda!

Demo di elaborazione video in tempo reale:
http://www.youtube.com/watch?v=D5mBt0kRYvk

Puoi usare la fonte qui sotto. Basta salvare un frame usando MarvinImageIO.saveImage () ogni 5 secondi.

Demo video webcam:

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);
    }
}

Per coloro che vogliono solo scattare una singola foto:

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

Utilizzo del lettore con Swing

Il Player può essere facilmente utilizzato anche in un'applicazione Swing. Il codice seguente crea un programma di acquisizione TV basato su Swing con l'uscita video visualizzata nell'intera finestra:

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

Ho usato l'API di acquisizione della webcam ... puoi scaricare da questo 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"));

                }
            }
        }

Dovresti fornire alcune spiegazioni insieme al codice
fen1x

1
Grazie. è leggero e invece javacv questo funziona per me.
Lucke

1

A Java di solito non piace accedere all'hardware, quindi avrai bisogno di un programma driver di qualche tipo, come ha detto goldenmean. L'ho fatto sul mio laptop trovando un programma a riga di comando che scatta un'immagine. Quindi è la stessa spiegazione di Goldenmean; esegui il programma a riga di comando dal tuo programma java nella routine takepicture () e il resto del codice viene eseguito allo stesso modo.

Fatta eccezione per la parte relativa alla lettura dei valori dei pixel in un array, potrebbe essere meglio salvare il file in BMP, che è già quasi quel formato, quindi utilizzare le librerie di immagini java standard su di esso.

L'uso di un programma a riga di comando aggiunge una dipendenza al tuo programma e lo rende meno portabile, ma lo era anche la webcam, giusto?


1

Consiglia di utilizzare FMJ per l'app Java multimediale relativa.


0

Credo che il software applicativo web-cam fornito con la web-cam, o il software nativo per webcam di Windows possa essere eseguito in uno script batch (script windows / dos) dopo aver acceso la web cam (cioè se necessita di un'alimentazione esterna fornitura). Nello script bacth, puoi aggiungere un ritardo appropriato per l'acquisizione dopo un certo periodo di tempo. E continua a eseguire il comando di acquisizione in loop.

Immagino che questo dovrebbe essere possibile

-ANNO DOMINI


0

C'è un'interfaccia molto carina per questo in elaborazione , che è una specie di java pidgin progettato per la grafica. Viene utilizzato in alcuni lavori di riconoscimento delle immagini, come quel collegamento.

A seconda di ciò di cui hai bisogno, potresti essere in grado di caricare la libreria video che è usata lì in java, o se stai solo giocando con essa potresti essere in grado di ottenere usando l'elaborazione stessa.


0

FMJ può farlo, così come la libreria di supporto che utilizza, LTI-CIVIL. Entrambi sono su Sourceforge.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.