Skip to main content
 首页 » 编程设计

delphi之如何使用 DSPack 和 Delphi 5 从网络摄像头捕获并保存到文件

2024年02月27日18yjmyzz

现在我正在尝试使用 Delphi 5 编写一个程序来从网络摄像头拍照。 我使用delphi 5 和DSPack 2.3.1,因为很多人都建议这样做,是的,这是我第一次使用delphi 进行多媒体编程。

我已经能够列出并添加动态连接到我的计算机的相机。我还可以显示网络摄像头“看到”的内容,打开视频并捕获它。 但现在我无法从网络摄像头捕获图片。

我有一个TImage,我将其命名为“Image”,用于检查图片是否被捕获。当我使用代码打开视频并捕获它时,它显示在 TImage 中。但是当我 try catch 网络摄像头时,它只是空白并且没有捕获任何内容。我保存的文件也是空白的。

有人可以检查一下我的代码的哪一部分出了问题吗? 先谢谢了...

这是我的代码的一部分

var SysDev: TSysDevEnum; 
    FotoBitmap: TBitmap; 
 
implementation 
 
{$R *.DFM} 
 
procedure Form1.FormCreate(Sender: TObject); 
var 
  i: integer; 
  Device: TMenuItem; 
begin 
  SysDev:= TSysDevEnum.Create(CLSID_VideoInputDeviceCategory); 
  if SysDev.CountFilters > 0 then 
    for i := 0 to SysDev.CountFilters - 1 do 
    begin 
      Device := TMenuItem.Create(Devices); 
      Device.Caption := SysDev.Filters[i].FriendlyName; 
      Device.Tag := i; 
      Device.OnClick := OnSelectDevice; 
      Devices.Add(Device); 
    end; 
end; 
 
procedure Form1.FormCloseQuery(Sender: TObject; 
  var CanClose: Boolean); 
begin 
  SysDev.Free; 
  FilterGraph.ClearGraph; 
  FilterGraph.Active := false; 
end; 
 
procedureForm1.OnSelectDevice(sender: TObject); 
var 
  CaptureGraph: ICaptureGraphBuilder2; 
  SourceFilter, DestFilter: IBaseFilter; 
begin 
  FilterGraph.ClearGraph; 
  FilterGraph.Active := false; 
 
  Filter.BaseFilter.Moniker := SysDev.GetMoniker(TMenuItem(Sender).tag); 
  Filter.FilterGraph := FilterGraph; 
 
  FilterGraph.Active := true; 
 
  FilterGraph.QueryInterface(ICaptureGraphBuilder2, CaptureGraph); 
 
  Filter.QueryInterface(IBaseFilter, SourceFilter); 
 
  VideoWindow.QueryInterface(IBaseFilter, DestFilter); 
 
  if Filter.BaseFilter.DataLength > 0 then 
    CaptureGraph.RenderStream(nil, nil, SourceFilter, nil, DestFilter); 
 
  FilterGraph.Play; 
  CaptureGraph := nil; 
  SourceFilter := nil; 
  DestFilter   := nil; 
end; 
 
procedure Form1.SnapshotClick(Sender: TObject); 
var dir : String; 
begin 
  if edt_nama_foto.Text <> '' then begin 
    dir := ExtractFilePath(Application.ExeName); 
    FotoBitmap := TBitmap.Create; 
 
    try 
      SampleGrabber.GetBitmap(FotoBitmap); 
      SampleGrabber.GetBitmap(Image.Picture.Bitmap); 
      showmessage(dir + 'Image\Foto\' + edt_nama_foto.Text + '.bmp'); 
      FotoBitmap.SaveToFile(dir + 'Image\Foto\' + edt_nama_foto.Text + '.bmp'); 
    finally 
      FotoBitmap.Free; 
    end; 
  end; 
end; 
 
procedure Form1.btn_batalClick(Sender: TObject); 
begin 
  modalresult:=mrCancel; 
end; 
 
procedure Form1.btn_simpanClick(Sender: TObject); 
begin 
  If CheckbeforeOK then 
  begin 
    ModalResult :=mrOK; 
  end else begin 
    ModalResult := mrNone; 
  end; 
end; 
 
function Form1.CheckbeforeOK:Boolean; 
var flag:boolean; 
    MasterDataSet:TQuery; 
begin 
  Flag:=True; 
 
  if flag and not(checkedit(nil, nil, edt_nama_foto, edt_nama_foto.Text, 'Nama Foto')) 
  then begin 
    flag := False; 
  end else begin 
    Snapshot.Click; 
  end; 
  Result := flag; 
end; 
 
procedure Form1.SampleGrabberBuffer(sender: TObject; 
  SampleTime: Double; pBuffer: Pointer; BufferLen: Integer); 
begin 
  Image.Picture.Bitmap.Canvas.Lock; 
  try 
    SampleGrabber.GetBitmap(Image.Picture.Bitmap, pBuffer, BufferLen); 
  finally 
    Image.Picture.Bitmap.Canvas.UnLock; 
  end; 
end; 
 
end. 

请您参考如下方法:

将视频帧“传输”为图像对象的对象是SampleGrabber:

SampleGrabber.GetBitmap(Image.Picture.Bitmap, pBuffer, BufferLen);

但是,在构建它时需要将其插入到过滤器图表中,并且您显然没有在 OnSelectDevice 中执行此操作:那里没有提及 SampleGrabber根本不。您需要将其包含到 RenderStream 调用中,或者以其他方式将其插入其中,以便视频通过它进行流式传输,并且您的回调称为将数据复制到 TImage 中。