OpenCV: Get camera resolutions C++
Asked Answered
M

4

5

Is there any way in OpenCV to get the list of camera's resolutions?

Mcadoo answered 22/8, 2013 at 1:13 Comment(0)
D
4

For windows you can enumerate all cameras and resolutions using this code:

#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;
}
Deactivate answered 24/8, 2013 at 15:29 Comment(3)
linker addition: Strmiids.libSoekarno
I am sorry, but how is this related to OpenCV?Forester
It allows to solve (for windows) lack of such funtion in opencv.Deactivate
H
2

You can use VideoCapture::get(int propId) function. Within that function you can get two properties to get the video resolution. CV_CAP_PROP_FRAME_WIDTH and CV_CAP_PROP_FRAME_HEIGHT which give you the with and height of the video stream respectively.

Havard answered 22/8, 2013 at 7:5 Comment(1)
Yeah, I know, but I mean how to get all possible resolutions? (which camera supports)Mcadoo
B
1

Here's a solution with OpenCV. But it's very slow and then, probably useless for most applications. Anyway, the code below displays supported resolutions. The idea is to test resolutions decreasingly, and check the actual resolution at each time. Just call query_resolutions() with pointer to your 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);
}
Belva answered 20/9, 2017 at 14:32 Comment(0)
E
0

I also encountered this problem. OpenCV has hidden some functions related to the resolutions and properties. So what I did is to build a camera library in directshow (Window-based) and output cv::Mat. You can use my code.

https://github.com/kcwongjoe/directshow_camera

Ecclesiology answered 15/3, 2021 at 6:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.