この記事はC# Advent Calendar 2023アドベントカレンダーの18日目です。
C#でWindowsアプリを作成する際に、USBカメラやWebカメラを利用する方法を紹介します。ネットで検索する限り、OpenCVSharpを利用している例が多いのですが、今回は、私が作成したライブラリ「UsbCamera」を紹介します。
「UsbCamera」は、DirectShowを利用して、WinFormsやWPFで、USBカメラ(Webカメラ)を利用するためのライブラリです。プログラムはGitHubで公開されています。リポジトリはこちらです。
ライブラリの特徴
UsbCameraの特徴は以下の通りです。
- 導入するには、ソースコードを1つあなたのプロジェクトに追加するだけです。(DLL等は必要ありません)
- WinFormsとWPFの両方に対応しています。
- チルト・ズーム・ホワイトバランス・露出などの設定を行うことができます。(カメラが対応している必要があります)
- カメラの撮影ボタンで静止画を撮影することができます。(カメラが対応している必要があります)
導入方法
上記リポジトリからクローンするか、zipファイルをダウンロードしてください。ここでは、zipファイルをダウンロードした場合で解説します。
ダウンロードしたzipを解凍すると、ライブラリ本体である「UsbCamera.cs」と、使い方のサンプルである「SampleProject」フォルダが作成されますので、「UsbCamera.cs」を、あなたのプロジェクトに追加してください。
今回は、サンプルプロジェクトでその使用例を説明しますので、「SampleProject」フォルダ内にある「UsbCameraSample.sln」を起動してください。
ソリューションには、2つのプロジェクトが含まれています。「UsbCameraForms」がWinForms用で、「UsbCameraWpf」がWPF用です。
プロジェクトを実行して、動作を確認してみてください。画面に、Webカメラの画像が表示されたはずです。
以後、プログラムの中身を解説します。
基本的な使い方
利用可能なカメラを探す。
// 利用可能なカメラを探す。
string[] devices = UsbCamera.FindDevices();
if (devices.Length == 0) return; // カメラが見つからなかった。
UsbCamera#FindDevices()を呼び出して、PCに接続されているカメラの一覧を取得します。
戻り値はstring[]で、カメラ名の配列が返りますので、この中から、利用したいカメラのインデックス番号を確認します。カメラのインデックス番号は、次の「ビデオフォーマットの作成」や、あとで「UsbCameraクラスのインスタンスを作成する際」に使用します。
ビデオフォーマットの選択。
// ビデオフォーマットの取得。
var cameraIndex = 0; // カメラインデックス番号0番のビデオフォーマットを取得。
var formats = UsbCamera.GetVideoFormat(cameraIndex);
カメラは320x240, 640x480など、複数の画面サイズに対応しているのが普通です。UsbCamera#GetVideoFormat()を呼び出して、カメラが対応しているビデオフォーマットのリストを取得します。
たとえば私が使用しているPCのWebカメラでは、以下のようになりました。
この中から、利用したい画像のサイズであるビデオフォーマットを探します。例えば、1920x1080サイズのビデオフォーマットを利用する場合は、formats[0]を、UsbCameraクラスのインスタンス作成時に指定します。
UsbCameraクラスのインスタンスを作成。
利用したいカメラのインデックス番号と、ビデオフォーマットを指定して、UsbCameraクラスのインスタンスを作成します。インスタンスを作成したら、camera.Start()で動作を開始します。
// カメラインデックスとビデオフォーマットを指定して、USBカメラクラスのインスタンスを作成
var camera = new UsbCamera(cameraIndex, formats[0]);
camera.Start(); // 動作開始!
画像の取得。
カメラから画像を取得するには、camera.GetBitmap()を呼び出します。
button1.Click += (s, ev) => pictureBox1.Image = camera.GetBitmap();
あとしまつ。
フォームクローズ時など、不要になった時点でcamera.Release()を呼び出してください。
this.FormClosing += (s, ev) => camera.Release(); // release when close.
高度な使い方
WPFで利用する。
ライブラリはデフォルトではWinFormsで利用されることを想定されており、GetBitmap()はSystem.Drawing.Bitmap型の画像を返します。
WPFで利用する場合は、「USBCAMERA_WPF」シンボルを定義すると、GetBitmap()はBitmapSource()型で画像を返すようになります。
プレビューを表示する。
カメラ画像のプレビューを画面に表示したい場合は、WinFormsとWPFで方法が異なります。
WinFormsの場合は、画面にPictureBoxを配置し、camera.SetPreviewControlでプレビューを表示するPictureBoxを指定してください。
camera.SetPreviewControl(pictureBox1.Handle, pictureBox1.ClientSize);
pictureBox1.Resize += (s, ev) => camera.SetPreviewSize(pictureBox1.ClientSize);
WPFの場合は、プレビュー画像が更新されるたびに呼び出されるcamera.PreviewCapturedでデータバインディングを利用して画像を更新してください。詳しくは、サンプルプロジェクトを参照してください。
camera.PreviewCaptured += (bmp) =>
{
Preview = bmp;
OnPropertyChanged("Preview");
};
カメラの撮影ボタンへの対応。
カメラには、通常の動画撮影とは別に、静止画撮影機能をもったものがあります。静止画撮影機能で取得した画像は、一般的に、動画撮影で取得した画像より高解像度なことが多いです。
あなたのカメラに、撮影ボタンが付いていたら、そのカメラは静止画撮影機能に対応している可能性が高いです。静止画撮影機能に対応しているかどうかは、camera.StillImageAvailableで判別できます。ボタンが押されたら、camera.StillImageCapturedがコールバックされます。ボタンの代わりに、camera.StillImageTrigger()を呼び出すことで撮影することもできます。
if (camera.StillImageAvailable)
{
button.Click += (s, ev) => camera.StillImageTrigger();
camera.StillImageCaptured += bmp => pictureBox.Image = bmp;
}
カメラプロパティ(チルト・ズーム・ホワイトバランス・露出など)の変更。
カメラが対応していれば、チルト・ズーム・ホワイトバランス・露出などを変更することができます。
カメラプロパティには大きく、CameraControlProperty系(Pan, Tilt, Roll, oom, Exposure, Iris, Focus)と、VideoProcAmpProperty系(Brightness, Contrast, hue, Saturation, Sharpness, Gamma, ColorEnable, WhiteBalance...)があります。
例えば露出(Exposure)を変更する場合は以下のようになります。プロパティはカメラが対応していない場合もありますので、必ずAvailableプロパティを確認してください。
// adjust properties.
var prop = camera.Properties[DirectShow.CameraControlProperty.Exposure];
if (prop.Available)
{
// get current value
var val = prop.GetValue();
// set new value
var min = prop.Min;
var max = prop.Max;
var def = prop.Default;
var step = prop.Step;
// set new value
prop.SetValue(DirectShow.CameraControlFlags.Manual, def);
}
おわりに。
以上、駆け足ですが、UsbCameraライブラリの使い方を説明しました。
近年では多くのノートPCにWebカメラが備わっています。もしあなたのPCにカメラがついていたら、試してみてはいかがでしょうか?
それでは、メリークリスマス!