チュートリアルに戻る

カメラを使う

目標: 組み込みで用意されているCameraサービスとGUIコンポーネントを使って、カメラ映像をウィンドウに表示する。

The Adobe Flash Plugin is needed to display this content.

写真を一枚撮る

materealライブラリでUSB接続されたWebカメラを使うには、Cameraサービスを初期化します。

RunCameraAndSaveImage.java
import java.awt.image.RenderedImage;
import java.io.File;
 
import javax.imageio.ImageIO;
 
import jp.digitalmuseum.mr.Matereal;
import jp.digitalmuseum.mr.service.Camera;
 
/**
 * Run a camera service to capture an image.
 *
 * @author Jun KATO
 */
public class RunCameraAndSaveImage {
 
	public static void main(String[] args) {
 
		// Run a camera.
		Camera camera = new Camera();
		camera.start();
 
		// Save an image captured from the camera.
		try {
			Thread.sleep(3000);
			RenderedImage image = camera.getImage();
			ImageIO.write(image, "JPEG", new File("test.jpg"));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			Matereal.getInstance().dispose();
		}
	}
}

サービスを起動した直後は真っ黒な画像が撮れるため、わざと撮影まで3秒あけています。Matereal.getInstance().dispose()はライブラリの終了処理を呼び出します。これで起動したサービスがすべてシャットダウンされ、プログラムが終了します。

カメラ画像をウィンドウに表示する

Cameraサービスは起動している間じゅうカメラの画像を取得し続けます。このように、画像を定期的に配信するサービスはImageProviderインタフェースを実装しています。materealに組み込みで用意されているサービスの中では、他に簡易2次元シミュレータのHakoniwaサービスもImageProviderインタフェースを実装しています。

さて、ImageProviderから画像を毎フレーム取得するためにはリスナインタフェースImageProvider.ImageListenerを実装します。したがって、カメラで撮影している映像を画面に表示するためには、JPanelクラスを継承し、ImageListenerインタフェースを実装した新しいパネルクラスを作成し、それをJFrameに追加する…といった工程が必要です。

利便性を考え、Materealには組み込みでImageProviderの画像を表示するためのGUIコンポーネントImageProviderPanelが用意されています。このコンポーネントは、使い終わったときにリスナの登録を外すためdispose()を呼ぶ必要があります。このような終了処理を伴うコンポーネント(DisposableComponent)を表示するために、JFrameを継承したGUIコンポーネントDisposeOnCloseFrameが用意されています。

実際のコードはRunCamera.javaのようになります。(以下転載)

RunCamera.java
import jp.digitalmuseum.mr.Matereal;
import jp.digitalmuseum.mr.gui.*;
import jp.digitalmuseum.mr.service.Camera;
 
/**
 * Run a camera service and show captured images.
 *
 * @author Jun KATO
 */
public class RunCamera {
 
	public static void main(String[] args) {
 
		// Run a camera.
		Camera camera = new Camera();
		camera.start();
 
		// Make and show a window for showing captured image.
		DisposeOnCloseFrame frame = new DisposeOnCloseFrame(
				new ImageProviderPanel(camera)) {
			private static final long serialVersionUID = 1L;
 
			@Override public void dispose() {
				super.dispose();
 
				// Shutdown Matereal when the window is closed.
				Matereal.getInstance().dispose();
			}
		};
		frame.setFrameSize(camera.getWidth(), camera.getHeight());
	}
}

ユーザに使うカメラを選択させる

最近のPCではカメラを複数台繋ぐことも珍しくありません。そのような場合は、ユーザに使用するカメラを選択してもらいましょう。

例えば、先のソースにimport宣言を加え、

import javax.swing.JOptionPane;

選択ダイアログを表示して、得られた結果を引数としてCameraサービスをインスタンス化することができます。

// Let users select a device to capture images.
String identifier = (String) JOptionPane.showInputDialog(null,
		"Select a device to capture images.", "Device list",
		JOptionPane.QUESTION_MESSAGE, null,
		Camera.queryIdentifiers(), null);
Camera camera;
if ((identifier != null) && (identifier.length() > 0)) {
	camera = new Camera(identifier);
} else {
	return;
}
camera.start();

なお、カメラのキャプチャ解像度を指定するにはcamera.start()より前にcamera.setSize(800, 600)のようにサイズ指定を挟みます。1)

以上の内容がサンプルコードのRunCameraWithDialog.javaに書かれています。

1) 64bit版のWindowsでは解像度の指定がうまくいかないケースがあります。とりあえずの対処法をtipsに書いておきました。