gpt4 book ai didi

c++ - 如何在不更改其他 channel 的情况下有效地将 cv::Mat 的给定 channel 设置为给定值?

转载 作者:IT老高 更新时间:2023-10-28 22:36:25 24 4
gpt4 key购买 nike

如何在不改变其他 channel 的情况下有效地将 cv::Mat 的给定 channel 设置为给定值?例如,我想将其第四个 channel (alpha channel )值设置为 120(即半透明),类似于:

cv::Mat mat; // with type CV_BGRA
...
mat.getChannel(3) = Scalar(120); // <- this is what I want to do

P.S.:我目前的解决方案是先将 mat 拆分为多个 channel 并设置 alpha channel ,然后将它们合并回来。

P.S.2:我知道如果我还想更改其他 channel ,我可以通过以下方式快速做到这一点:

mat.setTo(Scalar(54, 154, 65, 120)); 

用广义解决方案更新:

这两种方法都可以将给定 channel 的所有垫子值设置为给定值。无论它们是否连续,它们都适用于所有矩阵。

方法一——更高效

-> 基于@Antonio 的回答并由@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;
}
}

方法 2 - 更优雅

-> 基于@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;

// 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.:值得注意的是,根据 documentation ,用 Mat::create() 创建的矩阵总是连续的。但是如果你使用 Mat::col()Mat::diag() 等提取矩阵的一部分,或者构造一个矩阵头用于外部分配数据,此类矩阵可能不再具有此属性。

最佳答案

如果您的图像在内存中是连续的,您可以使用以下技巧:

mat.reshape(1,mat.rows*mat.cols).col(3).setTo(Scalar(120));

如果不是连续的:

for(int i=0; i<mat.rows; i++)
mat.row(i).reshape(1,mat.cols).col(3).setTo(Scalar(120));

编辑(感谢 Antonio 的评论):

请注意,这段代码可能是最短的,它没有分配新的内存,但它根本没有效率。它甚至可能比拆分/合并方法更慢。当 OpenCV 应该对连续 1 个像素的非连续矩阵执行操作时,它的效率确实很低。如果时间性能很重要,您应该使用@Antonio 提出的解决方案。

对他的解决方案进行了微小的改进:

const int cols = img.cols;
const int step = img.channels();
const int rows = img.rows;
for (int y = 0; y < rows; y++) {
unsigned char* p_row = img.ptr(y) + SELECTED_CHANNEL_NUMBER; //gets pointer to the first byte to be changed in this row, SELECTED_CHANNEL_NUMBER is 3 for alpha
unsigned char* row_end = p_row + cols*step;
for(; p_row != row_end; p_row += step)
*p_row = value;
}
}

这节省了 x 的增量操作和寄存器中的少一个值。在资源有限的系统上,它可能会提供约 5% 的加速。否则时间性能将相同。

关于c++ - 如何在不更改其他 channel 的情况下有效地将 cv::Mat 的给定 channel 设置为给定值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23510571/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com