화상 강의 관련 프로젝트를 자주 하다보니, 웹캠을 다뤄야할 일이 많습니다. DSPack을 이용해서 사용하다가 가끔씩 오동작을 하는 캠이 있어서, 이리 저리 수정하긴 했지만, 불안하기도 하고 해서, 쉽게 VideoGrabber를 이용하기로 했습니다. 상용 컴포넌트이고 다소 무거운(프로그램 사이즈가 커집니다) 것이 불만이긴 하지만, 잘 돌아갑니다.
이번 포스트에서는 VideoGrabber를 이용하여, 캠에서 Bitmap 데이터를 스냅 샷으로 잡아오기 위한 간단한 클래스를 설명하겠습니다.
소스는 아래 주소를 참고하시기 바랍니다.
우선 웹캠을 쉽게 다루기 위하여 만든 TWebCamCtrl의 인터페이스를 살펴보도록 하겠습니다.
[그림 1] TWebCamCtrl의 인터페이스
[그림 1]에서 보는 것처럼 간단한 인터페이스를 갖추고 있습니다. 각각의 설명은 아래와 같습니다.
- Method
- procedure Start;
- 웹캠을 작동 시킵니다. 성공하면, 미리보기가 보이기 시작합니다.
- procedure Stop;
- procedure Capture;
- 현재의 화면을 Bitmap으로 캡쳐합니다. 성공하면, OnCaputred 이벤트가 발생합니다.
- function SnapShot(ABitmap:TBitmap):boolean;
- 스냅 샷을 얻어서 ABitmap에 해당 데이터를 옮겨 줍니다. 성공하면 리턴 값이 불린이 됩니다.
- 캡쳐 자체는 성공했으나, 메소드의 실행 결과가 false 일 수도 있습니다. 비동기로 동작하기 때문에, 스냅 샷의 경우에는 반복적으로 요청해서 사용합니다.
- Capture 메소드와 같이 OnCaputred 이벤트가 발생합니다.
- Property
- property Active : boolean; // Read Only
- property DeviceNo : Integer;
- 웹캠이 여러 대 설치가 되어 있다면, DeviceNo를 변경하는 것으로 웹캠을 선별하여 동작 시킬 수 있습니다.
- property Resolution : Integer;
- 지원되는 해상도 중 하나를 선택할 수가 있습니다.
- property DeviceList : TStringList; // Read Only
- property ResolutionList : TStringList; // Read Only
- Event
- property OnCaptured : TCapturedEvent;
- 스냅 샷을 요구하면, TBitmap 클래스를 인자로 해서 OnCaptured 이벤트가 발생합니다.
예제를 통해서 실제 사용 방법을 살펴보면 다음과 같습니다. 소스가 간단하기 때문에 따로 설명이 필요 없을 것으로 보입니다.
unit main;
interface
uses
WebCam,
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TfmMain = class(TForm)
btSnapShot: TButton;
btStart: TButton;
btStop: TButton;
plCam: TPanel;
Image: TImage;
cbDeviceList: TComboBox;
cbResolutionList: TComboBox;
Timer: TTimer;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure btStartClick(Sender: TObject);
procedure btStopClick(Sender: TObject);
procedure cbResolutionListChange(Sender: TObject);
procedure cbDeviceListChange(Sender: TObject);
procedure TimerTimer(Sender: TObject);
private
FWebCam : TWebCamCtrl;
procedure on_Captured(Sender:TObject; const ABitmap:TBitmap);
public
end;
var
fmMain: TfmMain;
implementation
{$R *.dfm}
procedure TfmMain.btStartClick(Sender: TObject);
begin
FWebCam.Start;
cbResolutionList.Items.Text := FWebCam.ResolutionList.Text;
cbResolutionList.ItemIndex := 0;
end;
procedure TfmMain.btStopClick(Sender: TObject);
begin
FWebCam.Stop;
end;
procedure TfmMain.cbDeviceListChange(Sender: TObject);
begin
if cbDeviceList.ItemIndex > -1 then
FWebCam.DeviceNo := cbDeviceList.ItemIndex;
end;
procedure TfmMain.cbResolutionListChange(Sender: TObject);
begin
if cbResolutionList.ItemIndex > -1 then
FWebCam.Resolution := cbResolutionList.ItemIndex;
end;
procedure TfmMain.FormCreate(Sender: TObject);
begin
FWebCam := TWebCamCtrl.Create(Self);
FWebCam.Align := alClient;
FWebCam.Parent := plCam;
FWebCam.OnCaptured := on_Captured;
cbDeviceList.Items.Text := FWebCam.DeviceList.Text;
cbDeviceList.ItemIndex := 0;
end;
procedure TfmMain.FormDestroy(Sender: TObject);
begin
FWebCam.Free;
end;
procedure TfmMain.on_Captured(Sender: TObject; const ABitmap: TBitmap);
begin
Image.Picture.Bitmap.Assign(ABitmap);
end;
procedure TfmMain.TimerTimer(Sender: TObject);
begin
Timer.Enabled := false;
try
FWebCam.Capture;
// if FWebCam.SnapShot(Image.Picture.Bitmap) then ; // do Something
finally
Timer.Enabled := true;
end;
end;
end.
화면 구성은 아래와 같이 설정하였습니다.
[그림 2] 예제의 화면 설정