OpenCV中有什么方法可以获取相机分辨率列表吗?
问问题
9966 次
4 回答
4
对于 Windows,您可以使用以下代码枚举所有相机和分辨率:
#include <dshow.h>
#include <locale>
#include <vector>
using namespace std;
#define BLUE 0x0001
#define GREEN 0x0002
#define RED 0x0004
#define GRAY 0x0007
static void setcolor(unsigned int color)
{
HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hCon,color|FOREGROUND_INTENSITY);
}
void _FreeMediaType(AM_MEDIA_TYPE& mt)
{
if (mt.cbFormat != 0)
{
CoTaskMemFree((PVOID)mt.pbFormat);
mt.cbFormat = 0;
mt.pbFormat = NULL;
}
if (mt.pUnk != NULL)
{
// pUnk should not be used.
mt.pUnk->Release();
mt.pUnk = NULL;
}
}
HRESULT CamCaps(IBaseFilter *pBaseFilter)
{
HRESULT hr = 0;
vector<IPin*> pins;
IEnumPins *EnumPins;
pBaseFilter->EnumPins(&EnumPins);
pins.clear();
for(;;)
{
IPin *pin;
hr=EnumPins->Next(1,&pin,NULL);
if(hr!=S_OK){break;}
pins.push_back(pin);
pin->Release();
}
EnumPins->Release();
printf("Device pins number: %d\n",pins.size());
PIN_INFO pInfo;
for(int i=0;i<pins.size();i++)
{
pins[i]->QueryPinInfo(&pInfo);
setcolor(RED);
if(pInfo.dir==0)
{
wprintf(L"Pin name: %s (Ввод)\n",pInfo.achName);
}
if(pInfo.dir==1)
{
wprintf(L"Pin name: %s (Выход)\n",pInfo.achName);
}
IEnumMediaTypes *emt=NULL;
pins[i]->EnumMediaTypes(&emt);
AM_MEDIA_TYPE *pmt;
vector<SIZE> modes;
setcolor(GRAY);
wprintf(L"Avialable resolutions.\n",pInfo.achName);
for(;;)
{
hr=emt->Next(1,&pmt,NULL);
if(hr!=S_OK){break;}
if ( (pmt->formattype == FORMAT_VideoInfo) &&
//(pmt->subtype == MEDIASUBTYPE_RGB24) &&
(pmt->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
(pmt->pbFormat != NULL) )
{
VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat;
SIZE s;
// Get frame size
s.cy=pVIH->bmiHeader.biHeight;
s.cx=pVIH->bmiHeader.biWidth;
// Битрейт
unsigned int bitrate=pVIH->dwBitRate;
modes.push_back(s);
// Bits per pixel
unsigned int bitcount=pVIH->bmiHeader.biBitCount;
REFERENCE_TIME t=pVIH->AvgTimePerFrame; // blocks (100ns) per frame
int FPS=floor(10000000.0/static_cast<double>(t));
printf("Size: x=%d\ty=%d\tFPS: %d\t bitrate: %ld\tbit/pixel:%ld\n",s.cx,s.cy,FPS,bitrate,bitcount);
}
_FreeMediaType(*pmt);
}
//----------------------------------------------------
//
//
//
//----------------------------------------------------
modes.clear();
emt->Release();
}
pins.clear();
return S_OK;
}
/*
* Do something with the filter. In this sample we just test the pan/tilt properties.
*/
void process_filter(IBaseFilter *pBaseFilter)
{
CamCaps(pBaseFilter);
}
/*
* Enumerate all video devices
*
* See also:
*
* Using the System Device Enumerator:
* http://msdn2.microsoft.com/en-us/library/ms787871.aspx
*/
int enum_devices()
{
HRESULT hr;
setcolor(GRAY);
printf("Enumeraring videoinput devices ...\n");
// Create the System Device Enumerator.
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
if(FAILED(hr))
{
fprintf(stderr, "Error. Can't create enumerator.\n");
return hr;
}
// Obtain a class enumerator for the video input device category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0);
if(hr == S_OK)
{
// Enumerate the monikers.
IMoniker *pMoniker = NULL;
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void **)&pPropBag);
if(SUCCEEDED(hr))
{
// To retrieve the filter's friendly name, do the following:
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if (SUCCEEDED(hr))
{
// Display the name in your UI somehow.
setcolor(GREEN);
wprintf(L"------------------> %s <------------------\n", varName.bstrVal);
}
VariantClear(&varName);
// To create an instance of the filter, do the following:
IBaseFilter *pFilter;
hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
(void**)&pFilter);
process_filter(pFilter);
//Remember to release pFilter later.
pPropBag->Release();
}
pMoniker->Release();
}
pEnumCat->Release();
}
pSysDevEnum->Release();
return 0;
}
int wmain(int argc, wchar_t* argv[])
{
setlocale(LC_ALL, "Russian");
int result;
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
result = enum_devices();
CoUninitialize();
getchar();
return result;
}
于 2013-08-24T15:29:13.717 回答
1
您可以使用VideoCapture::get(int propId)函数。在该函数中,您可以获得两个属性来获取视频分辨率。CV_CAP_PROP_FRAME_WIDTH
并CV_CAP_PROP_FRAME_HEIGHT
分别为您提供视频流的 with 和 height 。
于 2013-08-22T07:05:25.060 回答
1
这是 OpenCV 的解决方案。但它非常慢,对于大多数应用程序来说可能无用。无论如何,下面的代码显示了支持的分辨率。这个想法是逐步测试分辨率,并在每次检查实际分辨率。只需使用指向您的 cv::VideoCapture 的指针调用 query_resolutions()。
// return true if the actual resolution has changed
bool test_resolution(cv::VideoCapture* camera, int width, int height, int &actualWidth, int &actualHeight)
{
camera->set(CV_CAP_PROP_FRAME_WIDTH, width);
camera->set(CV_CAP_PROP_FRAME_HEIGHT, height);
width = static_cast<int>(camera->get(CV_CAP_PROP_FRAME_WIDTH));
height = static_cast<int>(camera->get(CV_CAP_PROP_FRAME_HEIGHT));
if (width != actualWidth || height != actualHeight)
{
actualWidth = width;
actualHeight = height;
return true;
}
else
{
return false;
}
}
void query_resolutions(cv::VideoCapture* camera)
{
// Save current resolution
const int current_width = static_cast<int>(camera->get(CV_CAP_PROP_FRAME_WIDTH));
const int current_height = static_cast<int>(camera->get(CV_CAP_PROP_FRAME_HEIGHT));
int actualWidth = 10000;
int actualHeight = 10000;
int delta = 0;
do
{
// first, test to decrease width only
bool resoChanged = test_resolution(camera, actualWidth - delta, actualHeight, actualWidth, actualHeight);
if (!resoChanged)
{
// then, try to decrease height only
resoChanged = test_resolution(camera, actualWidth, actualHeight - delta, actualWidth, actualHeight);
}
if (!resoChanged)
{
// finally, try to decrease width and height
resoChanged = test_resolution(camera, actualWidth - delta, actualHeight - delta, actualWidth, actualHeight);
}
if (resoChanged)
{
delta = 100;
std::cout << actualWidth << "x" << actualHeight << std::endl;
}
else
{
// if these tries don't change the resolution, let's increase delta
delta += 100;
}
}
while (actualWidth > delta && actualHeight > delta);
// Restore resolution
camera->set(CV_CAP_PROP_FRAME_WIDTH, current_width);
camera->set(CV_CAP_PROP_FRAME_HEIGHT, current_height);
}
于 2017-09-20T14:32:26.320 回答
0
我也遇到了这个问题。OpenCV 隐藏了一些与分辨率和属性相关的功能。所以我所做的是在directshow(基于窗口)中构建一个相机库并输出cv::Mat。你可以使用我的代码。
于 2021-03-15T06:04:31.033 回答