Есть ли способ в OpenCV получить список разрешений камеры?
Для окон вы можете перечислить все камеры и разрешения, используя этот код:
#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;
}
Ты можешь использовать VideoCapture :: get (int propId) функция. Внутри этой функции вы можете получить два свойства, чтобы получить разрешение видео. CV_CAP_PROP_FRAME_WIDTH
а также CV_CAP_PROP_FRAME_HEIGHT
которые дают вам с и высоту видео потока соответственно.
Вот решение с OpenCV. Но это очень медленно а потом, наверное, бесполезно для большинства приложений. В любом случае код ниже отображает поддерживаемые разрешения. Идея состоит в том, чтобы тестировать разрешение по убыванию и проверять фактическое разрешение каждый раз.
Просто вызовите query_resolutions () с указателем на ваш cv :: VideoCapture.
// 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);
}