4

I've made a program in c++ using OpenCV library. The program record video from webcam and then split it in frames. I want to know if the frames are in RGB beacuse i want to access the RGB properties of every pixel. The codec for capture is CV_FOURCC('M','J','P','G'). How can i get the frames in RGB colorspace?

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;
}
karlphillip
  • 92,053
  • 36
  • 243
  • 426
Graver
  • 127
  • 1
  • 2
  • 10
  • Conversion function is called `cvtColor`, but I forgot how to query for the actual data. – Bartek Banachewicz Sep 26 '14 at 13:31
  • 4
    as far as I know OpenCV offers no way to determine the color space of the image. Well, other than check the amount of channels (if it equals 3, then it's definitely not grayscale). – xonxt Sep 26 '14 at 13:50

1 Answers1

8

When OpenCV loads colored images (i.e. 3 channel) from the disk, camera, or a video file, the image data will be stored in the BGR format. This is a simple test that you can do:

/* 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
// ...

Unless you have a weird camera, the frames will always be colored (and as result, stored as BGR).

When cv::imwrite() (C++ API) or cvSaveImage() (C API) are called, OpenCV does the proper magic tricks to ensure the data is saved in a compatible way with requested output format (JPG, PNG, AVI, etc) and during this process it automatically converts the data to RGB if it needs to.

Nevertheless, if for some reason you need to convert the image to RGB you can call:

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

Please note that OpenCV has a C API and also a C++ API, and they shouldn't be mixed:

  • If you use IplImage then stick with the rest of the C API.

  • If you decide to go with cv::Mat, then keep using the C++ API.

There are different ways to access the pixels of a cv::Mat, here is one of them:

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];
    }
}
Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • 9
    You did NOT answer the question. How to check if the image format RGB or BGR? You gave just some assumptions depending on image loading, but when presented with an isolated Mat, there is no way to verify this. This is what you should have said. Of course humans can detect this right away by comparing colors of the known objects. So there should be a way to do it in software too. – Vlad Dec 07 '18 at 18:40
  • 3
    @Vlad This question is about figuring out if the frames grabbed from a webcam are in the RGB format. **On this scenario**, OpenCV encodes the frames in the BGR order by default. I feel like my post answered his question successfully. It seems he also agrees with this assessment since he selected this answer as the official problem solver. – karlphillip Dec 07 '18 at 22:16
  • 1
    @Vlad It seems you read the title of the question but not the question itself. Sorry if Google brought you here for a different problem. The title is a bit misleading, I agree with you on that. – karlphillip Dec 07 '18 at 22:17