Как присвоить значение типа T для data [i] типа uchar без каких-либо потерь? - PullRequest
0 голосов
/ 10 апреля 2019

Сценарий

Я хочу создать свою собственную функцию SetChannel, которая будет устанавливать определенный канал изображения.Например, у меня есть изображение input типа CV_16UC3 (изображение BGR типа ushort), и я хочу изменить зеленый канал (= 1 из-за индексации на основе нуля) на ushort значение 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 для 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] типа uchar без потерь?

Для тех, кто не знает, как это Mat, может быть полезно следующее.

О программеOpenCV Mat class

OpenCV предоставляет несколько типов изображений.Например,

  • CV_8UC1 представляет тип изображения в оттенках серого, в котором каждый пиксель имеет один канал типа uchar.
  • CV_8UC3 представляет тип изображения BGR (не RGB)в котором каждый пиксель имеет три канала, каждый из которых типа uchar.
  • CV_16UC3 представляет тип изображения BGR (не RGB), в котором каждый пиксель имеет три канала, каждый из которых имеет тип ushort.

  • и т. Д.

Mat - это класс для инкапсуляции изображения.У него есть несколько атрибутов и функций.Позвольте мне перечислить некоторые из них, которые я буду использовать в этом вопросе, чтобы вы могли лучше понять мой сценарий.

  • Mat.data: указатель типа uchar, указывающий на блок пикселей изображения.
  • Mat.rows: количество строк
  • Mat.channels(): количество каналов на пиксель
  • Mat.elemSize1() (заканчивается 1): количество байтов на канал
  • Mat.elemSize(): количество байтов на пиксель.Mat.elemSize() = Mat.channels() * Mat.elemSize1().
  • Mat.step: количество байтов в строке

Здесь Mat.step можно рассматривать как произведение "эффективного" количества пикселей в строке (пустья называю это EPPR), - количество каналов на пиксель или Mat.channels(), и - количество байтов на канал или Mat.elemSize1().

Математически,

 Mat.step = EPPR  * Mat.elemSize() 
 Mat.step = EPPR * Mat.channels() * Mat.elemSize1()

Позвольте мне определить EPPR * Mat.channels() как блоки памяти на строку (MBPR).Если вы знаете правильный термин для MBPR, дайте мне знать.

В результате MBPR = Mat.step / Mat.elemSize1().

1 Ответ

0 голосов
/ 10 апреля 2019

Я получил это от кого-то в автономном режиме.Надеюсь, это будет полезно и для других.

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;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...