OpenCVとDelphiでの画像の相互利用

 OpenCVの画像をDelphiで利用、又は、その逆の場合、画像データーの変換をしないと、利用できません。 此処では、 その変換を行っています。
OpenCVのインストール方法は、このホームページのOpenCV_WabCamera.htmlと、https://github.com/Laex/Delphi-OpenCVを参照してください。
OpenCVのIplImageの構造体については、イメージングソリューションのhttp://imagingsolution.net/program/opencv/iplimage-structure/を参照して下さい。
OpenCVのからはCV::MATが利用されていますがこれについては、画像処理ソリューション http://imagingsolution.blog107.fc2.com/blog-entry-178.htmlを参照してください。
このサイトは、イメージングソリューションの旧サイトになっていますので、何時まで存続するかは不明です。

 ここでは、IplImageとTbitmapの変換を行っています。(CV::MATとの変換は難しい)


 変換時の注意点は、IplImageの画像データーのデフォルト原点と、Tbitmapの原点が上下逆であることです。
Tbitmapの原点は、左下であり、IplImageの画像データーのデフォルト原点は、左上です。
IplImageの原点を左下にとることも出来ますが、OpenCVの画像処理プログラムが、左上を原点としているので、左下を原点とした場合、OpenCVでの画像処理は出来なくなります。
 Tbitmapと、IplImageを変換する場合は、画像データーを1ラインごと上下を入れ替えてコピーします。
TBitmapのLineScanを利用すると、LineScanの[Y]が示すポインタが左下原点からの値となるので、簡単に高速にコピーする事が出来ます。



 此処でのプログラム例でのDLLは、VC2013の場合です。
新しく delphi用のopenCvをダウンロードすると、新しいバージョンのVCのDLLを使用しているのでそちらを使用してください。
無料のVC2017をインストールした場合は、***2413.dllのみでOKです。
Release 時
 msvcp120.dll,msvcr120.dll,opencv_core2413.dll,opencv_highgui2413.dll,opencv_imgproc2413.dll,opencv_objdetect2413.dll
Debug 時
 msvcp120d.dll,msvcr120d.dll,opencv_core2413d.dll,opencv_highgui2413d.dll,opencv_imgproc2413d.dll,opencv_objdetect2413d.dll

サンプルプログラム IplImage To TBitmap

 最初のプログラムは、IplImageからTBitmapに変換してDelphiのVCL画面に表示をしています。
顔認識プログラムを使用した例です。
 顔認識は、IplImageで行いTBitmapに変換した後、顔部分の四角領域のTBitmap上に書き込んで、Timageに変倍表示しています。
描画の基準原点は、左上なので、OpenCVで得た結果をそのまま使用して、顔を認識した位置を四角で表示することが出来ます。
 顔認識時、グレイに変換し、更にヒストグラムによるコントラスト調整をして認識率を上げていますが、この画像を表示する場合は、TBitmapを8ビットとし、グレーのカラーパレットを作成する必要があります。

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, system.UITypes,
  Dialogs, ExtCtrls, ocv.core_c, ocv.core.types_c, ocv.compat, ocv.highgui_c,
  ocv.haar, ocv.legacy, ocv.objdetect_c,ocv.imgproc_c, ocv.imgproc.types_c;

type
  TForm1 = class(TForm)
    Image1: TImage;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private 宣言 }
    Capture: PCvCapture;
    CameraBmp: TBitmap;
    Storage: PCvMemStorage;
    Xml: ansistring;
    Cascade2: PCvHaarClassifierCascade;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  fgray     : PIplImage;
  fFormset  : Boolean;

const
// カメラ仕様に依存します
  VideoWidth = 1280;
  VideoHeight = 960;

{-----------------------------------------------------------------------------
  Procedure:  IplImageToBitmap
  Date:       28-Feb-2017
  Arguments:  iplImg: PIplImage; bitmap: TBitmap
  Description: convert a IplImage to a Windows bitmap
-----------------------------------------------------------------------------}
procedure IplImageToBitmap(iplImg: PIplImage; var bitmap: TBitmap);
var
  j: integer;
  offset: integer;
  dataByte: PByte;
  RowIn: PByte;
begin
  try
    // data 8bit BGR 3byte color の確認
    assert((iplImg.Depth = 8) and (iplImg.NChannels = 3),
            'IplImageToBitmap: Not a 24 bit color iplImage!');

    bitmap.Height := iplImg.Height;
    bitmap.Width := iplImg.Width;
    // メモリーの画像の上下合っている場合
    if (iplImg.ChannelSeq = 'BGR') and (iplimg.Origin = IPL_ORIGIN_BL) then begin
      RowIn := Bitmap.Scanline[bitmap.height - 1];
      dataByte := pbyte(iplimg.ImageData);
      {direct copy of the iplImage row bytes to bitmap row}
      CopyMemory(rowin, dataByte, iplImg.ImageSize);
      exit;
    end
    // メモリーの画像の上下が合っていない場合
    else begin
      for j := 0 to Bitmap.Height - 1 do begin
        RowIn := Bitmap.Scanline[j];
        offset := integer(iplimg.ImageData) + iplImg.WidthStep * j;
        dataByte := pbyte(offset);
        CopyMemory(rowin, dataByte, iplImg.WidthStep);
      end;
    end;
  except
    on E: Exception do begin
      Form1.Timer1.Enabled := False;
      MessageDlg('IplImageToBitmap failed - ' + e.Message, mtError, [mbOK], 0);
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  fFormset := False;
  fgray := nil;

  Form1.Top := (Screen.Height - Form1.Height) div 2;
  Form1.Left := (Screen.Width - Form1.Width) div 2;

  // cvCreateCameraCaptureのindexはカメラの番号を設定してください
  Capture := cvCreateCameraCapture(0);
  if not Assigned(Capture) then begin
    MessageDlg('カメラエラー', mtError, [mbOK], 0);
    Exit;
  end;
  cvSetCaptureProperty(Capture, CV_CAP_PROP_FRAME_HEIGHT, VideoHeight);
  cvSetCaptureProperty(Capture, CV_CAP_PROP_FRAME_WIDTH, VideoWidth);

  // ダブルバッファでちらつき防止
  DoubleBuffered := True;

  // コンポーネント表示用のビットマップ
  CameraBmp := TBitmap.Create;
  CameraBmp.PixelFormat := pf24bit;
  Storage := cvCreateMemStorage(0);
  Xml := 'haarcascade_frontalface_alt.xml';
//  Xml := 'haarcascade_frontalface_default.xml';  // default
  Cascade2 := PCvHaarClassifierCascade(cvLoad(PAnsiChar(Xml), nil, nil, nil));

  // デフォルトからの変更プロパティ
  with Image1 do begin
    Align := alClient;
    Center := True;
    Proportional := True;
    Stretch := True;
  end;
  Timer1.Interval := 20;
  Timer1.Enabled := True;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  cvReleaseCapture(Capture);
  FreeAndNil(CameraBmp);
  cvReleaseImage(fgray);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  frame: PIplImage;
  r: PCvRect;
  faces: PCvSeq;
  i: Integer;
  pt1, pt2: TCvPoint2D32f;
begin
  // 画像の取得
  frame  := cvQueryFrame(Capture);
  if not Assigned(frame) then Exit;
  // 表示サイズ設定
  if not fFormset then begin
    Form1.ClientHeight := frame.height div 2;
    Form1.ClientWidth := frame.width div 2;
    Form1.Top := (Screen.Height - Form1.Height) div 2;
    Form1.Left := (Screen.Width - Form1.Width) div 2;
    fFormset := true;
  end;
  // グレー用メモリー確保
  if fgray = nil then
    fgray := cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
  // カラーグレー変換
  cvCvtColor(frame, fgray, CV_BGR2GRAY);
  // グレーヒストグラム調整
  cvEqualizeHist(fgray, fgray);

  // メモリストレージをクリア
  cvClearMemStorage(Storage);
  // 画像から物体検出
  faces := cvHaarDetectObjects(
         fgray, Cascade2, Storage, 1.2, 3,
         CV_HAAR_DO_CANNY_PRUNING, CvSize(50, 50), CvSize(0, 0));
{
  faces := cvHaarDetectObjects(
        frame, Cascade2, Storage, 1.2, 4,
        CV_HAAR_DO_CANNY_PRUNING, CvSize(50, 50), CvSize(720, 720));
}
  // OpenCV -> delphi bitmap
  IplImageToBitmap(frame, CameraBmp);
  // 顔部赤枠
  CameraBmp.Canvas.Pen.Color := clRed;
  CameraBmp.Canvas.Pen.Width := 3;
  CameraBmp.Canvas.Brush.Style:= bsClear;
  for i := 0 to faces.total - 1 do begin
    r     := PCvRect(cvGetSeqElem(Faces, i));
    pt1.x	 := r.x;
    pt2.x := r.x + r.width;
    pt1.y := r.y;
    pt2.y	 := r.y + r.height;
    // 矩形描画
    CameraBmp.Canvas.Rectangle(Round(pt1.x), Round(pt1.y), Round(pt2.x), Round(pt2.y));
  end;

  Image1.Canvas.StretchDraw(Image1.Canvas.ClipRect, CameraBmp);
end;

end.

サンプルプログラム TBitmap To IplImage

 Webカメラの画像表示にAVICAP32.DLLを利用した場合のプログラムに、OpenCVの顔認識を追加してみました。
この場合、TBitmapをIPlImageに変換して顔認識を行います。
顔認識を行う場合、OpenCVのメモリー上データーは、左上原点にしないと、顔認識は出来ません。
 AVICAP32.DLLを利用して、TBitmapに画像を取り込む場合は、一旦クリップボードにコピーして、クリップボードから取り込む必要があります。
クリップボードからの取り込みは、TPictureのTBitmapを利用します。
クリップボードからカラー画像を取り込むと、BitmapのPixelFormatがpfDeviceとなります。
デフォルトは32bitフォーマットのようですので、pf24bitに変換してからIPlImageに変換しています。
顔認識は、32bitフォーマットでも問題ないようです。
 クリップボードを利用しているので、写真をクリップボードに貼り付ければ、写真の顔認識も可能です。


unit unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, ComCtrls, StrUtils, Clipbrd, Vcl.Buttons,
  Vcl.ExtDlgs;

type
  TForm1 = class(TForm)
    btnConnectClick: TButton;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Image1: TImage;
    Button5: TButton;
    SavePictureDialog1: TSavePictureDialog;
    Button6: TButton;
    ListBox1: TListBox;
    procedure btnConnectClickClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button6Click(Sender: TObject);
  private
    { Private 宣言 }

  public
    { Public 宣言 }

  end;

const
  WM_CAP_DRIVER_CONNECT           = WM_USER + 10;
  WM_CAP_DRIVER_DISCONNECT        = WM_USER + 11;
  WM_CAP_FILE_SET_CAPTURE_FILEA   = WM_USER + 20;
  WM_CAP_SAVEDIB                  = WM_USER + 25;
  WM_CAP_SEQUENCE                 = WM_USER + 62;
  WM_CAP_GRAB_FRAME               = WM_USER + 60;
  WM_CAP_SEQUENCE_NOFILE          = WM_USER + 63;
  WM_CAP_EDIT_COPY                = WM_USER + 30;
  WM_CAP_SET_OVERLAY              = WM_USER + 51;
  WM_CAP_SET_SCALE                = WM_USER + 53;
  WM_CAP_SET_PREVIEWRATE          = WM_USER + 52;
  WM_CAP_SET_PREVIEW              = WM_USER + 50;
  WM_CAP_STOP                     = WM_USER + 68;

  WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_USER + 6;
  WM_CAP_SET_CALLBACK_ERROR       = WM_USER + 2;
  WM_CAP_SET_CALLBACK_STATUSA     = WM_USER + 3;
  WM_CAP_SET_CALLBACK_FRAME       = WM_USER + 5;
  WM_CAP_GET_VIDEOFORMAT          = WM_USER + 44;
  WM_CAP_SET_VIDEOFORMAT          = WM_USER + 45;

  WM_CAP_DLG_VIDEOSOURCE          = WM_USER + 42;
  WM_CAP_DLG_VIDEOFORMAT          = WM_USER + 41;
  WM_CAP_DLG_VIDEODISPLAY         = WM_USER + 43;

var
  Form1: TForm1;

implementation

{$R *.dfm}
uses
  ocv.core_c, ocv.core.types_c, ocv.imgproc_c, ocv.imgproc.types_c,
  ocv.objdetect_c;

var
  CaptureWnd   : HWND;
  Filename     : ansistring;
  lpBmpInfo    : Bitmapinfo;
  Xml: ansistring;
  Cascade2: PCvHaarClassifierCascade;
  Storage: PCvMemStorage;

const
  str_Connect = 'Webカメラに接続';
  str_Disconn = '接続解除';
  CaptureLeft     = 160;
  CaptureTop      = 8;
  // webカメラに合わせて設定します
  CaptureWidth    = 1280;     // ok
  CaptureHeight   = 720;

//  CaptureWidth    = 640;      // ok
//  CaptureHeight   = 480;

//  CaptureWidth    = 640;      // ok
//  CaptureHeight   = 360;

// このサイズは動作しない原因不明
// バッファサイズが確保できないのか
//  CaptureWidth    = 1280;     // NG
//  CaptureHeight   = 960;

function capCreateCaptureWindow(WindowName: PChar;
    dwStyle: Cardinal; x,y, nWidth,nHeight: Integer;
    ParentWin: HWnd; nID: Integer): HWnd; stdcall;
     external 'AVICAP32.DLL' name 'capCreateCaptureWindowW';


function capGetDriverDescription(wDriverIndex: DWORD;
    lpszName: LPWSTR; cbName : integer;
    lpszVer : LPWSTR; cbVer  : Integer): Boolean; stdcall;
     external 'AVICAP32.DLL' name 'capGetDriverDescriptionW';

{-----------------------------------------------------------------------------
  Procedure:  BitmapToIplImage
  Arguments:  iplImg: PIplImage; bitmap: TBitmap
  Description: create a new IplImage and convert a Windows bitmap (24bit) to it
-----------------------------------------------------------------------------}
procedure BitmapToIplImage(iplImg: PIplImage; bitmap: TBitmap);
var
  dataByte: PByte;
//  dataByte: pByteArray;
  RowIn: PByte;
//  RowIn: pByteArray;
  j : integer;
  offset: integer;
begin
  try
    // 24ビットフォーマットの確認
    assert((iplImg.Depth = 8) and (iplImg.NChannels = 3),
//    assert((iplImg.Depth = 8) and (iplImg.NChannels = 4),
            'Bitmap2IplImage: Not a 24 bit color iplImage!');
    assert((bitmap.pixelFormat = pf24bit),
//    assert((bitmap.pixelFormat = pfdevice),
            'Bitmap2IplImage: Not a 24 bit color BMP bitmap!');
    // 画像の先頭ライン設定
    iplimg.Origin := IPL_ORIGIN_TL;
//    iplimg.Origin := IPL_ORIGIN_BL;
    iplImg.ChannelSeq := 'BGR';
    // 画像データーのコピー
    for j := 0 to Bitmap.Height - 1 do begin
      RowIn := Bitmap.Scanline[j];
      offset := integer(iplimg.ImageData) + iplImg.WidthStep * j;
      dataByte := pbyte(offset);
      CopyMemory(dataByte, rowin, iplImg.WidthStep);
    end;

//    RowIn := Bitmap.Scanline[bitmap.height - 1];
//    dataByte := pbytearray(iplimg.ImageData);
  {direct copy of the bitmap row bytes to iplImage rows}
//    CopyMemory(dataByte, rowin, iplimg.ImageSize);
  except

  end;
end;

procedure TForm1.btnConnectClickClick(Sender: TObject);
begin
  if (Sender as TButton).Caption = str_Connect then begin
    // デバイスの設定とハンドルの取得
    CaptureWnd := capCreateCaptureWindow('Window',
        WS_CHILD or WS_VISIBLE, CaptureLeft, CaptureTop,
        CaptureWidth, CaptureHeight, Handle, 0);
    if CaptureWnd <> 0 then begin
//      SendMessage(CaptureWnd, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);
//      SendMessage(CaptureWnd, WM_CAP_SET_CALLBACK_ERROR, 0, 0);
//      SendMessage(CaptureWnd, WM_CAP_SET_CALLBACK_STATUSA, 0, 0);

      //デバイスへの接続
      SendMessage(CaptureWnd, WM_CAP_DRIVER_CONNECT, 0, 0);

      // カメラ画像の調整
//      SendMessage(CaptureWnd, WM_CAP_DLG_VIDEOSOURCE, 0, 0);

      // カメラの解像度とフォーマットの指定
      // WM_CAP_DLG_VIDEOFORMATは、4:3 で最大サイズ640×480です。
//      SendMessage(CaptureWnd, WM_CAP_DLG_VIDEOFORMAT, 0, 0);

      // Video フォーマットの取得
      SendMessage(CaptureWnd, WM_CAP_GET_VIDEOFORMAT, sizeof(lpBmpInfo), Cardinal(@lpBmpInfo));
      // 解像度の設定
      with lpbmpInfo.bmiHeader do begin
        biWidth := CaptureWidth;
        biHeight := CaptureHeight;
        biSizeImage := biWidth * biHeight * biBitCount div 8;
//        biCompression := BI_RGB;
      end;
      // Video フォーマットの設定
      SendMessage(CaptureWnd, WM_CAP_SET_VIDEOFORMAT, sizeof(lpBmpInfo), Cardinal(@lpBmpInfo));

      //プレビュースケール 変倍有効設定
      SendMessage(CaptureWnd, WM_CAP_SET_SCALE, 1, 0);
      //プレビューのコマ数(ミリ秒)
      SendMessage(CaptureWnd, WM_CAP_SET_PREVIEWRATE, 35, 0);

      // 表示サイズの指定
      SetWindowPos(CaptureWnd, HWND_BOTTOM, 0, 0,
           CaptureWidth div 2, CaptureHeight div 2,
           SWP_NOMOVE or SWP_NOZORDER);

      // プレビュー開始
      SendMessage(CaptureWnd, WM_CAP_SET_PREVIEW, 1, 0);
    end;
    (Sender as TButton).Caption:= str_Disconn
  end
  else begin
    if CaptureWnd <> 0 then begin
      // デバイスへの接続解除
      SendMessage(CaptureWnd, WM_CAP_DRIVER_DISCONNECT, 0, 0);
      // CaptureようWindowの破棄
      DestroyWindow(CaptureWnd);
      // ハンドルのクリア
      CaptureWnd := 0;
      (Sender as TButton).Caption:= str_Connect;
    end;
  end;
end;

// クリップボードへコピー
procedure TForm1.Button1Click(Sender: TObject);
begin
  if CaptureWnd <> 0 then
    SendMessage(CaptureWnd, WM_CAP_EDIT_COPY, 1, 0 );
end;

// ファイルへ保存
// SendMessageで送るファイル名はAnsiStringの必要があります。
procedure TForm1.Button2Click(Sender: TObject);
begin
  if CaptureWnd <> 0 then begin
    SavePictureDialog1.Filter := '画像ファイル|*.bmp';
    if SavePictureDialog1.Execute then begin
      Filename := ansistring(ChangeFileExt(SavePictureDialog1.FileName,'.bmp'));
    end
    else exit;
    SendMessage(CaptureWnd, WM_CAP_SAVEDIB, 0, Cardinal(pAnsiChar(Filename)));
  end;
end;

// ファイルへの動画保存開始
// SendMessageで送るファイル名はAnsiStringの必要があります。
procedure TForm1.Button3Click(Sender: TObject);
begin
  if CaptureWnd <> 0 then begin
    SavePictureDialog1.Filter := '動画ファイル|*.avi';
    if SavePictureDialog1.Execute then begin
      Filename := ansistring(ChangeFileExt(SavePictureDialog1.FileName,'.avi'));
    end
    else exit;
    SendMessage(CaptureWnd, WM_CAP_FILE_SET_CAPTURE_FILEA, 0, Cardinal(pAnsichar (Filename)));
    SendMessage(CaptureWnd, WM_CAP_SEQUENCE, 0, 0);
  end;
end;

// 動画保存の停止
procedure TForm1.Button4Click(Sender: TObject);
begin
  if CaptureWnd <> 0 then
    SendMessage(CaptureWnd, WM_CAP_STOP, 0, 0);
end;

// クリップボードから画像貼り付け  顔検出
procedure TForm1.Button5Click(Sender: TObject);
var
  bitmm: TPicture;
  frame, fgray : PIplImage;
  faces: PCvSeq;
  pt1, pt2: TCvPoint2D32f;
  i : integer;
  r: PCvRect;
begin
  if Clipboard.HasFormat(CF_DIB) then begin
    bitmm := TPicture.Create;
    try
      // クリップボードから画像取得
      bitmm.Bitmap.Assign(Clipboard);
      // デフォルトはpfDevice (pf32bit)
      // 24ビットフォーマットに変換
      bitmm.Bitmap.PixelFormat := pf24bit;
      // Opencv IplImage 24ビットフォーマット設定
      frame := cvCreateImage(cvSize(bitmm.Bitmap.Width, bitmm.Bitmap.Height), IPL_DEPTH_8U, 3);
//      frame := cvCreateImage(cvSize(bitmm.Bitmap.Width, bitmm.Bitmap.Height), IPL_DEPTH_8U, 4);
//      frame.Origin := IPL_ORIGIN_BL;
      // bitmap to IplImage 変換
      BitmapToIplImage(frame, bitmm.Bitmap);
      // カラーグレー変換
      fgray := cvCreateImage(cvGetSize (frame), IPL_DEPTH_8U, 1);
      cvCvtColor(frame, fgray, CV_BGR2GRAY);
      // グレーヒストグラム調整
      cvEqualizeHist(fgray, fgray);

      // メモリストレージをクリア
      cvClearMemStorage(Storage);
      // 画像から物体検出
      faces := cvHaarDetectObjects(fgray, Cascade2, Storage, 1.2, 3,
                                    CV_HAAR_DO_CANNY_PRUNING, CvSize(50, 50), CvSize(0, 0));
      bitmm.Bitmap.Canvas.Pen.Color	:= clRed;
      bitmm.Bitmap.Canvas.Pen.Width	:= 4;
      bitmm.Bitmap.Canvas.Brush.Style:= bsClear;
      for i := 0 to faces.total - 1 do begin
        r	 := PCvRect(cvGetSeqElem(Faces, i));
        pt1.x := r.x;
        pt2.x := r.x + r.width;
        pt1.y := r.y;
        pt2.y := r.y + r.height;
        // 矩形描画
        bitmm.Bitmap.Canvas.Rectangle(Round(pt1.x),Round(pt1.y), Round(pt2.x), Round(pt2.y));
      end;

      Image1.Canvas.StretchDraw(rect(0, 0, CaptureWidth div 4, CaptureHeight div 4), bitmm.Bitmap);
    finally
      bitmm.Free;
    end;
  end;
end;

// ドライバーバージョンの取得
procedure TForm1.Button6Click(Sender: TObject);
var Indx : Cardinal;
    szName,
    szVersion: array[0..MAX_PATH] of Char;
begin
  ListBox1.Clear;
  for Indx := 0 to 9 do begin
    if capGetDriverDescription(Indx, @szName, sizeof(szName), @szVersion, sizeof(szVersion)) then begin
      ListBox1.Items.Add(szName + ' (' + szVersion + ')');
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  top := (screen.Height - Height) div 2;
  left := (screen.Width - Width) div 2;
  btnConnectClick.Caption := str_Connect;
  CaptureWnd := 0;
  Storage := cvCreateMemStorage(0);
  Xml := 'haarcascade_frontalface_alt.xml';
//  Xml := 'haarcascade_frontalface_default.xml';  // default
  Cascade2 := PCvHaarClassifierCascade(cvLoad(PAnsiChar(Xml), nil, nil, nil));
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if CaptureWnd <> 0 then begin
    SendMessage(CaptureWnd, WM_CAP_DRIVER_DISCONNECT, 0, 0);
    DestroyWindow(CaptureWnd);
  end;
end;

end.

    download DelphiVCLFacedetect.zip

      画像処理一覧へ戻る

      最初に戻る