如何知道 OpenCV 中的图像是不是为 RGB?

Posted

技术标签:

【中文标题】如何知道 OpenCV 中的图像是不是为 RGB?【英文标题】:How can I know if a image is RGB in OpenCV?如何知道 OpenCV 中的图像是否为 RGB? 【发布时间】:2014-09-26 12:23:48 【问题描述】:

我使用 OpenCV 库在 c++ 中制作了一个程序。该程序从网络摄像头录制视频,然后将其拆分为帧。我想知道帧是否在 RGB 中,因为我想访问每个像素的 RGB 属性。捕获的编解码器是 CV_FOURCC('M','J','P','G')。如何获取 RGB 颜色空间中的帧?

int main() 

Mat image;
VideoCapture cap(0);
cap.set(CV_CAP_PROP_FPS, 10);

if ( !cap.isOpened() ) 
    cout << "ERROR : Cannot open the video file"<<endl;
    return -1;

namedWindow("MyWindow", CV_WINDOW_AUTOSIZE);

double dWidth   = cap.get(CV_CAP_PROP_FRAME_WIDTH);
double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
cout << "Frame size :" << dWidth << "x" << dHeight << endl;
Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight));
VideoWriter oVideoWriter("E:/myVideo.avi", CV_FOURCC('M', 'J', 'P', 'G'), 10, frameSize, true);

if (!oVideoWriter.isOpened()) 
    cout << "ERROR : Failed to write the video"<<endl;
    return - 1;


while (1) 
    Mat image;
    bool bSuccess = cap.read(image);

    if (!bSuccess) 
        cout << "ERROR : Cannot read a frame from video file" << endl;
        break;
    
    oVideoWriter.write(image);
    imshow("MyWindow", image);

    if (waitKey(10) == 27) 

        saveImages();


            cout << "ESC key is pressed by user" << endl;
            break


    

return 0;





int saveImages()   



CvCapture *capture = cvCaptureFromFile("E:/myVideo.avi");
if(!capture) 

    cout<<"!!! cvCaptureFromAVI failed (file not found?)"<<endl;
    return -1; 


int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);


IplImage* frame = NULL;
int frame_number = 0;
char key = 0;   

while (key != 'q') 


    frame = cvQueryFrame(capture);       
    if (!frame) 
    
        cout<<"!!! cvQueryFrame failed: no frame"<<endl;
        break;
           

    char filename[100];
    strcpy(filename, "frame_");

    char frame_id[30];
    _itoa(frame_number, frame_id, 10);
    strcat(filename, frame_id);
    strcat(filename, ".jpg");

    printf("* Saving: %s\n", filename);

    if (!cvSaveImage(filename, frame))
    
        cout<<"!!! cvSaveImage failed"<<endl;
        break;
    

    frame_number++;

    key = cvWaitKey(1000 / fps);



cvReleaseCapture(&capture);

return 0;

【问题讨论】:

转换函数调用cvtColor,但是我忘记如何查询实际数据了。 据我所知,OpenCV 无法确定图像的色彩空间。好吧,除了检查通道的数量(如果等于3,那肯定不是灰度)。 【参考方案1】:

当 OpenCV 从磁盘、相机或视频文件加载彩色图像(即 3 通道)时,图像数据将以 BGR 格式存储。这是一个你可以做的简单测试:

/* Code using the C++ API */

cv::VideoCapture cap(0);
if (!cap.isOpened()) 
    std::cout << "!!! Failed to open webcam" << std::endl;
    return -1;


if (!cap.read(frame)) 
    std::cout << "!!! Failed to read a frame from the camera" << std::endl;
    return -1;


bool is_colored = false;
if (frame.channels() == 3) 
    is_colored = true;


// Do something with is_colored
// ...

除非您有一个奇怪的相机,否则帧将始终被着色(并因此存储为 BGR)。

当调用cv::imwrite() (C++ API) 或cvSaveImage() (C API) 时,OpenCV 会使用适当的魔术技巧来确保以与请求的输出格式(JPG、PNG、AVI 等)兼容的方式保存数据) 并且在此过程中,如果需要,它会自动将数据转换为 RGB。

不过,如果由于某种原因您需要将图像转换为 RGB,您可以调用:

cv::Mat img_rgb;
cv::cvtColor(frame, img_rgb, CV_BGR2RGB);  

请注意,OpenCV 有一个 C API 和一个 C++ API,它们不应混用:

如果您使用 IplImage,请坚持使用 C API 的其余部分。

如果您决定使用 cv::Mat,请继续使用 C++ API。

There are different ways to access the pixels of a cv::Mat,这是其中之一:

unsigned char* pixels = (unsigned char*)(frame.data);
for (int i = 0; i < frame.rows; i++)

    for (int j = 0; j < frame.cols; j++)
    
        char b = pixels[frame.step * j + i] ;
        char g = pixels[frame.step * j + i + 1];
        char r = pixels[frame.step * j + i + 2];
    

【讨论】:

您没有回答问题。如何检查图像格式是RGB还是BGR?您仅根据图像加载给出了一些假设,但是当使用孤立的 Mat 呈现时,无法验证这一点。这是你应该说的。当然,人类可以通过比较已知物体的颜色来立即检测到这一点。所以也应该有一种方法可以在软件中做到这一点。 @Vlad 这个问题是关于确定从网络摄像头抓取的帧是否为 RGB 格式。 在这种情况下,OpenCV 默认按照 BGR 顺序对帧进行编码。我觉得我的帖子成功地回答了他的问题。看来他也同意这个评估,因为他选择了这个答案作为官方问题解决者。 @Vlad 看来您阅读了问题的标题,但没有阅读问题本身。抱歉,如果 Google 将您带到这里是为了解决不同的问题。标题有点误导,我同意你的观点。

以上是关于如何知道 OpenCV 中的图像是不是为 RGB?的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenCV 将 RGB 图像转换为二进制图像

如何将 Mat 数据(OpenCV,图像数据格式)转换为统一的 3d 纹理

opencv中为啥图像局矩阵是以BGR而不是RGB显示像素的大小?

使用 OpenCV 将 RGB 图像转换为 LMS,反之亦然

OpenCV 访问 MAT 对象中的 RGB 值

将 Mat 中的 RGB 图像转换为 MFC 中的 BYTE *