How to set given channel of a cv::Mat
to a given value efficiently without changing other channels? For example, I want to set its fourth channel (alpha channel) value to 120
(i.e. half transparent), something like:
cv::Mat mat; // with type CV_BGRA
...
mat.getChannel(3) = Scalar(120); // <- this is what I want to do
P.S.: My current solution is first split the mat
into multiple channels and set the alpha channel, and then merge them back.
P.S.2: I know that I can do this quickly if I also want to change other channels as well by:
mat.setTo(Scalar(54, 154, 65, 120));
Update with generalized solution:
Both methods will work for setting all mat values at given channel to given value. And they will work for all matrices whether they are continuous or not.
Method-1 - more efficient
-> based on @Antonio's answer and further improved by @MichaelBurdinov
// set all mat values at given channel to given value
void setChannel(Mat &mat, unsigned int channel, unsigned char value)
{
// make sure have enough channels
if (mat.channels() < channel + 1)
return;
const int cols = mat.cols;
const int step = mat.channels();
const int rows = mat.rows;
for (int y = 0; y < rows; y++) {
// get pointer to the first byte to be changed in this row
unsigned char *p_row = mat.ptr(y) + channel;
unsigned char *row_end = p_row + cols*step;
for (; p_row != row_end; p_row += step)
*p_row = value;
}
}
Method-2 - more elegant
-> based on @MichaelBurdinov's answer
// set all mat values at given channel to given value
void setChannel(Mat &mat, unsigned int channel, unsigned char value)
{
// make sure have enough channels
if (mat.channels() < channel+1)
return;
// check mat is continuous or not
if (mat.isContinuous())
mat.reshape(1, mat.rows*mat.cols).col(channel).setTo(Scalar(value));
else{
for (int i = 0; i < mat.rows; i++)
mat.row(i).reshape(1, mat.cols).col(channel).setTo(Scalar(value));
}
}
P.S.: It's worthy noting that, according to the documentation, matrices created with Mat::create()
are always continuous. But if you extract a part of the matrix using Mat::col()
, Mat::diag()
, and so on, or constructed a matrix header for externally allocated data, such matrices may no longer have this property.