c++opencvstdvectoropencv-mat

How to access elements of a std::vector<cv::Mat> and put them in separate matrices cv::Mat


I have a const std::vector<cv::Mat> containing 3 matrices (3 images), and in order to use each image further in my program I need to save them in separate matrices cv::Mat. I know that I need to iterate over vector elements, since this vector is a list of matrices but somehow I can't manage it. At the end, I also need to push 3 matrices back to a vector. I would appreciate if someone could help me out with this. I am still learning it.

std::vector<cv::Mat> imagesRGB;
cv::Mat imgR, imgG, imgB;

for(size_t i=0; i<imagesRGB.size(); i++)
{
   imagesRGB[i].copyTo(imgR);
}

Solution

  • In your code, note that imagesRGB is uninitialized, and its size is 0. The for loop is not evaluated. Additionally, the copyTo method copies matrix data into another matrix (like a paste function), it is not used to store a cv::Mat into a std::vector.

    Your description is not clear enough, however here's an example of what I think you might be needing. If you want to split an RGB (3 channels) image into three individual mats, you can do it using the cv::split function. If you want to merge 3 individual channels into an RGB mat, you can do that via the cv::merge function. Let's see the example using this test image:

    //Read input image:
    cv::Mat inputImage = cv::imread( "D://opencvImages//lena512.png" );
    
    //Split the BGR image into its channels:
    cv::Mat splitImage[3];
    cv::split(inputImage, splitImage);
    
    //show images:
    cv::imshow("B", splitImage[0]);
    cv::imshow("G", splitImage[1]);
    cv::imshow("R", splitImage[2]);
    

    Note that I'm already storing the channels in an array. However, if you want to store the individual mats into a std::vector, you can use the push_back method:

    //store the three channels into a vector:
    std::vector<cv::Mat> matVector;
    
    for( int i = 0; i < 3; i++ ){
        //get current channel:
        cv::Mat currentChannel = splitImage[i];
        //store into vector
        matVector.push_back(currentChannel);
    }
    
    //merge the three channels back into an image:
    cv::Mat mergedImage;
    cv::merge(matVector, mergedImage);
    
    //show final image:
    cv::imshow("Merged Image", mergedImage);
    cv::waitKey(0);
    

    This is the result: