Przechwytywanie obrazu z kamery internetowej w Javie?


85

Jak mogę w sposób ciągły przechwytywać obrazy z kamery internetowej?

Chcę poeksperymentować z rozpoznawaniem obiektów (być może przy użyciu środowiska java Media).

Myślałem o stworzeniu dwóch wątków

jeden wątek:

  • Węzeł 1: przechwytywanie obrazu na żywo
  • Węzeł 2: zapisz obraz jako „1.jpg”
  • Węzeł 3: poczekaj 5 sekund
  • Węzeł 4: powtórz ...

inny wątek:

  • Węzeł 1: poczekaj, aż obraz zostanie przechwycony
  • Węzeł 2: używając „1.jpg” pobierz kolory z każdego piksela
  • Węzeł 3: zapisuj dane w tablicach
  • Węzeł 4: powtórz ...

2
Oto twoja odpowiedź - program Java Swing do przechwytywania obrazów z samouczka kamery internetowej Lekko zmodyfikuj go i gotowe ...
Aman

Odpowiedzi:


49

Ta implementacja JavaCV działa dobrze.

Kod:

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

Jest też post na temat konfiguracji dla JavaCV

Możesz modyfikować kody i być w stanie zapisywać obrazy w regularnych odstępach czasu i wykonywać resztę żądanego przetwarzania.


4
+1 Ty rządzisz! Szukałem dobrego open source i obsługiwanej alternatywy dla JMF do przechwytywania z kamery internetowej w systemie Windows i Linux. To działa jak urok! Dziękuję :)
maple_shaft

2
Nie działa dla mnie, jest napisane Wyjątek w wątku „main” java.lang.UnsatisfiedLinkError: C: \ Users \ steve \ AppData \ Local \ Temp \ javacpp213892357885346 \ jniopencv_core.dll: Nie można znaleźć bibliotek zależnych
Stepan Yakovenko

To zadziała, ale jakość wideo nie jest tak dobra, jak powinna. Zobacz moją odpowiedź, aby uzyskać lepszą jakość wyjścia wideo.
syb0rg

Dziękuję za sugestię. Interesuje mnie, jak ustawić to w systemie Windows? Czy potrzebuję rozpakowanego zipa 3Gb? W przeciwnym razie mój program używający JavaCV w systemie Linux działa dobrze.
Ilian Zapryanov

@StepanYakovenko musisz zainstalować OpenCV.
Matthieu

33

Jakiś czas temu stworzyłem ogólną bibliotekę Java, za pomocą której można robić zdjęcia kamerą internetową. Interfejs API jest bardzo prosty, nie ma zbyt wielu funkcji, może działać samodzielnie, ale obsługuje również dodatkowe sterowniki kamer internetowych, takie jak OpenIMAJ, JMF, FMJ, LTI-CIVIL itp., A także niektóre kamery IP.

Link do projektu to https://github.com/sarxos/webcam-capture

Przykładowy kod (zrób zdjęcie i zapisz w test.jpg):

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

Jest również dostępny w Maven Central Repository lub jako osobny plik ZIP, który zawiera wszystkie wymagane zależności i pliki JAR innych firm.


1
Aby ułatwić rozpoczęcie pracy, warto się temu przyjrzeć. Kod zadziałał dla mnie świetnie, mam nadzieję, że Ty też :)
mrswadge

@Bartosz Firyn: witam pracuję z Twoim API. świetny robotnik! ale teraz chcę wiedzieć, czy powiększanie w aparacie jest obsługiwane, czy nie? jak powiększyć kamerę za pomocą tego API?
Java Man

@JavaMan, nie ma natywnej obsługi powiększania.
Bartosz Firyn

2
@JavaMan, możesz rysować na panelu wyświetlającym widok z kamery (WebcamPanel), ustawiając niestandardową instancję Paintera, lub bezpośrednio na obrazie pochodzącym z kamery za pomocą funkcji WebcamImageTransformer. Aby uzyskać więcej informacji, otwórz zgłoszenie na stronie projektu Webcam Capture na Github, ponieważ nie chcę tego szczegółowo wyjaśniać tutaj, w Stack Overflow (za dużo do napisania i za mało znaków do wykorzystania w komentarzach). Projekt można znaleźć tutaj github.com/sarxos/webcam-capture
Bartosz Firyn

1
@Elyas Hadizadeh, w razie problemów zawsze możesz utworzyć nowe zgłoszenie wydania na github.com/sarxos/webcam-capture, gdzie znajdziesz również dokumentację i przykłady. Należy również pamiętać, że jest to framework dla osób raczej zaznajomionych z Javą. Jeśli jesteś nowicjuszem w Javie, są też chętni do pomocy, ale podstaw musisz nauczyć się samodzielnie.
Bartosz Firyn


5

Oto podobne pytanie z kilkoma - jeszcze nie zaakceptowanymi - odpowiedziami. Jeden z nich wspomina o FMJ jako o alternatywnej java dla JMF.


5

Ten rodzaj odpowiedzi wychodzi z odpowiedzi gt_ebuddy przy użyciu JavaCV, ale moje wyjście wideo ma znacznie wyższą jakość niż jego odpowiedź. Dodałem także kilka innych usprawnień losowych (takich jak zamykanie programu kiedy ESCi CTRL+Csą prasowane i upewniając się zamknąć zasobów zastosowań programu prawidłowo).

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

Użyłem JMF w aplikacji do wideokonferencji i działał dobrze na dwóch laptopach: jednym ze zintegrowaną kamerą internetową i drugim ze starą kamerą USB. Wymaga wcześniejszego zainstalowania i skonfigurowania JMF, ale kiedy skończysz, możesz dość łatwo uzyskać dostęp do sprzętu za pośrednictwem kodu Java.


3

Możesz wypróbować Marvin Framework . Zapewnia interfejs do pracy z kamerami. Ponadto zapewnia również zestaw funkcji przetwarzania wideo w czasie rzeczywistym, takich jak śledzenie obiektów i filtrowanie.

Spójrz!

Demo przetwarzania wideo w czasie rzeczywistym:
http://www.youtube.com/watch?v=D5mBt0kRYvk

Możesz skorzystać z poniższego źródła. Po prostu zapisuj ramkę za pomocą MarvinImageIO.saveImage () co 5 sekund.

Demo wideo z kamery internetowej:

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

Dla tych, którzy chcą tylko zrobić jedno zdjęcie:

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

Korzystanie z odtwarzacza z zamachem

Odtwarzacza można również łatwo używać w aplikacji Swing. Poniższy kod tworzy program przechwytywania TV oparty na Swing z wyjściem wideo wyświetlanym w całym oknie:

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

Użyłem Webcam Capture API ... możesz pobrać z tego 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"));

                }
            }
        }

Powinieneś podać wyjaśnienie wraz z kodem
fen1x

1
dzięki. jest lekki, a zamiast tego javacv ten działa dla mnie.
Lucke

1

Java zwykle nie lubi dostępu do sprzętu, więc jak powiedział Goldenmean, będziesz potrzebować jakiegoś programu sterownika. Zrobiłem to na moim laptopie, znajdując program wiersza poleceń, który robi zdjęcie. Wtedy jest to to samo, co wyjaśnił goldenmean; uruchamiasz program wiersza poleceń z programu java w procedurze takepicture (), a reszta kodu działa tak samo.

Z wyjątkiem części dotyczącej wczytywania wartości pikseli do tablicy, możesz lepiej skorzystać, zapisując plik w formacie BMP, który jest już prawie w tym formacie, a następnie używając standardowych bibliotek obrazów java.

Korzystanie z programu wiersza poleceń dodaje zależności do programu i sprawia, że ​​jest mniej przenośny, ale tak samo jak kamera internetowa, prawda?


1

Zalecamy używanie FMJ do obsługi multimedialnej aplikacji java.


0

Uważam, że oprogramowanie aplikacji kamery internetowej, które jest dostarczane wraz z kamerą internetową, lub natywne oprogramowanie kamery internetowej dla systemu Windows można uruchomić w skrypcie wsadowym (skrypt Windows / DOS) po włączeniu kamery internetowej (tj. Jeśli wymaga zewnętrznego zasilania Dostawa). W skrypcie bacth możesz dodać odpowiednie opóźnienie do przechwytywania po określonym czasie. I kontynuuj wykonywanie polecenia przechwytywania w pętli.

Myślę, że to powinno być możliwe

-OGŁOSZENIE


0

Jest do tego całkiem niezły interfejs w przetwarzaniu , który jest rodzajem pidginowej javy zaprojektowanej dla grafiki. Jest używany w niektórych pracach związanych z rozpoznawaniem obrazu, takich jak ten link.

W zależności od tego, czego z niej potrzebujesz, możesz załadować bibliotekę wideo, która jest tam używana w javie, lub jeśli po prostu się nią bawisz, możesz uzyskać za pomocą samego przetwarzania.


0

Może to zrobić FMJ, podobnie jak biblioteka pomocnicza, której używa LTI-CIVIL. Obie są na SourceForge.


0

Spróbuj użyć JMyron How To Use Webcam Using Java . Myślę, że użycie JMyron jest najłatwiejszym sposobem uzyskania dostępu do kamery internetowej za pomocą Java. Próbowałem go używać z 64-bitowym procesorem, ale dało mi to błąd. Jednak działał dobrze na 32-bitowym procesorze.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.