大佬directshow 摄像头采集如何对每新到的一帧缩放大小?
格式是MJPG 1920*1080 摄像头捕获格式STDMETHODIMP SampleCB(double Time, IMediaSample *pSample){
if(WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) return S_OK;
HRESULT hr = pSample->GetPointer(&ptrBuffer);//新帧地址
怎么处理ptrBuffer缩放采集帧大小,需要从1920*1080压缩到320*240
if(hr == S_OK){
latestBufferLength = pSample->GetActualDataLength();
if(latestBufferLength == numBytes){
EnterCriticalSection(&critSection);
memcpy(pixels, ptrBuffer, latestBufferLength);
newFrame = true;
freezeCheck = 1;
LeaveCriticalSection(&critSection);
SetEvent(hEvent);
}else{
printf("ERROR: SampleCB() - buffer sizes do not match\n");
}
} 要对每一帧进行缩放操作,您可以使用OpenCV库来实现。以下是对SampleCB函数进行修改的示例代码:
#include "opencv2/opencv.hpp"
#include <iostream>
// ...
STDMETHODIMP SampleCB(double Time, IMediaSample *pSample) {
if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0)
return S_OK;
HRESULT hr = pSample->GetPointer(&ptrBuffer);
if (hr == S_OK) {
latestBufferLength = pSample->GetActualDataLength();
if (latestBufferLength == numBytes) {
EnterCriticalSection(&critSection);
// 使用OpenCV进行缩放
cv::Mat frame(1080, 1920, CV_8UC3, ptrBuffer); // 创建输入帧
cv::Mat resizedFrame;
cv::resize(frame, resizedFrame, cv::Size(320, 240), 0, 0, cv::INTER_LINEAR); // 缩放到320*240
// 将缩放后的帧复制到pixels数组
memcpy(pixels, resizedFrame.data, resizedFrame.total() * resizedFrame.elemSize());
newFrame = true;
freezeCheck = 1;
LeaveCriticalSection(&critSection);
SetEvent(hEvent);
}
else {
printf("ERROR: SampleCB() - buffer sizes do not match\n");
}
}
// ...
}
需要注意的是,此示例假设您已经正确设置了临界区(critical section)和相关的全局变量。另外,它使用OpenCV的cv::resize函数将输入帧缩放为所需的大小,并将缩放后的帧数据复制到pixels数组中。
请确保已正确安装和配置了OpenCV库,并在代码中包含了必要的OpenCV头文件和库路径。
如果问题已经解决,请设置最佳答案 您可以使用DirectShow的图像处理滤镜来对每一帧进行缩放。以下是一种可能的实现方式:
1. 创建一个图像处理滤镜的实例。您可以使用DirectShow提供的现有滤镜,如Transform Filter或Resize Filter,也可以自定义一个滤镜。
2. 配置滤镜的输入和输出格式。将输入格式设置为原始帧的格式(MJPG 1920*1080),将输出格式设置为所需的缩放大小(320*240)。
3. 将滤镜添加到DirectShow图形中。您需要创建一个Filter Graph实例,并将摄像头捕获的数据流连接到滤镜的输入端口。
4. 处理每个新帧。在SampleCB方法中,您可以使用滤镜来处理ptrBuffer中的数据。您需要将数据传递给滤镜的输入端口,并从滤镜的输出端口获取缩放后的数据。
下面是一个示例代码片段,演示如何使用DirectShow的Transform Filter来实现缩放:
#include <dshow.h>
#include <d3d9.h>
IBaseFilter* CreateTransformFilter()
{
IBaseFilter* pTransformFilter = NULL;
CoCreateInstance(CLSID_LegacyAmFilterCategory, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pTransformFilter);
return pTransformFilter;
}
void ConfigureTransformFilter(IBaseFilter* pTransformFilter)
{
ITransformFilter* pTransform = NULL;
pTransformFilter->QueryInterface(IID_ITransformFilter, (void**)&pTransform);
// 设置输入和输出格式
AM_MEDIA_TYPE mtInput, mtOutput;
ZeroMemory(&mtInput, sizeof(AM_MEDIA_TYPE));
ZeroMemory(&mtOutput, sizeof(AM_MEDIA_TYPE));
mtInput.majortype = MEDIATYPE_Video;
mtInput.subtype = MEDIASUBTYPE_MJPG;
mtInput.formattype = FORMAT_VideoInfo;
mtInput.bFixedSizeSamples = TRUE;
mtInput.lSampleSize = 0;
mtInput.cbFormat = sizeof(VIDEOINFOHEADER);
VIDEOINFOHEADER* pviInput = (VIDEOINFOHEADER*)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
ZeroMemory(pviInput, sizeof(VIDEOINFOHEADER));
pviInput->bmiHeader.biWidth = 1920;
pviInput->bmiHeader.biHeight = 1080;
pviInput->bmiHeader.biPlanes = 1;
pviInput->bmiHeader.biBitCount = 24;
pviInput->bmiHeader.biCompression = MAKEFOURCC('M', 'J', 'P', 'G');
mtInput.pbFormat = (BYTE*)pviInput;
mtOutput.majortype = MEDIATYPE_Video;
mtOutput.subtype = MEDIASUBTYPE_RGB24;
mtOutput.formattype = FORMAT_VideoInfo;
mtOutput.bFixedSizeSamples = TRUE;
mtOutput.lSampleSize = 0;
mtOutput.cbFormat = sizeof(VIDEOINFOHEADER);
VIDEOINFOHEADER* pviOutput = (VIDEOINFOHEADER*)CoTaskMemAlloc(sizeof(VIDEOINFOHEADER));
ZeroMemory(pviOutput, sizeof(VIDEOINFOHEADER));
pviOutput->bmiHeader.biWidth = 320;
pviOutput->bmiHeader.biHeight = 240;
pviOutput->bmiHeader.biPlanes = 1;
pviOutput->bmiHeader.biBitCount = 24;
pviOutput->bmiHeader.biCompression = BI_RGB;
mtOutput.pbFormat = (BYTE*)pviOutput;
pTransform->SetMediaType(0, &mtInput);
pTransform->SetMediaType(1, &mtOutput);
CoTaskMemFree(pviInput);
CoTaskMemFree(pviOutput);
pTransform->Release();
}
void ProcessFrame(IMediaSample* pSample)
{
// 获取原始帧数据
BYTE* ptrBuffer = NULL;
pSample->GetPointer(&ptrBuffer);
DWORD bufferSize = pSample->GetSize();
// 创建Filter Graph实例
IGraphBuilder* pGraphBuilder = NULL;
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraphBuilder);
// 创建摄像头捕获的数据流
IBaseFilter* pCaptureFilter = NULL;
pGraphBuilder->AddFilter(pCaptureFilter, L"Capture Filter");
// 创建缩放滤镜
IBaseFilter* pTransformFilter = CreateTransformFilter();
ConfigureTransformFilter(pTransformFilter);
pGraphBuilder->AddFilter(pTransformFilter, L"Transform Filter");
// 连接滤镜
pGraphBuilder->ConnectDirect(GetPin(pCaptureFilter, PINDIR_OUTPUT), GetPin(pTransformFilter, PINDIR_INPUT), NULL);
// 运行图形
IMediaControl* pMediaControl = NULL;
pGraphBuilder->QueryInterface(IID_IMediaControl, (void**)&pMediaControl);
pMediaControl->Run();
// 等待滤镜处理完帧
Sleep(100);
// 从滤镜的输出端口获取缩放后的数据
IPin* pOutputPin = GetPin(pTransformFilter, PINDIR_OUTPUT);
IMemInputPin* pInputPin = NULL;
pOutputPin->QueryInterface(IID_IMemInputPin, (void**)&pInputPin);
BYTE* pScaledBuffer = NULL;
DWORD scaledBufferSize = 0;
pInputPin->Receive(ptrBuffer, bufferSize);
pInputPin->GetBuffer(&pScaledBuffer, &scaledBufferSize);
// 处理缩放后的数据
// ...
// 释放资源
pInputPin->Release();
pMediaControl->Stop();
pGraphBuilder->Release();
}
请注意,这只是一个示例实现,并且可能需要根据您的具体需求进行修改和调整。另外,由于DirectShow已经过时,您可能希望考虑使用更现代的多媒体框架,如Media Foundation或OpenCV来处理摄像头采集数据。
页:
[1]