为什么网络摄像头图像比从其他应用程序启动时显得更暗?

发布于 2025-01-05 17:29:15 字数 1625 浏览 0 评论 0原文

我正在使用 Windows API 使用附加的网络摄像头拍照。

除了拍摄的图片非常暗之外,一切正常。如果我在另一个应用程序中启动网络摄像头,然后使用我的应用程序进行捕获,则一切正常。我做错了什么?

这是我使用的代码:

procedure TWebCam.Execute; //different thread
var
  hand: THandle;
  fname: AnsiString;
const
  WM_CAP_START = $0400;
  WM_CAP_DRIVER_CONNECT = $0400 + 10;
  WM_CAP_DRIVER_DISCONNECT = $0400 + 11;
  WM_CAP_SAVEDIB = $0400 + 25;
  WM_CAP_GRAB_FRAME = $0400 + 60;
  WM_CAP_STOP = $0400 + 68;
  WM_CAP_SET_PREVIEW = WM_CAP_START + 50;
  WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52;
  WM_CAP_SET_SCALE = WM_CAP_START + 53;
begin
  FreeOnTerminate := True;
  fname := AnsiString(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) +
    'capture.bmp');
  if FileExists(String(fname)) then DeleteFile(string(fname));
  hand := capCreateCaptureWindowA('CapWindow32', WS_CHILD and WS_VISIBLE, 0, 0,
    0, 0, frmMain.Handle, 0);
  if hand <> 0 then
  begin
    if SendMessage(hand, WM_CAP_DRIVER_CONNECT, 0, 0) <> 0 then
    begin
      SendMessage(hand,WM_CAP_SET_PREVIEWRATE,66,0); //tried some stuff that are not required but without any success
      SendMessage(hand, WM_CAP_SET_PREVIEW, 1, 0);
      Sleep(5000);
      SendMessage(hand, WM_CAP_GRAB_FRAME, 0, 0);
      SendMessage(hand, WM_CAP_SAVEDIB, 0, NativeInt(PAnsichar(fname)));
      SendMessage(hand, WM_CAP_DRIVER_DISCONNECT, 0, 0);
      SendMessage(hand, $0010, 0, 0);
      SendMessage(frmMain.Handle,WM_USER + 24,0,0); //notify main thread
    end
    else
    begin
      SendMessage(hand, $0010, 0, 0);
      Synchronize(NoWebcam);
    end;
  end
  else
    Synchronize(NoWebcam);
end;

I am using the Windows API to take a picture with the attached webcam.

All works fine except the picture captured is very dark. If I start the webcam in another application and then I capture with my application, all works fine. What am I doing wrong?

Here is the code I use:

procedure TWebCam.Execute; //different thread
var
  hand: THandle;
  fname: AnsiString;
const
  WM_CAP_START = $0400;
  WM_CAP_DRIVER_CONNECT = $0400 + 10;
  WM_CAP_DRIVER_DISCONNECT = $0400 + 11;
  WM_CAP_SAVEDIB = $0400 + 25;
  WM_CAP_GRAB_FRAME = $0400 + 60;
  WM_CAP_STOP = $0400 + 68;
  WM_CAP_SET_PREVIEW = WM_CAP_START + 50;
  WM_CAP_SET_PREVIEWRATE = WM_CAP_START + 52;
  WM_CAP_SET_SCALE = WM_CAP_START + 53;
begin
  FreeOnTerminate := True;
  fname := AnsiString(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0))) +
    'capture.bmp');
  if FileExists(String(fname)) then DeleteFile(string(fname));
  hand := capCreateCaptureWindowA('CapWindow32', WS_CHILD and WS_VISIBLE, 0, 0,
    0, 0, frmMain.Handle, 0);
  if hand <> 0 then
  begin
    if SendMessage(hand, WM_CAP_DRIVER_CONNECT, 0, 0) <> 0 then
    begin
      SendMessage(hand,WM_CAP_SET_PREVIEWRATE,66,0); //tried some stuff that are not required but without any success
      SendMessage(hand, WM_CAP_SET_PREVIEW, 1, 0);
      Sleep(5000);
      SendMessage(hand, WM_CAP_GRAB_FRAME, 0, 0);
      SendMessage(hand, WM_CAP_SAVEDIB, 0, NativeInt(PAnsichar(fname)));
      SendMessage(hand, WM_CAP_DRIVER_DISCONNECT, 0, 0);
      SendMessage(hand, $0010, 0, 0);
      SendMessage(frmMain.Handle,WM_USER + 24,0,0); //notify main thread
    end
    else
    begin
      SendMessage(hand, $0010, 0, 0);
      Synchronize(NoWebcam);
    end;
  end
  else
    Synchronize(NoWebcam);
end;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

注定孤独终老 2025-01-12 17:29:15

我讨厌回答自己的问题,但也许将来有人会发现它有用。

问题是网络摄像头在启动时会逐渐调整其亮度,因此您必须首先捕获一些虚拟帧才能获得正常的图片...这是我现在使用的:

var
 i : Integer;
...
begin
...
   for i := 0 to 24 do
   begin
     SendMessage(hand, WM_CAP_GRAB_FRAME, 0, 0);
     Sleep(200)
   end;
...
end;

工作起来就像一个魅力,有点 hacky,我希望有一个 WaitForInputIdle设备也存在该功能...

I hate to give my own questions an answer but maybe someone will find it useful in the future.

The thing is that the webcam adjusts its luminosity progressively when it starts, so you must first capture some dummy frames to get a normal picture... Here is what I use now:

var
 i : Integer;
...
begin
...
   for i := 0 to 24 do
   begin
     SendMessage(hand, WM_CAP_GRAB_FRAME, 0, 0);
     Sleep(200)
   end;
...
end;

Works like a charm, kind of hacky, I wish a WaitForInputIdle function exist for devices too...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文