5

我正在开发一个 C++ 应用程序,它应该使用 USB 相机来捕捉高分辨率照片。它应该与 Windows 10 中的相机应用程序具有相同的行为。我正在尝试使用 DirectShow 来执行此操作。现在我只能拍摄延迟的高分辨率照片或及时但低分辨率的照片。此外,我对 MS 文档感到非常困惑,很多东西都被弃用了,也没有提到替代它们的东西。我将描述我绝望的步骤,等待有人能够告诉我一条路。

让我们从头开始...

我从搜索合适的库开始,对 Window 中的视频捕获一无所知。经过一番谷歌搜索后,我发现有四个主要的库用于在 Windows 中捕获视频。

  1. 适用于 Windows 的视频
  2. 直接秀
  3. 视窗媒体基金会
  4. 开放式CV

让我们观察:

  1. Video for Windows
    不幸的是,这个库被标记为已弃用,但它似乎仍然有效。我写了“不幸的是”,因为我认为这是唯一易于使用的。从摄像头查看视频只需要几行代码。我在这里唯一想念的是“TakePhoto”功能。您可以使用 VFW 将视频或单帧捕获到 avi 文件。还是我错过了什么?

  2. DirectShow
    这是一个复杂得多的库。您需要数百行代码才能看到视频预览。但是您可以在 MS Docs 上获得此代码。好的,现在我有一个视频预览,我只需要拍照。人们会期望这应该只是一个函数调用。但是功能在哪里?我没有找到它。

您可以简单地使用GetCurrentImagefrom ,IVMRWindowlessControl但这仅需要从低分辨率预览中提取一帧。如果您为预览设置更高的分辨率,则视频不流畅。

我可以实现的最佳方法来自一篇名为“从静止图像引脚捕获图像”的文章,可在此处https://docs.microsoft.com/en-us/windows/desktop/directshow/capturing-an-image-from-静止图像针。当我找到这个网站时,我以为我赢了,我的任务也快完成了。但事实并非如此。

本文给您的第一个建议是不要使用它:“从设备获取静止图像的推荐方法是使用 Windows Image Acquisition (WIA) API。有关更多信息,请参阅平台中的“Windows Image Acquisition” SDK 文档。但是,您也可以使用 DirectShow 来捕获图像。” 我试图探索WIA。但这在 Vista 上停止工作。我继续研究这篇文章。
一切似乎都很清楚,但您需要实现您的类继承ISampleGrabberCB标记为已弃用此处https://docs.microsoft.com/en-us/windows/desktop/directshow/isamplegrabbercb。为什么????在哪里可以找到一些替代品?
我在这里找到了一个可以接受的解决方案https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/2ab5c212-5824-419d-b5d9-7f5db82f57cd/qedith-missing-in-current-windows-sdk-v70?forum=windowsdirectshowdevelopment。您需要添加来自旧 SDK 的头文件。(顺便说一句,这是一个近十年前的建议。)在我用这个标题编译应用程序后,我能够阅读高分辨率图片,但我需要等待几秒钟,这是不可接受的。我知道问题不在相机中,因为它在相机应用程序中有效。此外,图像是在函数中获得的,SampleCB而不是BufferCB在某种奇怪的格式中。我可以将其保存为 jpg,但压缩得不够。

  1. Windows Media Foundation
    我认为 MS 不喜欢程序员,这就是它发布 WMF 的原因。我完全不懂。我找到了本教程https://www.dreamincode.net/forums/topic/347938-a-new-webcam-api-tutorial-in-c-for-windows/。它可以工作,但它只存储预览中的一帧,这不是我想要的。
    接下来我在 MS Docs 上探索了一些 WMF 接口。IMFCapturePhotoSink 接口应该做的事情。但是如何实现它。文档没用。

  2. OpenCV
    在我的研究过程中,我还发现了这个库。但同样我无法拍摄高分辨率照片。它只存储预览中的一帧。

有人能告诉我我应该关注什么吗?我相信这不会那么困难。网络摄像头有成千上万的应用程序。其他程序员如何实现它们?我怎么了?我想找到一种简单的方法来实现一项简单的任务。非常感谢您的帮助。

4

2 回答 2

0

您的问题与主题无关-问题必须与代码有关-但多年前我遇到了类似的问题,并且找到了解决方案:

DirectShow被声明为 Windows 10 已弃用,并且在支持 USB 网络摄像头方面存在问题。在 Windows 10 中,只有 Media Foundation 支持的 USB 视频类。

因此,我围绕 Media Foundation 代码编写了一个简单的 C++ 包装器,它简化了使用 Media Foundation 从 Windows 7 和 8 上的网络摄像头捕获视频的原始图像的获取

此外,还有CaptureManager SDK项目——它是 DLL COM 组件,具有简单的接口、强大的功能和许多 C++、Python、C#、Java 的演示程序。

于 2018-10-14T01:30:58.063 回答
0

感谢叶夫根尼。

概括:

  1. 下载CaptureEngine 视频捕获示例

  2. 编辑CaptureManager::TakePhoto方法。CreatePhotoMediaType(pMediaType, &pMediaType2);在行前添加代码以查找最高分辨率的媒体类型

将照片流设置为最高分辨率的额外代码:

DWORD dwMediaTypeIndex = 0;
UINT32 maxSize = 0;
DWORD maxSizeIndex = 0;
while (1) {
    IMFMediaType* pMediaType = NULL;
    hr = pSource->GetAvailableDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO, dwMediaTypeIndex, &pMediaType);
    if (hr == MF_E_NO_MORE_TYPES)
        break;

    UINT32 w, h;
    MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &w, &h);
    UINT32 size = w * h;
    if (size > maxSize) {
        maxSize = size;
        maxSizeIndex = dwMediaTypeIndex;
    }
    SafeRelease(&pMediaType);
    dwMediaTypeIndex++;
}

SafeRelease(&pMediaType);
pSource->GetAvailableDeviceMediaType((DWORD)MF_CAPTURE_ENGINE_PREFERRED_SOURCE_STREAM_FOR_PHOTO, maxSizeIndex, &pMediaType);
于 2018-10-16T15:56:54.450 回答