繁体   English   中英

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

[英]Take high resolution photo from USB camera in Windows (C++)

我正在开发一个C ++应用程序,该应用程序应使用USB相机捕获高分辨率照片。 它的行为应与Windows 10中的“相机”应用程序相同。我正在尝试使用DirectShow。 现在,我只能拍摄延迟的高分辨率照片,或者只能及时拍摄但分辨率低的照片。 另外,我对MS文档感到非常困惑,不赞成使用许多功能,没有地方提到用什么代替它们。 我将描述我绝望的步骤,等待有可能向我展示方法的人。

让我们从头开始...

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

  1. Windows视频
  2. DirectShow的
  3. Windows Media基础
  4. OpenCV的

让我们观察一下:

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

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

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

我可以实现的最佳方法是来自一篇名为“从静止图像图钉捕获图像”的文章, 网址为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的类, ISampleGrabberCB在此处https://docs.microsoft.com/zh-cn/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基础
    我认为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中,只有Media Foundation支持USB Video Class。

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

此外,还有一个项目CaptureManager SDK-它是DLL COM组件,具有简单的界面,强大的功能以及许多基于C ++,Python,C#,Java的演示程序。

感谢Evgeny。

概括:

  1. 下载CaptureEngine视频捕获样本

  2. 编辑CaptureManager::TakePhoto方法。 CreatePhotoMediaType(pMediaType, &pMediaType2);之前添加代码以查找最高分辨率的媒体类型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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM