视频问题,从摄像头流中捕捉一张图片。用ISampleGrabber方法

Atomictry 2004-10-28 07:43:07
用ISampleGrabber方法。 显示窗口已经能显示图像。

HRESULT StartDisplay(HWND hwnd) // 显示
{
HRESULT hr = S_OK;
hr = BuilderSendGraph(); // 建立Graph

//Create Display Windows
pSendWindow->put_Owner((OAHWND)hwnd);
pSendWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
pSendWindow->SetWindowPosition(0,0,300,300);
pSendWindow->put_Visible(OATRUE);

//Begin Send
hr = pSendControl->Run();
SnapStill(); // 此处开始抓取一张图片
}

以下是SnapStill()函数:
HRESULT SnapStill()
{
HRESULT hr;
long cbBuffer = 0;

/********** -->>>>>这句有问题************/
hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);

char *pBuffer = new char[cbBuffer];
if (!pBuffer) {
// Out of memory. Return an error code.
}
hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
if(FAILED(hr)) return E_FAIL;

...... // 生成bmp文件
}

BuilderSendGraph()中的函数实现:
HRESULT BuilderSendGraph()
{
// 建立 Filter Graph
hr = CoCreateInstance((REFCLSID)CLSID_FilterGraph,NULL,
CLSCTX_INPROC_SERVER,
(REFIID)IID_IGraphBuilder,
(void**)&pSendGraph);

// 建立 Caputer Filter
hr = CoCreateInstance(CLSID_CaptureGraphBuilder2,NULL,
CLSCTX_INPROC,IID_ICaptureGraphBuilder2,
(void**)&pCaputerBuilder);

hr = pCaputerBuilder->SetFiltergraph(pSendGraph);

// 建立 SampleGrabber Filter
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pGrabberSample)

// 把pCaputerFilter和pGrabberSample加入filter
hr = pSendGraph->AddFilter(pCaputerFilter,L"Caputer Filter");
hr = pSendGraph->AddFilter(pGrabberSample, L"Sample Grabber");

// 查询各个接口
hr=pSendGraph->QueryInterface(IID_IMediaControl,(void**)&pSendControl);
hr=pSendGraph->QueryInterface(IID_IVideoWindow,(void**)&pSendWindow);
hr=pSendGraph->QueryInterface(IID_IMediaEvent,(void**)&pSendEvent);
hr=pGrabberSample->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);

/***请问这里是不是还需要什么代码?***/

// 根据色深设置媒体类型
AM_MEDIA_TYPE mt;
ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
HDC hdc = GetDC(NULL);
int iBitDepth = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(NULL, hdc);
mt.majortype = MEDIATYPE_Video;
switch (iBitDepth)
{
case 8:
mt.subtype = MEDIASUBTYPE_RGB8;
break;
case 16:
mt.subtype = MEDIASUBTYPE_RGB555;
break;
case 24:
mt.subtype = MEDIASUBTYPE_RGB24;
break;
case 32:
mt.subtype = MEDIASUBTYPE_RGB32;
break;
default:
return E_FAIL;
}
hr = pGrabber->SetMediaType(&mt);
if(FAILED(hr)) return E_FAIL;

// 显示本地视频
hr = pCaputerBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,NULL,pCaputerFilter,NULL,NULL);
if(FAILED(hr)) return S_FALSE;

// 准备一祯
hr = pGrabber->SetOneShot(TRUE);
hr = pGrabber->SetBufferSamples(TRUE);
}

问题出在SnapStill()函数中的第一个GetCurrentBuffer处:
cbBuffer得到的值为空,这里hr返回的值VFW_E_WRONG_STATE,
msdn说:The filter has not received any samples yet. To deliver a sample, run or pause the graph.
但是在StartDisplay()中已经hr = pSendControl->Run();了.

请各位兄弟,前辈帮帮忙, 查了一个星期的资料了,又郁闷一个星期了。 谢谢~
...全文
1035 11 打赏 收藏 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
ywybetter 2005-01-11
  • 打赏
  • 举报
回复
楼主是好人
先顶一下
Atomictry 2004-11-04
  • 打赏
  • 举报
回复
经过n天努力,问题解决,发现网上使用ISampleGrabber接口进行捕获的代码好少,感觉又不是关键技术,DirectShow已经包含大部分代码,怎么都藏着?
期间还用VFW的宏来做,修改分辨率后本地可以正常显示各种分辨率,可惜拍照又有问题,最后作罢,还是用ISampleGrabber比较彻底。

现总结如下:
关键字: 视频 捕获 拍照 ISampleGrabber

函数说明
/*
* 本地显示函数
*/
HRESULT StartDisplay(HWND hwnd);

/*
* 建立链路
*/
HRESULT BuilderGraph()

/*
* 拍照
*/
HRESULT SnapStill()

/*
* 修改摄像头分辨率,色深,频率
*/
BOOL SetFormat(ICaptureGraphBuilder2* pBuilder, IBaseFilter* pCap, long lWidth, long lHeight, unsigned short iColorBit, __int64 iRate )

HRESULT StartDisplay(HWND hwnd)
{
HRESULT hr = S_OK;
hr = BuilderGraph();
if(hr==S_FALSE) return S_FALSE;

//Create Display Windows
pSendWindow->put_Owner((OAHWND)hwnd);
pSendWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
pSendWindow->SetWindowPosition(0,0,250,250);
pSendWindow->put_Visible(OATRUE);

hr = pGrabber->SetOneShot(FALSE);
hr = pGrabber->SetBufferSamples(TRUE);

//Begin display
hr=pSendControl->Run();
Sleep(500);
SnapStill();

return S_OK;
}

HRESULT BuilderGraph()
{
HRESULT hr=S_OK;

pSendGraph = NULL;
pCaputerFilter = NULL;
pCaputerBuilder = NULL;
pSendWindow = NULL;
pSendControl = NULL;
pSendEvent = NULL;
pGrabberSample = NULL;

//1.Builder Filter Graph
hr=CoCreateInstance((REFCLSID)CLSID_FilterGraph,NULL,
CLSCTX_INPROC_SERVER,
(REFIID)IID_IGraphBuilder,
(void**)&pSendGraph);
if(FAILED(hr)) return S_FALSE;

//2.Builder Caputer Filter
hr=CoCreateInstance(CLSID_CaptureGraphBuilder2,NULL,
CLSCTX_INPROC,IID_ICaptureGraphBuilder2,
(void**)&pCaputerBuilder);
if(FAILED(hr)) return S_FALSE;

//3.Builder SampleGrabber Filter
hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&pGrabberSample);
if(FAILED(hr)) return S_FALSE;

hr=pCaputerBuilder->SetFiltergraph(pSendGraph);
if(FAILED(hr)) return S_FALSE;

//Find Caputer Filter
hr=FindCaputerDevice();
if(FAILED(hr)) {
SAFE_RELEASE(pCaputerBuilder);
SAFE_RELEASE(pSendGraph);
return S_FALSE;
}

hr = pSendGraph->AddFilter(pNetSend,NULL);
hr = pSendGraph->AddFilter(pCaputerFilter,L"Caputer Filter");
hr = pSendGraph->AddFilter(pCompressor,L"Compressor Filter");
hr = pSendGraph->AddFilter(pGrabberSample, L"Sample Grabber");

hr=pSendGraph->QueryInterface(IID_IMediaControl,(void**)&pSendControl);
if(FAILED(hr)) return S_FALSE;

hr=pSendGraph->QueryInterface(IID_IVideoWindow,(void**)&pSendWindow);
if(FAILED(hr)) return S_FALSE;

hr=pSendGraph->QueryInterface(IID_IMediaEvent,(void**)&pSendEvent);
if(FAILED(hr)) return S_FALSE;

hr=pGrabberSample->QueryInterface(IID_ISampleGrabber, (void**)&pGrabber);
if(FAILED(hr)) return S_FALSE;

// 修改分辨率
SetFormat(pCaputerBuilder, pCaputerFilter, 640, 480, 24, 30);

//Display local video
hr=pCaputerBuilder->RenderStream(&PIN_CATEGORY_PREVIEW,NULL,pCaputerFilter,pGrabberSample,NULL);
if(FAILED(hr)) return S_FALSE;

return S_OK;
}

HRESULT SnapStill()
{
HRESULT hr;

long cbBuffer = 0;
hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
if(FAILED(hr)) return E_FAIL;

char *pBuffer = new char[cbBuffer];
if (!pBuffer) {
// Deal Out of memory. Return an error code.
}
hr = pGrabber->GetCurrentBuffer(&cbBuffer, (long*)pBuffer);
if(FAILED(hr)) return E_FAIL;

//生成Bitmap
AM_MEDIA_TYPE mt;
hr = pGrabber->GetConnectedMediaType(&mt);
if (FAILED(hr)) return E_FAIL;

VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER*)mt.pbFormat;
if(pVideoHeader==NULL) return E_FAIL;

BITMAPINFO BitmapInfo;
ZeroMemory(&BitmapInfo, sizeof(BitmapInfo));
CopyMemory(&BitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader), sizeof(BITMAPINFOHEADER));

HBITMAP hBitmap;
hBitmap = ::CreateDIBitmap(::GetDC(NULL), &(pVideoHeader->bmiHeader), CBM_INIT, pBuffer, &BitmapInfo, DIB_RGB_COLORS);

if(hBitmap==NULL) return E_FAIL;
CString strSaveFileName="";
CFileDialog filedlg(FALSE,_T("bmp"),_T(""),OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,_T("BMP(*.bmp)"));
if(filedlg.DoModal()==IDOK){
strSaveFileName=filedlg.GetPathName();
SaveBitmapToFile(hBitmap,strSaveFileName.GetBuffer(0));
}

return hr;
}

BOOL SetFormat(ICaptureGraphBuilder2* pBuilder, IBaseFilter* pCap, long lWidth, long lHeight, unsigned short iColorBit, __int64 iRate )
{
VIDEOINFOHEADER* phead;
IAMStreamConfig* iconfig;

HRESULT hr;
hr = pBuilder -> FindInterface( &PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Interleaved,
pCap, IID_IAMStreamConfig, (void **)&iconfig );
if ( hr != NOERROR )
{
hr = pBuilder -> FindInterface( &PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video, pCap,
IID_IAMStreamConfig, (void **)&iconfig);
}

if ( FAILED( hr ) )
return FALSE;

AM_MEDIA_TYPE* pmt;
if ( iconfig -> GetFormat( &pmt ) != S_OK )
return FALSE;

if ( pmt -> formattype == FORMAT_VideoInfo)
{
phead = ( VIDEOINFOHEADER* )pmt -> pbFormat;
phead -> bmiHeader.biBitCount = iColorBit;
phead -> bmiHeader.biWidth = lWidth;
phead -> bmiHeader.biHeight = lHeight;
phead -> bmiHeader.biSizeImage = lWidth * lHeight * iColorBit / 8;
phead -> AvgTimePerFrame = iRate;
if ( ( hr = iconfig -> SetFormat( pmt ) ) != S_OK )
return FALSE;
}
iconfig -> Release();
iconfig = NULL;
FreeMediaType( *pmt );
return TRUE;
}
51flyou 2004-11-02
  • 打赏
  • 举报
回复
从你上面的代码好象有点难看出问题在哪儿?帮你顶
Atomictry 2004-11-01
  • 打赏
  • 举报
回复
to 51flyou(while(1){study++;}) :
谢谢你,在程序中
hr = pGrabber->SetOneShot(TRUE);
hr = pGrabber->SetBufferSamples(TRUE); 函数hr = BuilderSendGraph();中有这两句的,
放在SnapStill之前了。

各路兄弟们, 大家都有个难处, 相帮一下。 谢谢了。
Atomictry 2004-11-01
  • 打赏
  • 举报
回复
顶
vicky_jam 2004-10-31
  • 打赏
  • 举报
回复
up
GameWeaverDummy 2004-10-30
  • 打赏
  • 举报
回复
顶
Atomictry 2004-10-30
  • 打赏
  • 举报
回复
to pGrabber: 在dll中,跟踪不进去。

我相信这里肯定有人做过的,是不是不愿意相告呢? 这又不是什么关键技术,DS中已经包含了大量代码了。

还请各位同仁,老师不吝赐教~
fcf128 2004-10-30
  • 打赏
  • 举报
回复
想知道, 关注!
51flyou 2004-10-30
  • 打赏
  • 举报
回复
你的GetCurrentBuffer是SampleGrabber Filter中的方法,可能需要看看GetCurrentBuffer的实现以及调用方法啦。从你的调用方法来看GetCurrentBuffer类似于IID_IBasicVideo 上的方法GetCurrentImage

BOOL Grab(const char * inFile)
{
if (!mBasicVideo)
{
return FALSE;
}

long bitmapSize = 0;
if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, 0)))
{
BOOL pass = FALSE;
BYTE * buffer = new BYTE[bitmapSize];
if (SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, (long *)buffer)))
{
BITMAPFILEHEADER hdr;
LPBITMAPINFOHEADER lpbi;

lpbi = (LPBITMAPINFOHEADER)buffer;

int nColors = 1 << lpbi->biBitCount;
if (nColors > 256)
nColors = 0;

hdr.bfType = ((WORD) ('M' << 8) | 'B'); // always is "BM"
hdr.bfSize = bitmapSize + sizeof( hdr );
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
hdr.bfOffBits = (DWORD) (sizeof(BITMAPFILEHEADER) + lpbi->biSize +
nColors * sizeof(RGBQUAD));

CFile bmpFile(inFile, CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
bmpFile.Write(&hdr, sizeof(BITMAPFILEHEADER));
bmpFile.Write(buffer, bitmapSize);
bmpFile.Close();
pass = TRUE;
}
delete [] buffer;
return pass;
}
return TRUE;
}
你可以用用这个方法。

另外在SampleGrabber Filter中提供抓图,可能需要什么条件,比如成功传入缓冲区, hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);

char *pBuffer = new char[cbBuffer];这是获得大小设置缓冲区,但你失败.可以尝试把
hr = pGrabber->SetOneShot(TRUE);
hr = pGrabber->SetBufferSamples(TRUE)
放在
SnapStill(); 之前.
syy64 2004-10-29
  • 打赏
  • 举报
回复
看看pGrabber里面的值。
内容概要:本文围绕直流最优潮流(DC-OPF)展开,深入剖析其建模逻辑与数学本质,系统阐述了从交流最优潮流(AC-OPF)向直流简化模型的转化路径,并强调了该模型作为线性规划问题在计算效率方面的显著优势。文章详细分析了简化过程中忽略无功功率、电压幅值变化及网损等物理量所带来的精度代价,明确划定了DC-OPF的应用精度边界。同时,全面梳理了其在电力市场出清、节点电价计算、发输电系统可靠性评估以及高比例新能源消纳调度等关键场景中的应用价值。最后,探讨了当前的研究前沿,涵盖网损近似的精细化处理、适用于大规模系统的分布式求解架构设计,以及对不确定性和多目标优化的扩展研究。; 适合人群:具备电力系统分析基础知识,正在学习或从事电力系统优化、调度、市场等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①理解直流最优潮流(DC-OPF)的理论基础、核心简化假设及其适用范围;②掌握其在电力系统经济调度与市场出清等核心业务场景中的具体应用方法;③了解该领域的最新改进方向和研究前沿,为后续的学术研究或工程实践提供理论支撑和发展指引。; 阅读建议:本文兼具理论深度与应用指导性,建议读者结合经典电力系统分析教材,对照文中关于建模简化与精度代价的分析进行深入思考,重点关注其在现代电力系统中的实际应用场景,并对未来的发展趋势保持关注。
内容概要:本文系统研究了永磁同步电机(PMSM)的速度控制问题,重点探讨了矢量控制(FOC)技术的原理与实现方法,并基于Simulink搭建了完整的仿真模型进行验证。文章深入剖析了矢量控制的核心环节,包括Clarke变换与Park变换在内的坐标变换原理、磁场定向控制策略、双闭环(电流环与速度环)PI控制器的设计,以及空间矢量脉宽调制(SVPWM)技术的应用。通过仿真实验,验证了该控制策略在调节PMSM转速和转矩时具备良好的动态响应性能和稳态精度,为高性能电机驱动系统的研发提供了详实的理论依据和技术参考。; 适合人群:具备电机学、电力电子技术和自动控制理论基础的电气工程、自动化、机电一体化等相关专业的本科生、研究生、科研人员及从事电机驱动开发的工程技术人员。; 使用场景及目标:①深入学习和掌握永磁同步电机矢量控制的理论基础与关键技术;②利用Simulink进行电机控制系统的建模、仿真与算法验证,服务于课程设计、毕业设计或科研项目;③为工业领域中高性能伺服驱动器、新能源汽车电驱系统等产品的开发提供技术方案与仿真支持。; 阅读建议:建议读者结合提供的Simulink仿真模型,动手实践并调整控制器参数(如PI参数),通过对比不同参数下的系统响应曲线,深刻理解各控制环节的作用和系统动态性能的优化方法。

19,463

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧