Saemas
Saemas

Reputation: 81

OpenCV copying subsection of an image

What I'm trying to do

I'm trying to paste a subsection of one image onto another for part of a project I'm working on. When I tried to view what I had so far, I saw that calling imshow() on both images to check doesn't actually show that both of them have the same BRG values at the points that they should.

What's wrong

The values are almost always wrong and often half of the screen will show up as black.

IE: pixel [0,1] of firstIMG will have [91,21,30] while secondIMG will have some other values when hovering over the pixel in the imshow() screen

The code

// Randomly create an image of 10x10 pixels
Mat firstIMG = Mat(10, 10, CV_8UC3);
randu(firstIMG, Scalar::all(0), Scalar::all(255));
imshow("First", firstIMG);
waitKey();

// Create a second image of same type as the first
Mat secondIMG = Mat::zeros(firstIMG.rows-5, firstIMG.cols-5, firstIMG.type());

// Iterate through all rows of secondIMG
for(int i = 0; i < secondIMG.rows; i++) {

    // Iterate through all columns of secondIMG
    for(int j = 0; j < secondIMG.cols; j++) {
        secondIMG.at<unsigned char>(i, j) = firstIMG.at<unsigned char>(i, j);
    }   
}

imshow("Second", secondIMG);
waitKey();


What I've tried so far

It will print out the same exact data for both images if I iterate over every pixel of each image, but when I use imshow() on the secondIMG many if not all of the pixels are incorrect.

Despite that, I've also tried accessing and changing the BRG values for the secondIMG in different ways, [like in this post][1]. That still leads to the same result of completely different values at the points that they share.

Finally, I've also tried just straight up clone() the firstIMG with the same size and everything, also leading to the same error as above.

  [1]: https://stackoverflow.com/questions/7899108/opencv-get-pixel-channel-value-from-mat-image

Upvotes: 3

Views: 325

Answers (1)

Burak
Burak

Reputation: 2495

It should be cv::Vec3b instead of uchar for a color image.

Instead of looping over pixels, you can use optimised built-in functions.

cv::Mat secondIMG(firstIMG.rows, firstIMG.cols, firstIMG.type());
cv::Rect rect(0, 0, secondIMG.cols, secondIMG.rows);  // x, y, width, height

firstIMG(rect).copyTo(secondIMG);
// or
cv::Mat thirdIMG = firstIMG(rect).clone();

Upvotes: 1

Related Questions