I am relatively new to OpenCV. I want to set the colour of individual pixels using img.at
I also kind of understand cv::Scalar
, for example cv::Scalar(0,255,0)
is green, cv::Scalar(255,0,0)
is blue
I tried the following code
int main( void ){
cv::Mat img(400,400, CV_8UC3);
for(int i=0; i < 400; ++i){
for(int j=0; j < 400; ++j){
img.at<cv::Scalar>(i,j) = cv::Scalar(0,255,0);
}
}
cv::imshow("Tetris", img);
cv::moveWindow("Tetris",400,400);
cv::waitKey(0);
}
It compiles without error messages, but if I launch the program, nothing is visible at all. How do you set the colour of an indiviual pixel to red, green or blue?
Your cv::Mat
type is CV_8UC3
, meaning it contains 3 channels, each of them a uchar
.
But cv::Scalar
contains 4 elements, and by default each of them is a double
.
cv::Vec3b
is a convenient type to represent an RGB value, where each channle is a uchar
.
Therefore instead of:
img.at<cv::Scalar>(i,j) = cv::Scalar(0,255,0);
Use:
//-----vvvvvvvvv----------vvvvvvvvv------------
img.at<cv::Vec3b>(i, j) = cv::Vec3b(0, 255, 0);
Note that although it doesn't matter in the posted example, the indices that you pass to cv::Mat:at
should be row index (AKA y) first and column index (AKA x) second.
A side note:
Using cv::Mat::at
in such a tight loop to set the pixels of the entire image is not very efficient (due to some validations performed in each at
call).
A better approach would be to iterate over the rows, and for each row iterate via a pointer to the beginning of the row with cv::Mat::ptr
.
Also you should be aware that if you need to set all the pixels of an image to the same value, you can use cv::Mat::setTo
method.
Following the request from the OP, here's an example of using cv::Mat::ptr
to set image pixels more efficiently.
As mentioned above, if in the real case all pixels should have the same value, you can simply use cv::Mat::setTo
instead.
for (int row = 0; row < img.rows; ++row) {
auto* pRowData = img.ptr<cv::Vec3b>(row);
for (int col = 0; col < img.cols; ++col) {
pRowData[col] = cv::Vec3b(0, 255, 0); // assign the pixel with the relevant value (here green is just an example)
}
}