使用COM和Python通过DirectShow访问网络摄像头



我想使用DirectShow的IAMVideoProcAmp获得对网络摄像头属性的低级访问。

有几个 Python 模块(pywin32pywintypescomtypeswin32compythoncom(用于此上下文,它们似乎以某种方式相关。但我不知道从哪里开始。

我找到了一些例子(这里,这里,这里(,但我无法弄清楚如何让 IID/CLSID 像

import win32com.client
clsid='{9BA05972-F6A8-11CF-A442-00A0C90A8F39}'
ShellWindows=win32com.client.Dispatch(clsid)

或带有明确的名称,例如

import win32com.client
xl = win32com.client.Dispatch("Excel.Application")

from comtypes import client, GUID
graph = client.CreateObject(some_CLSID)
graph.QueryInterface(...)

有人可以帮助我吗?

我找到了另一个示例(dshow.py(,但它有一些我找不到的依赖项(interfacesuuids(。

Microsoft的此页面将过程列为

在 IAMVideoProcAmp 接口的捕获筛选器上调用查询接口。

查询 IAMCameraControl 的捕获筛选器。

并为此陈述了一些C++代码:

// Query the capture filter for the IAMVideoProcAmp interface.
IAMVideoProcAmp *pProcAmp = 0;
hr = pCap->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp);
hr = m_pProcAmp->GetRange(VideoProcAmp_Brightness, &Min, &Max, &Step,
&Default, &Flags);

编辑: 我终于找到了一些到目前为止看起来不错的代码:

哈拉科

它似乎完全符合我想要编写的内容,并使用了一些元素 直接显示(见这里(:

from comtypes.gen.DirectShowLib import (FilterGraph, CaptureGraphBuilder2, ...)

jaraco.video声称是"使用ctypes和comtypes的纯Python中VideoCapture模块的端口"。

它使用DirectShow.tlb文件(无论是什么(来获取定义 成商品

类型库 (.tlb( 是一个二进制文件,用于存储有关 COM 或 DCOM 对象的属性和方法,其形式为 其他应用程序可在运行时访问。

标识复制代码所需的值

再看一眼您帖子末尾的代码摘录,我意识到您只需要 IID 而不是 CLSID 即可IAMVideoProcAmp获取它的实例。

查看这个 strmif.h 源代码的第 8733 行,标记为接口的必需标头,我发现IID_IAMVideoProcAmpC6E13360-30AC-11d0-A18C-00A0C9118956

在 strmif.h 的这一部分上方,您可以确定哪些整数对应于tagVideoProcAmpProperty枚举中的哪些属性,例如0forVideoProcAmp_Brightness。在 strmif.h 的这一部分下,您可以确定哪些整数对应于 VTableIAMVideoProcAmpVtbl中的哪些函数,例如3forGetRange。我不熟悉如何在 Python 中与 COM 对象交互,但在 Java 中,您需要确定这些属性和函数索引,以便复制演示如何获取IAmVideoProcAmp实例的C++代码摘录。

获取IAMVideoProcAmp实例

您可能已经注意到,C++代码摘录调用了名为pCap的内容QueryInterface,并指出您需要"查询 IAMVideoProcAmp 接口的捕获筛选器"。您链接的文章的这个兄弟姐妹解释了如何做到这一点:

若要为设备创建 DirectShow 捕获筛选器,请调用 IMoniker::BindToObject 方法来获取 IBaseFilter 指针。然后调用 IFilterGraph::AddFilter 将筛选器添加到筛选器图中:

IBaseFilter *pCap = NULL;
hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap);
if (SUCCEEDED(hr))
{
hr = m_pGraph->AddFilter(pCap, L"Capture Filter");
}

现在您知道如何获取pCap,您注意到您需要一个名为pMoniker的东西,这在同一篇文章的前面已经定义。代码相当长,所以我在这里省略它。

在 Python 中完成所有这些操作

正如我之前提到的,我从未使用过任何Python COM库,所以我不能轻易地举出一个示例,但是您的目标应该是在Python中复制C++示例中的函数调用,以获取IAMVideoProcAmp的实例并对其进行修改以满足您的需求。

我终于找到了一些工作的示例库:

哈拉科

它完全符合我想要实现的目标,并使用了一些元素 直接显示(见这里(:

from comtypes.gen.DirectShowLib import (FilterGraph, CaptureGraphBuilder2, ...)

jaraco.video声称是"使用ctypes和comtypes的纯Python中VideoCapture模块的端口"。

它使用DirectShow.tlb文件(无论是什么(来获取定义 成商品

类型库 (.tlb( 是一个二进制文件,用于存储有关 COM 或 DCOM 对象的属性和方法,其形式为 其他应用程序可在运行时访问。

导入__init__.py自动生成,可以轻松使用:

from api.objects import ..., IMediaControl, IAMVideoProcAmp, IAMCameraControl, ...

并且可以使用

def _get_camera_control(self):
return self._get_graph_builder_interface(IAMCameraControl)
def get_camera_control_property(self, i):
video_properties = self._get_camera_control()
return video_properties.Get(i)

然后,您可以将这些功能与文档中所述的enum结合使用,例如

# CameraControl_Exposure = 4
print(d.get_camera_control_property(4))

最新更新