From e8f94182f577894410cc59d5d20979dff69d8878 Mon Sep 17 00:00:00 2001 From: jason_w Date: Thu, 7 Sep 2023 20:47:00 +0800 Subject: [PATCH] Merge pull request #24180 from MambaWong:4.x Fixed the channels when capturing yuv422 with v4l2 backend #24180 example to reproduce the problem ```cpp #include #include #include #include #include using namespace cv; using namespace std; void help_func(VideoCapture& cap) { int height = cap.get(cv::CAP_PROP_FRAME_HEIGHT); int width = cap.get(cv::CAP_PROP_FRAME_WIDTH); int pixel_type = cap.get(cv::CAP_PROP_FORMAT); int channels = CV_MAT_CN(pixel_type); int pixel_bytes = CV_ELEM_SIZE(pixel_type); bool to_bgr = static_cast(cap.get(cv::CAP_PROP_CONVERT_RGB)); std::cout << "backend: " << cap.getBackendName() << std::endl; std::cout << std::hex << "fourcc: " << static_cast(cap.get(cv::CAP_PROP_FOURCC)) << std::endl; std::cout << std::boolalpha << "to_bgr: " << to_bgr << std::endl; std::cout << std::dec << "height: " << height << " width: " << width << " channels: " << channels << " pixel_bytes: " << pixel_bytes << std::endl; std::cout << "-----------------------------------------" << std::endl; } int main(int, char**) { VideoCapture cap; cap.open("/dev/video0"); if (!cap.isOpened()) { cerr << "ERROR! Unable to open camera\n"; return -1; } { help_func(cap); } { cap.set(cv::CAP_PROP_FRAME_HEIGHT, 1080); cap.set(cv::CAP_PROP_FRAME_WIDTH, 1920); cap.set(cv::CAP_PROP_CONVERT_RGB, 0); help_func(cap); } // { // cap.set(cv::CAP_PROP_CONVERT_RGB, 0); // cap.set(cv::CAP_PROP_FRAME_HEIGHT, 1080); // cap.set(cv::CAP_PROP_FRAME_WIDTH, 1920); // help_func(cap); // } Mat frame; int frame_idx = 0; while (cap.read(frame)) { std::cout << "frame index: " << frame_idx++ << std::endl; help_func(cap); if (frame.empty()) { cerr << "ERROR! blank frame grabbed\n"; break; } Mat bgr; if (cap.get(cv::CAP_PROP_CONVERT_RGB)) { bgr = frame; } else { cv::cvtColor(frame, bgr, cv::COLOR_YUV2BGR_YUYV); } imshow("frame", bgr); if (waitKey(5) >= 0) { break; } } return 0; } ``` The above code will get the wrong channels. By changing lines 41-45 like below, can get the correct channels. code This is because `cap.set(cv::CAP_PROP_FRAME_HEIGHT, 1080);` and `cap.set(cv::CAP_PROP_FRAME_WIDTH, 1920);` reinitialize the `frame`, but `cap.set(cv::CAP_PROP_CONVERT_RGB, 0);` not. Log info. log We can also observe that we get the correct channels in the while loop. This is because: https://github.com/opencv/opencv/blob/ca0bd70cde431b1dd211254011dd9bcf965f582f/modules/videoio/src/cap_v4l.cpp#L2309-L2310 reinitialize the `frame`. --- modules/videoio/src/cap_v4l.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/videoio/src/cap_v4l.cpp b/modules/videoio/src/cap_v4l.cpp index 905c79e42f..5b282f1966 100644 --- a/modules/videoio/src/cap_v4l.cpp +++ b/modules/videoio/src/cap_v4l.cpp @@ -2155,6 +2155,7 @@ bool CvCaptureCAM_V4L::setProperty( int property_id, double _value ) }else{ convert_rgb = false; releaseFrame(); + v4l2_create_frame(); return true; } case cv::CAP_PROP_FOURCC: