Наши исходные данные:
Универсальный контейнер 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; }