OpenCV — коррекция цвета

Использование OpenCV.

У меня есть изображение RGB, каждое значение является числом с плавающей запятой. У меня тоже стандартная матрица цветокоррекции 3х4.

Каким будет самый быстрый способ "применить" эту матрицу к изображению?

Если вы не знаете цветокоррекцию... Это простая матричная операция.

Если изображение выглядит так (каждый пиксель равен 3 числам с плавающей запятой):

R G B
R G B
R G B
R G B
R G B
.
.
.

Затем я хотел бы выполнить следующее:

1 R G B     [ A1, A2, A3 ] 
1 R G B     [ R1, R2, R3 ]
1 R G B  *  [ G1, G2, G3 ]
1 R G B     [ B1, B2, B3 ]
1 R G B
.
.
.

Все значения в матрице 3x4 являются константами.

Спасибо.


person Gilad    schedule 09.09.2012    source источник
comment
Я не понимаю. У вас есть rgb и вы хотите вернуть rgba? Или rgb, который вы хотите, чтобы матрица видела как rgba, с результатом rgb? Обычно преобразование (я думаю) даст вам самое быстрое умножение, поскольку оно оптимизировано. И даже необходимость добавления накладных расходов на преобразование цвета CV_BGR2RGBA (плюс копирование 1.0 в новую альфу) все равно, вероятно, быстрее, чем что-либо, кроме написанного вручную векторизованного кода.   -  person Bobbi Bennett    schedule 10.09.2012
comment
«A» — это не альфа-канал, а просто константа для умножения на 1, поэтому она добавляется.   -  person Gilad    schedule 10.09.2012


Ответы (2)


Умножьте на rgb части матрицы цветокоррекции:

transform(imageIn,imageOut,M3x3);

Затем добавьте коррекцию канала A:

add(imageOut,Scalar(A1,A2,A3),imageOut);

Прочитайте о преобразовании в opencv2refman, где подразумевается, что вы можете использовать

transfrom(imageIn,imageOut,M4X3);

чтобы получить тот же результат за один шаг (это делает dst (I) = mtx · [src (I); 1], так полезно), избегая добавления компонентов A. Прошу прощения, если это должен быть M3X4. Я довольно дислексичен, когда дело доходит до матричной математики, строк против столбцов и того, что на первом месте.

person Bobbi Bennett    schedule 10.09.2012
comment
Спасибо за ответ, можете ли вы объяснить, как именно это делается, поскольку я не знаком с преобразованием (это CvMul?). Я использую объект изображения, нужно ли мне изменить его форму перед выполнением этой операции? - person Gilad; 10.09.2012
comment
Я подозреваю, что cv::transform может быть хорошим вопросом «вы прочитали всю документацию?» вопрос с домашним заданием, потому что он (для меня) скрыт под кучей описаний RNG и SVD в файле opencv2refman. Я вернулся, чтобы прочитать это снова, и, эй, берегись! Он должен делать именно то, что вы хотите, с матрицей 4X3. - person Bobbi Bennett; 11.09.2012
comment
@Gilad Подробная информация о том, как поместить ваше изображение в мат, выходит за рамки вашего вопроса и очень проста для openCV. Вы должны принять этот ответ, так как это самый быстрый способ применить матрицу коррекции цвета к изображению в openCV. - person Bobbi Bennett; 11.09.2012

Если вы уверены, что значения в вашей матрице хранятся в формате RGB (по умолчанию OpenCV читает их в режиме BGR), вы можете приступить к простому перемножению матриц. Вам просто нужно создать правильную матрицу, содержащую значения RGB, как вы указали, то есть 1, R, G, B 1, R, G, B, ..., с 1 строкой на пиксель в исходном изображении.

Вот как вы можете это сделать (на С++)

// say img is your original RGB matrix, transform is your transformation matrix

std::vector<cv::Mat> channels;
// this extracts the R,G and B channels in single matrices
cv::split(img, channels);
// create a matrix on ones in floating point
cv::Mat oneMat = cv::Mat::ones(img.size(), CV_32F);
oneMat.push_front(channels);
// now channels is a vector containing 4 matrices of the same dimension as img
// you want to group those matrix into 1 single matrix of same dimension and 4 channels
// 1, R, G, B
cv::Mat rgbOne;
cv::merge(channels, rgbOne);
// Transform the row by col, 4 channel matrix rgbOne into a row*col, 4, single channel matrix prior to multiplication
cv::Mat reshaped = rgbOne.reshape(1, rgbOne.rows*rgbOne.cols);
// reshape is very fast as no allocation is required, check documentation

// now simply do the matrix multiplication
cv::Mat colorCorrectedImage = reshaped*transform;

// get back colorCorrectedImage to it's original dimensions
cv::Mat colorCoorectedReshaped = colorCorrectedImage.reshape(4, rgbOne.rows);
// note that you still have the extra channel of ones
// you can use split and merge functions as above to get rid of it and get your proper RGB image
person remi    schedule 10.09.2012
comment
Спасибо. Кажется, есть довольно много операций по переупорядочению данных, поэтому я чувствую, что это будет работать очень медленно, но я проверю это. - person Gilad; 10.09.2012
comment
Самой длинной операцией должно быть умножение матриц, большинство других операций должны быть очень быстрыми. Reshape - это O (1), разделение и слияние включают копирование значений из одного массива в другой, но это довольно быстро. Вы должны проверить математику, но ответ Бобби также может справиться с этой задачей и должен быть быстрее, поскольку он работает непосредственно с данными без необходимости их изменения. И это 2 строки кода! Раньше никогда не использовал функцию преобразования, но обязательно запомню. - person remi; 11.09.2012