Сценарий
Я хочу создать свою собственную функцию 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 предоставляет несколько типов изображений.Например,
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()
.