簡體   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