# API für Webcam?



## Kampfzwereg (26. Mrz 2012)

Hallo zusmammen.

Ich probiere ganz simpel, mittels eines Tools, mit dem Java-Editor alle n Sekunden ein Bild von einer Webcam zu bekommen. Mehr nicht!!!

Ich hab mir dazu mehrere Threats in diesem Froum durchgelesen. Dazu habe ich ein paar Fragen:

1)Was mein ihr mit JMF ist tot? :-]
2)Welches Tool wäre für diese simple Aufgabe am sinnvollsten. Hab in nem anderen Threat gelsen, dass GStream gut sein soll, da es viele Funktionen hat, die brauch ich aber nicht, soll ich dann JMF nehmen?
3)Weiß jemand ob es irgendwo ein Tutorial für Dummies gibt, das stumpf in deutsch erklärt wie ich mir nur ein einziges Bild von meiner cam hole. Ich hab den Quellcode in einem anderen Threat gesehen, in dem sich wohl von einer Cam ein Bild geholt wird. Nur versteh ich den ohne Erläuterungen eigenltich nicht mal gerade so.
4)Wie läuft sowas denn ab. Lad ich mir die (zb) JMF runter und zieh dann die Datei in meinen ordner, und kann dann Objekte von bestimmten Klassen erzeugen oder wie?

LG Kampfzwereg


----------



## JohannisderKaeufer (26. Mrz 2012)

Eine Variante die ich unter linux verwendet habe um an bilder von meiner Webcam zu kommen war das Programm scanimage zu benutzen.

Damit reduziert sich das speichern eines Bildes auf den Aufruf

```
scanimage -d v4l:/dev/video0 --mode Color --format pnm > dateiname.pnm
```
oder

```
scanimage -d v4l:/dev/video0 --mode Color --format tiff > dateiname.tiff
```

Das könnte man über Runtime absetzen und dann das Bild mit ImageIO laden.


----------



## Kampfzwereg (26. Mrz 2012)

ok danke...versteh ich soweit. wie krieg ich denn scanimage in mein Prog? also was muss ich machen. ich kann ja nich eifnach deine Zeile in meinen Quellcode implementieren.


----------



## nillehammer (26. Mrz 2012)

```
final Runtime runtime = Runtime.getRuntime();

final Process process = runtime.exec(new String[] { "/voller/pfad/zu/scanimage", "-d", "v4l:/dev/video0", "--mode",
		"Color", "--format", "tiff" });

//Darüber holst Du die Ausgabe von scanimage
final InputStream is = process.getInputStream();
```
So in etwa. Ich habe scanimage leider nicht, aber mit /bin/ping hat's wunderbar funktioniert.


----------



## JohannisderKaeufer (27. Mrz 2012)

Also ich hab mein ein kleines Programm zusammengehackt, dass ein Bild einscannt, in ein png convertiert und in einem JFrame anzeigt.

Es werden die Programme scanimage und convert benötigt. Das sollte sogut wie jede Distro liefern können.


```
import javax.swing.*;
import java.io.*;
import java.awt.*;

/**
 * 
 * Scant ein Bild ein, convertiert es und zeigt es in einem Fenster an.
 */
public class WebcamSnapshot {
	/**
	 * Bild einscannen und speichern als name.pnm
	 * @param name als dateiname 
	 */
	public static void scanImage(String name) throws Exception {
		String command = "scanimage -d v4l:/dev/video0 --mode Color --format pnm";
		Process p = Runtime.getRuntime().exec(command);
		InputStream is = p.getInputStream();
		FileOutputStream fos = new FileOutputStream(name+".pnm");
		int nRead;
		byte[] data = new byte[16384];

		while ((nRead = is.read(data, 0, data.length)) != -1) {
			fos.write(data, 0, nRead);
		}

		fos.flush();
		fos.close();
		p.waitFor();
	}
    /**
     * Bild name.pnm zu name.png convertieren da pnm nur mit JAI unterstützt wird
     * @param name als dateiname
     */
	public static void convert(String name) throws Exception{
		String command = "convert "+name+".pnm "+name+".png";
		Process p2 = Runtime.getRuntime().exec(command);
		p2.waitFor();  
	}
    /**
     * Erzeugt ein Fenster und zeigt darin das name.png Bild an
     * @param name als dateiname
     */
	public static void showImage(String name) throws Exception {
			ImageIcon ii = new ImageIcon(name+".png");
			JLabel l = new JLabel(ii);
			JFrame f = new JFrame("My Webcam image");
			f.setPreferredSize(new Dimension(640, 480));
			f.add(l);
			f.pack();
			f.setVisible(true);
			f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		}
	/**
	 * Scant ein Bild ein, convertiert es und zeigt es in einem Fenster an.
	 * @param args unused
	 */
	public static void main(String[] args) throws Exception {
		String fileName = "webcamimage";
		scanImage(fileName);
		convert(fileName);
		showImage(fileName);
	}
}
```


----------



## Kampfzwereg (27. Mrz 2012)

ok danke nochmal, hilft mir alles schon super. 
aber : 
1) was ist ne distro?
2)beantwortet doch bitte noch meine erste frage. wie sieht das aus , kann ich mir scanimage und covert einfach laden und die exe ausführen ums zu installieren un dann kann ich ganz einfach objekte von den Typen, die ich durch die progs kriegen, erstellen und benutzen?
3)kann nen jFrame nur png anzeigen, brauch ich das prog "convert" überhaupt?

@nillehammer:also ich bin wirklich nich so der pro in java, könnteste du den ersten Teil deines Quelltextes nochmal genau erläutern, wär voll dufte :-D


----------



## Marcinek (27. Mrz 2012)

Diese Lösungen funktionieren und unter Linux und nicht Windows. 

Man müsste etwas vergleichbares unter windows suchen.

1) Eine Distribution ist eine der möglichen ausprägungen eines Linuxsystems (Suse, Debian..)

2) vermutlich nicht. Du brauchst eine Version für Windows

3) Wenn du da drin einen entsprechenden Container hast, kannst du aber alle Bilder anzeigen. Du kannst auch das painting überladen und selbst was reinmalen, z.B. ein bild.

Mit Runtime kannst du Systemseitig prozesse starten. Wie zum Beispiel scanimage.


----------



## Kampfzwereg (27. Mrz 2012)

@Marcinek : also sind die vorherigen Beiträge eher unwichtig für mich als windows nutzer? (sry and die Poster)


wär es denn mit JMF oder Gstream so, dass ich da ne exe zum Installieren ausführe und dann kann ich das ganz normal nutzen?
wenn ja, ist sowas dann sehr kompliziert ?


----------



## nillehammer (27. Mrz 2012)

> @Marcinek : also sind die vorherigen Beiträge eher unwichtig für mich als windows nutzer? (sry and die Poster)


Insofern, als hier mit scanimage von einem Linux-Tool die Rede ist, das es wohl unter Windows nicht zu geben scheint. Wenn es ein vergleichbares Tool unter Windows gibt, kannst Du es aber genauso aufrufen, wie hier am Beispiel scanimage dargestellt.


> wär es denn mit JMF oder Gstream so, dass ich da ne exe zum Installieren ausführe und dann kann ich das ganz normal nutzen?
> wenn ja, ist sowas dann sehr kompliziert ?


Nein, ist es nicht. Wie hier schon mehrfach erwähnt und auch in Codebeispielen dargestellt, kannst Du Kommandozeilenaufrufe ganz leicht mit Hilfe der Runtime-Klasse machen.


----------



## JohannisderKaeufer (27. Mrz 2012)

Ein Windows-Tool das Bilder von der Webcam abspeichert und sich per Commandozeile verwenden läßt, wäre z.B 

Webcamshot, Download bei heise

Runterladen und instllieren.

Im Installationsordner gibt es dann 
1. eine exe Datei die man analog zu oben genannten Beispielen ausführen kann.

2. eine Datei Java Beispiel, die zeigt, wie man das Programm aus Java heraus aufrufen kann.


Wenn das Programm erstmalig ausgeführt wird, gibt es eine Konfigurationsansicht in der Einstellungen gemacht, sowie die Webcam ausgewählt werden können.

Bei einem weiteren Start, wird dann ein Bild im Jpg, sowie im BMP-Format auf der Festplatte abgespeichert. Beim starten des Programms sollte lediglich ein parameter -s für silent mitgegeben werden, so daß sich kein Anwendungsfenster öffnet.

Beides Bildformate lassen sich in der Regel problemlos in einem Java-Programm anzeigen. Auch ohne Konvertierung.


----------



## Kampfzwereg (27. Mrz 2012)

ja super!danke erstmal.

ok. das heißt ich öffne das Prog webcamshot in meiner Java Applikation und dann gibt mir das automatisch das derzeitige Bild von der Kamera, die ich ausgewählt habe?

noch zwei klitzekleine Fragen  
1)ein Kommandozeileaufruf ...das heißt doch lediglich, dass ich mit einer Zeile etwas, in diesem fall zb das Prog webcamshot, aufrufe oder?
2)was isn nochmal die Klasse Runtime? 

lg Kampfzwereg


----------



## Andi_CH (27. Mrz 2012)

Ich konnte den Kunden zum Glück überzeugen Webcams zu installieren die man gleich per http ansprechen kann.
Zuvor habe ich die Daten der USB-Cams mit Hilfe eines kleinen Webservers (der aber auch nur auf Linux läuft) gestreamt und per http gelesen.

Wenn du in diese Richtung gehen kannst, könnte ich dir weiter helfen.


----------



## Kampfzwereg (27. Mrz 2012)

@Andi_CH : Ja also ich hab keine Ahnung von http, weiß nicht ob man die dafür braucht. Ich die Hercules Deluxe Optical Glass ...geht sowas mit dieser Kamera?


----------



## Andi_CH (27. Mrz 2012)

Das war ein 3-Zeiler oder so. ich mach mal ein kleines BSP-Programm und poste es dann.


----------



## Kampfzwereg (27. Mrz 2012)

wär natürlich cool.geht das denn überhaupt mit meienr cam?
und was GENAU machst du da in deinem Prog?



@JohannisderKaufer:



> ok. das heißt ich öffne das Prog webcamshot in meiner Java Applikation und dann gibt mir das automatisch das derzeitige Bild von der Kamera, die ich ausgewählt habe?





> ein Kommandozeileaufruf ...das heißt doch lediglich, dass ich mit einer Zeile etwas, in diesem fall zb das Prog webcamshot, aufrufe oder?


----------



## Andi_CH (27. Mrz 2012)

Ich hab dir doch schon beschrieben was die Voraussetzung ist und dabei wird dir hier kaum jemand helfen können! Du musst einen kleinen Webserver laufen lassen, der die Bilder der USB-CAM streamt oder ein CAM einsetzen die das von sich aus kann.
Als "Webserver" habe ich damals mjpg-streamer auf Debian und Ubuntu eingesetzt

Wenn eine CAM nicht erreichbar ist oder sonstwie "spinnt" hängt der get-Befehl. Das war der Grund das in einen Thread zu packen. (Da flucht man dann wieder einmal mehr über den Entscheid stop() depricated zu setzen, denn anders kann man einen hängenden Thread nicht "entsorgen")

Es hat garantiert Overhead und ungeschickte Sequenzen im Code, aber das stammt ja aus einem grösseren Programm und ist zusammenkopiert, aber ich habe jetzt keine Zeit das noch zu bereinigen - auf jeden Fall tut es.


```
package getpicture;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

public class GetPictures {

	private static class GetPictureThread  extends Thread {
		private final String RESPONSE_OK = "200 OK";
		private final int BUFFER_LENGTH  = 65535;

		private final String mFileName;
		private volatile int mResult = -2;

		public GetPictureThread (String pFileName) {
			mFileName = pFileName;
		}

		public void run() {
			File f = new File(mFileName);
			if (f.exists()) {
				mResult = -1;
			} else {
				try {
					URL url = new URL("http://10.0.0.41/cgi-bin/viewer/video.jpg?streamid=0");
					URLConnection connection = url.openConnection();
					if (connection == null) {
						mResult = -1;
					}
					if (connection.getHeaderField(0) == null) {
						mResult = -2;
					}
					if (connection.getHeaderField(0).contains(RESPONSE_OK)) {
						if ("image/jpeg".equals(connection.getContentType())) {
							InputStream in = connection.getInputStream();
							byte[] buffer = new byte[BUFFER_LENGTH];
							int len;
							int total = 0;
							FileOutputStream fileOut = new FileOutputStream(new File(mFileName));
							while ((len = in.read(buffer))>0) {
								total += len;
								fileOut.write( buffer, 0, len );
							}
							fileOut.close();
							mResult = total;
						} else {
							mResult = 0;
						}
					} else {
						mResult = -1;
					}
				} catch (Exception e) {
					mResult = -1;
				}
			}
		}
		public int result() { return mResult; }
	}

	private void sleep(long pTime) {
		try {
			Thread.sleep(pTime);
		} catch (InterruptedException e) {}
	}

	@SuppressWarnings("deprecation")
	private int saveSnapshot(String pFilename) {
		int retVal = -2;
		int counter = 0;
		GetPictureThread gpt = new GetPictureThread(pFilename);
		gpt.setDaemon(true);
		gpt.start();
		while((gpt.result()<-1) && (counter<300)) {
			sleep(1000);
		}
		retVal = gpt.result();
		if (retVal<-1) {
			gpt.stop();
			sleep(500);
			gpt = null;
		}
		return retVal;
	}
	
	public static void main(String[] args) {
		new GetPictures().saveSnapshot("/temp/testbild.jpg");
		
	}
}
```


----------



## Kampfzwereg (28. Mrz 2012)

ok...das is ja super net, dass des sowas für mich da zusammenkopiert hast. aber ich wills ja auch selber können.
Desswegen werde ich mir wohl den Tipp von JohannsiderKaeufer zu Herzen nehmen und probieren mittels des Programms Webcamshot ein BIld von meiner Cam zu bekommen und einzubinden. Trotzdem danke für die Hilfe.

LG Max


----------



## schlingel (28. Mrz 2012)

Es gibt in Form von JavaCV übrigens eine aktuelle Library die das kann. JavaCV ist dabei ein Wrapper für die OpenCV-Libs die es für Windows und Linux gibt. Siehe hier ein Beispielprogramm das genau das leistet was du möchtest.


----------



## Kampfzwereg (2. Apr 2012)

also ich habs jetzt soweit, dass er eigentlich auf knopfdruck das Programm Webcamshot im silent modus startet, er sagt mir dann aber immer ich bräuchte für den Vorgang erhöte Rechte. Keine ahnung was damit gemeint ist, da mein Konto ja das Adminkonto ist.
Hier mal die Zeilen zum Programmaufruf und die Fehlermeldung:


```
public void jBimportierenC_ActionPerformed(ActionEvent evt)
  {
    try
    {
       Runtime runtime = Runtime.getRuntime();
       Process process = runtime.exec(new String[] { "M:/Webcamshot/WEBCAMSHOT.exe", "-s" });
    }
    catch(Exception e)
    {
      System.out.println(e);
    }

  }
```


```
java.io.IOException: Cannot run program "M:/Webcamshot/WEBCAMSHOT.exe": CreateProcess error=740, Der angeforderte Vorgang erfordert erhöhte Rechte
```


----------



## schlingel (2. Apr 2012)

Du wirst das ganze wohl mit runas starten müssen.


----------



## Kampfzwereg (2. Apr 2012)

und das bedeutet?....sry für die dumme Frage , aber auf dem Gebiert kenn ich mich nicht aus ...


----------



## Kampfzwereg (13. Mai 2012)

also ich benutze jetzt doch JMF . Das ist, wenn man sich da nen bisschen reinhängt, einfach am besten. AUch wenn das keinen Support mehr hat. Webcamshot ist in dem Sinne unpraktisch, da man dafür Befehle braucht, und dass desswegen mit "runAs" nicht klappt.


----------

