«

»

Oct 11

как cv::Mat заполнить массивом из unsigned char

Наши исходные данные:
Универсальный контейнер cv::Mat из библиотеки openCV в который мы страстно жаждем запихнуть обычное RGB изображение.
RGB изображение к нам приходит от сторонних функций, которые выдают данные в виде отдельных массивов unsigned char для каждого из цветов каналов.

В исходном примере это массив элементов PixelRGB из библиотеки PCL, где каждому элементу ставится в соответствие простенькая структура содержащая значения всех цветовых каналов:

struct PixelRGB
{
      unsigned char r, g, b;
};

В контейнере cv::Mat все данные хранятся в одномерном массиве в виде последовательных характеристик каждой точки.
То есть для нашего трехмерного случая получается в таком виде:
[bgr-1][bgr-2]….[bgr-n] где [bgr-1] – соответственно характеристика голубого, зеленого и красного цветов первого пикселя.
Порядок хранения данных важен – т.е. grb или rgb не подойдет, в OpenCV данные о цвете хранятся именно в таком порядке – BGR – blue,green,red.

Свойства cv::Mat – rows и cols – говорят сами за себя – число строк и столбцов соответственно. cv::Mat.step – число элементов массива в каждой строке. Для трехмерного случая длина одной строки получается 640*3 = 1920.

Сниппет кода для заполнения контейнера cv::Mat массивом из unsigned char:

int your_rgb_image_width = 640;
int your_rgb_image_height = 480;

PixelRGB* rgb_color_info = new PixelRGB[your_rgb_image_width*your_rgb_image_width];
Mat cv_rgb_image (your_rgb_image_height,your_rgb_image_width,CV_8UC3);
// fill Mat multidimensional array with unsigned char data
for(int i = 0,k=0;i < cv_rgb_image.rows;i++)
{
	for(int j = 0;j < cv_rgb_image.step;j+=3,k++;)
	{
		cv_rgb_image.data[RgbImageCur.step * i + j] = rgb_color_info[k].b;
		cv_rgb_image.data[RgbImageCur.step * i + j + 1] = rgb_color_info[k].g;
		cv_rgb_image.data[RgbImageCur.step * i + j + 2] = rgb_color_info[k].r;
	}
}

по ссылке расписано как произвести обратную операцию – скопировать данные из контейнера Mat:
http://jayrambhia.wordpress.com/2012/06/23/get-data-from-mat-cvmat-in-opencv/

update 17.11.2012
Что делать, в случае, если данные о цвете желательно хранить в виде целочисленного 32-разрядного числа – uint32_t, меж тем как на вход подается все тот же массив unsigned char?
В большинстве случаев (зависит от системы/компилятора) uint32_t эквивалентен unsigned int, uint8_t – unsigned char. Т.е. сниппет можно использовать как пример для преобразования RGB данных из массива unsigned char в unsigned int.

Как запаковать RGB-данные из unsigned char в unsigned int:

void pack_rgb_to_int(uint32_t& rgb_value, uint8_t red_value, uint8_t green_value,uint8_t blue_value)
{
	rgb_value = ((int)red_value) << 16 | ((int)green_value) << 8 | ((int)blue_value);
}

Как распаковать RGB-данные из unsigned int в unsigned char:

void unpack_rgb_from_int(uint32_t& rgb_value, uint8_t& red_value, uint8_t& green_value,uint8_t& blue_value)
{
	red_value   = (rgb_value >> 16) & 0x0000ff;
	green_value = (rgb_value >> 8)  & 0x0000ff;
	blue_value  = (rgb_value)       & 0x0000ff;
}

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>