在Windows(C++)中使用USB相机拍摄高分辨率照片



我正在开发一个C++应用程序,该应用程序应该使用USB相机来拍摄高分辨率照片。它应该具有与Windows 10中的Camera应用程序相同的行为。我正在尝试使用DirectShow进行此操作。现在我只能拍摄延迟的高分辨率照片或及时拍摄低分辨率的照片。此外,我对MS文档感到非常困惑,很多东西都被弃用了,没有提到是什么取代了它们。我会描述我绝望的脚步,等待有人能给我指路。

让我们从头开始。。。

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

  1. Windows视频
  2. DirectShow
  3. Windows Media Foundation
  4. OpenCV

让我们观察一下:

  1. Windows视频
    很遗憾,此库被标记为已弃用,但它似乎仍然有效。我写了"不幸",因为我认为这是唯一容易使用的。从摄像机上观看视频只需要几行代码。我唯一怀念的是"拍照"功能。您可以使用VFW来捕获视频或单个帧到avi文件。还是我错过了什么?

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

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

我能实现的最好方法是从一篇名为"从静止图像引脚捕获图像"的文章中获得https://learn.microsoft.com/en-us/windows/desktop/directshow/capturing-an-image-from-a-still-image-pin.当我找到这个网站时,我以为我赢了,我的任务几乎完成了。但事实并非如此。

这篇文章给你的第一个建议是不要使用它:"从设备获取静态图像的推荐方法是使用Windows图像采集(WIA)API。有关更多信息,请参阅平台SDK文档中的"Windows图像采集"。但是,你也可以使用DirectShow来捕获图像。">我尝试过探索WIA。但这在Vista上停止了工作。我继续研究这篇文章
一切似乎都很清楚,但您需要实现继承此处标记为弃用的ISampleGrabberCB的类https://learn.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
    在我的研究过程中,我也发现了这个库。但我还是不能拍高分辨率的照片。它只存储预览中的一帧。

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

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

DirectShow被宣布为Windows 10不推荐使用,并且它在支持USB网络摄像头方面存在问题。在Windows 10中,有一个USB视频类,只有Media Foundation支持。

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

此外,还有CaptureManagerSDK项目,它是一个DLL COM组件,具有简单的接口、巨大的功能,并在C++、Python、C#、Java上有许多演示程序。

感谢叶夫根尼。

重述:

  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);

最新更新