如何为类型为uchar的data [i]分配类型T的值而不会造成任何损失?

时间:2019-04-09 22:15:51

标签: c++ opencv

场景

我想创建自己的SetChannel函数,该函数将设置图像的特定通道。例如,我有一个类型为input的图像CV_16UC3(类型为ushort的BGR图像),我想将绿色通道(由于从零开始的索引,其值= 1)更改为{ ushort的{​​1}}值。为此,我调用32768

SetChannel(input,1,32768)

与嵌套循环相比,我更喜欢在单个循环中工作,因此如上所述,我定义了迭代次数template<typename T> void SetChannel(Mat mat, uint channel, T value) { const uint channels = mat.channels(); if (channel + 1 > channels) return; T * data = (T*)mat.data; // MBPR : number of Memory Block Per Row // Mat.step : number of byte per row // Mat.elemSize1() : number of byte per channel const unsigned int MBPR = mat.step / mat.elemSize1(); // N : total number of memory blocks const unsigned int N = mat.rows * MBPR; for (uint i = channel; i < N; i += channels) data[i] = value; }

上面的代码按预期工作,但是其他一些人说了这一部分

N

是一种代码味道,被认为是设计不良的程序。

现在,我想用另一种方法重写新的方法,如下所示。 它无法正常工作,因为我不知道如何将T * data = (T*)mat.data; 分配给类型T value的{​​{1}}。

data[i]

问题

如何将uchar类型的template<typename T> void SetChannel(Mat mat, uint channel, T value) { const uint channels = mat.channels(); if (channel + 1 > channels) return; uchar * data = mat.data; const unsigned int N = mat.rows * mat.step;// byte per image const unsigned int bpc = mat.elemSize1();// byte per channel const unsigned int bpp = mat.elemSize(); // byte per pixel for (uint i = channel * bpc; i < N; i += bpp) //data[i] = value; } 分配给value类型的T而不造成任何损失?

对于那些不了解data[i]的人,以下内容可能会有用。

关于OpenCV uchar

OpenCV提供了一堆图像。例如,

  • Mat代表灰度图像类型,其中每个像素具有一个类型为Mat的通道。
  • CV_8UC1代表BGR(不是RGB)图像类型,其中每个像素具有三个通道,每个通道类型为uchar
  • CV_8UC3代表BGR(非RGB)图像类型,其中每个像素具有三个通道,每个通道的类型为uchar

  • 等。

CV_16UC3是封装图像的类。它具有几个属性和功能。让我列出其中一些我将在此问题中使用的内容,以便您可以更好地理解我的情况。

  • ushort:类型为Mat的指针,指向一个图像像素块。
  • Mat.data:行数
  • uchar:每像素的通道数
  • Mat.rows(以1结尾):每个通道的字节数
  • Mat.channels():每个像素的字节数。 Mat.elemSize1()
  • Mat.elemSize():每行字节数

这里Mat.elemSize() = Mat.channels() * Mat.elemSize1()被认为是  -每行“有效”像素数(我将其命名为EPPR),  -每个像素或Mat.step的通道数,以及  -每个通道或Mat.step的字节数。

在数学上,

Mat.channels()

让我将Mat.elemSize1()定义为每行( Mat.step = EPPR * Mat.elemSize() Mat.step = EPPR * Mat.channels() * Mat.elemSize1() )的存储块。如果您知道EPPR * Mat.channels()的正确术语,请告诉我。

因此,MBPR

1 个答案:

答案 0 :(得分:0)

我是从离线用户那里获得的。希望它对其他人也有用。

template<typename T>
void SetChannel(Mat mat, uint channel, T value)
{
    const uint channels = mat.channels();
    if (channel + 1 > channels)
        return;


    uchar * data = mat.data;
    const unsigned int N = mat.rows * mat.step;// byte per image
    const unsigned int bpc = mat.elemSize1();// byte per channel
    const unsigned int bpp = mat.elemSize(); // byte per pixel
    const unsigned int bpu = CHAR_BIT * sizeof(uchar);// bits per uchar
    for (uint i = channel * bpc; i < N; i += bpp)
        for (uint j = 0; j < bpc; j++) 
            data[i + j] = value >> bpu * j;

}