How get all resolution of a webcam?

hi, how get all resolution of a webcam?
In Windows 10, the camera app showed me this list of resolutions, I want to do the same in my app, But I do not know how to do it.

Untitled

With these functions I can read and change the resolution, But I want to know the list of all possible resolutions and the minimum value and maximum value of the webcam resolution connected to the computer.

videoCapture.set(cv::CAP_PROP_FRAME_WIDTH, 1920);
videoCapture.set(cv::CAP_PROP_FRAME_HEIGHT, 1080);
//---
videoCapture.get(cv::CAP_PROP_FRAME_WIDTH);
videoCapture.get(cv::CAP_PROP_FRAME_HEIGHT);

unfortunately, there is no way to do this from opencv

I found these links
Procedure: Test a series of standard or pre-used resolutions …

  1. Find All Possible Webcam Resolutions with OpenCV in Python
  2. List of common resolutions
  3. Graphics display resolution
1 Like

But I have a big problem, when I try to test this list of resolutions, opencv shows the following error, what is my problem?

[ WARN:1] global F:.…\OpenCV\4.5.4\opencv\modules\videoio\src\cap_msmf.cpp (680) CvCapture_MSMF::initStream Failed to reset streams

my codes :

QVector<QVector<int>> standardResolutions =
{
	{160, 120},

	{192, 144},
	{256, 144},

	{240, 160},

	{320, 240},
	{360, 240},
	{384, 240},
	{400, 240},
	{432, 240},

	{480, 320},

	{480, 360},
	{640, 360},

	{600, 480},
	{640, 480},
	{720, 480},
	{768, 480},
	{800, 480},
	{854, 480},
	{960, 480},

	{675, 540},
	{960, 540},

	{720, 576},
	{768, 576},
	{1024, 576},

	{750, 600},
	{800, 600},
	{1024, 600},

	{960, 640},
	{1024, 640},
	{1136, 640},

	{960, 720},
	{1152, 720},
	{1280, 720},
	{1440, 720},

	{960, 768},
	{1024, 768},
	{1152, 768},
	{1280, 768},
	{1366, 768},

	{1280, 800},

	{1152, 864},
	{1280, 864},
	{1536, 864},

	{1200, 900},
	{1440, 900},
	{1600, 900},

	{1280, 960},
	{1440, 960},
	{1536, 960},

	{1280, 1024},
	{1600, 1024},

	{1400, 1050},
	{1680, 1050},

	{1440, 1080},
	{1920, 1080},
	{2160, 1080},
	{2280, 1080},
	{2560, 1080},

	{2048, 1152},

	{1500, 1200},
	{1600, 1200},
	{1920, 1200},

	{1920, 1280},
	{2048, 1280},

	{1920, 1440},
	{2160, 1440},
	{2304, 1440},
	{2560, 1440},
	{2880, 1440},
	{2960, 1440},
	{3040, 1440},
	{3120, 1440},
	{3200, 1440},
	{3440, 1440},
	{5120, 1440},

	{2048, 1536},

	{2400, 1600},
	{2560, 1600},
	{3840, 1600},

	{2880, 1620},

	{2880, 1800},
	{3200, 1800},

	{2560, 1920},
	{2880, 1920},
	{3072, 1920},

	{2560, 2048},
	{2732, 2048},
	{3200, 2048},

	{2880, 2160},
	{3240, 2160},
	{3840, 2160},
	{4320, 2160},
	{5120, 2160},

	{3200, 2400},
	{3840, 2400},

	{3840, 2560},
	{4096, 2560},

	{5120, 2880},
	{5760, 2880},

	{4096, 3072},

	{7680, 4320},
	{10240, 4320},
};

while(true)
{
	videoCapture >> frame;

	if(allPossibleResolutionsFinded == false)
	{
		for(int i = 0; i < standardResolutions.count(); i++)
		{
			int w = standardResolutions[i][0];
			int h = standardResolutions[i][1];

			videoCapture.set(cv::CAP_PROP_FRAME_WIDTH, w);
			videoCapture.set(cv::CAP_PROP_FRAME_HEIGHT, h);
			int _w = videoCapture.get(cv::CAP_PROP_FRAME_WIDTH);
			int _h = videoCapture.get(cv::CAP_PROP_FRAME_HEIGHT);

			if(w == _w && h == _h)
			{
				QString itemText = QString("%1x%2").arg(w).arg(h);
				qDebug() << w << "x" << h;
			}
		}
		
		allPossibleResolutionsFinded = true;
	}
}

I found the answer : I should not read any frames [ The following code ] before my code [ top code ]; but why? :neutral_face:

videoCapture >> frame;

I have to change the resolution after reading the frame, for example, after connecting to the webcam after about 2-3 minutes when a large number of frames have been read, I may want to change the resolution, but it shows an error.

[ WARN:1] global F:…\OpenCV\4.5.4\opencv\modules\videoio\src\cap_msmf.cpp (680) CvCapture_MSMF::initStream Failed to reset streams

try with CAP_DSHOW instead

When I use this [ CAP_DSHOW ], the following code gives me a empty image.

videoCapture >> frame;
// frame.empty() = true!!!

opencv can not read the frame, I tested with this function too, it returns false.

bool status = videoCapture.read(frame);

i think i find answer, i must use this code :

processFramesThread.pause();

videoCapture.release();
videoCapture.open(0);
videoCapture.set(cv::CAP_PROP_FRAME_WIDTH, width);
videoCapture.set(cv::CAP_PROP_FRAME_HEIGHT, height);

processFramesThread.resume();

But this takes about 10 seconds, in other apps it takes about 1 second, and it shows these 2 warnings, what’s wrong with me?

[ WARN:0] global F:.…\OpenCV\4.5.4\opencv\modules\videoio\src\cap_msmf.cpp (438) `anonymous-namespace’::SourceReaderCB::~SourceReaderCB terminating async callback

[ WARN:1] global F:.…\4.5.4\opencv\modules\videoio\src\cap_msmf.cpp (1022) CvCapture_MSMF::grabFrame videoio(MSMF): can’t grab frame. Error: -2147483638

My function to check frames :

void file_webcam::ProcessWebcamFrames(QString name)
{
    cv::Mat frame;
    QString fileName;
    QString currentTime;
    QLocale testLocale = QLocale(QLocale::English, QLocale::UnitedStates);
    //---
    double contrast;
    int brightness;
    //---
    // list of resolution standards in computer monitors
    // https://en.wikipedia.org/wiki/List_of_common_resolutions
    // https://en.wikipedia.org/wiki/Graphics_display_resolution
    QVector<QVector<int>> standardResolutions =
    {
        {160, 120},

        {192, 144},
        {256, 144},

        {240, 160},

        {320, 240},
        {360, 240},
        {384, 240},
        {400, 240},
        {432, 240},

        {480, 320},

        {480, 360},
        {640, 360},

        {600, 480},
        {640, 480},
        {720, 480},
        {768, 480},
        {800, 480},
        {854, 480},
        {960, 480},

        {675, 540},
        {960, 540},

        {720, 576},
        {768, 576},
        {1024, 576},

        {750, 600},
        {800, 600},
        {1024, 600},

        {960, 640},
        {1024, 640},
        {1136, 640},

        {960, 720},
        {1152, 720},
        {1280, 720},
        {1440, 720},

        {960, 768},
        {1024, 768},
        {1152, 768},
        {1280, 768},
        {1366, 768},

        {1280, 800},

        {1152, 864},
        {1280, 864},
        {1536, 864},

        {1200, 900},
        {1440, 900},
        {1600, 900},

        {1280, 960},
        {1440, 960},
        {1536, 960},

        {1280, 1024},
        {1600, 1024},

        {1400, 1050},
        {1680, 1050},

        {1440, 1080},
        {1920, 1080},
        {2160, 1080},
        {2280, 1080},
        {2560, 1080},

        {2048, 1152},

        {1500, 1200},
        {1600, 1200},
        {1920, 1200},

        {1920, 1280},
        {2048, 1280},

        {1920, 1440},
        {2160, 1440},
        {2304, 1440},
        {2560, 1440},
        {2880, 1440},
        {2960, 1440},
        {3040, 1440},
        {3120, 1440},
        {3200, 1440},
        {3440, 1440},
        {5120, 1440},

        {2048, 1536},

        {2400, 1600},
        {2560, 1600},
        {3840, 1600},

        {2880, 1620},

        {2880, 1800},
        {3200, 1800},

        {2560, 1920},
        {2880, 1920},
        {3072, 1920},

        {2560, 2048},
        {2732, 2048},
        {3200, 2048},

        {2880, 2160},
        {3240, 2160},
        {3840, 2160},
        {4320, 2160},
        {5120, 2160},

        {3200, 2400},
        {3840, 2400},

        {3840, 2560},
        {4096, 2560},

        {5120, 2880},
        {5760, 2880},

        {4096, 3072},

        {7680, 4320},
        {10240, 4320},
    };
    //QVector<QVector<int>> possibleResolutions(1000, QVector< int >(2));



    while(true)
    {
        ShowMessageOnStatusBar();

        if(videoCapture.isOpened())
        {
            // Find All Possible Webcam Resolutions [ only 1 time ]
            if(allPossibleResolutionsFinded == false)
            {
                for(int i = 0; i < standardResolutions.count(); i++)
                {
                    int w = standardResolutions[i][0];
                    int h = standardResolutions[i][1];

                    videoCapture.set(cv::CAP_PROP_FRAME_WIDTH, w);
                    videoCapture.set(cv::CAP_PROP_FRAME_HEIGHT, h);
                    int _w = videoCapture.get(cv::CAP_PROP_FRAME_WIDTH);
                    int _h = videoCapture.get(cv::CAP_PROP_FRAME_HEIGHT);

                    if(w == _w && h == _h)
                    {
                        QString item = QString("%1x%2").arg(w).arg(h);
                        ui->comboBox_PossibleResolutions->addItem(item);
                    }
                }

                qDebug() << "END!";

                allPossibleResolutionsFinded = true;
            }



            // read next frame
            videoCapture >> frame;
            if(frame.empty() == false)
            {
                // increase frame counter
                numberFramesAfterConnect++;



                // apply effects on frame
                contrast = (double)ui->horizontalSlider_Contrast->value() / 100.0; // 1 to 5
                brightness = ui->horizontalSlider_Brightness->value(); // -255 to 255
                frame.convertTo(frame, -1, contrast, brightness);



                // show frame
                cv::cvtColor(frame, frame, cv::COLOR_BGR2RGB); // Qt reads in RGB whereas CV in BGR
                QImage image((uchar*)frame.data, frame.cols, frame.rows, frame.step, QImage::Format_RGB888); // Converts the CV image into Qt standard format
                ui->label_Image->setPixmap(QPixmap::fromImage(image)); // display the image in label that is created earlier



                // if start button pressed
                if(isStarted)
                {
                    // save frame as image
                    if(canSaveImageNow)
                    {
                        currentTime = testLocale.toString(QDateTime::currentDateTime(), "hh-mm-ss.zzz");
                        fileName = LastDirectoryPath_SaveImageVideo + "/" + QString::number(numberFramesAfterConnect) + ") " + currentTime + ".jpg";
                        image.save(fileName);

                        canSaveImageNow = false;
                    }

                    // save frame as video
                }
            }
        }
    }
}
1 Like

other apps can query the resolution (e.g. using low-level dshow code),
while your approach is probing it,

actually changing the resolution is expensive, the whole graph has to be destroyed and rebuilt.