【问题标题】:OpenCV - Color correctionOpenCV - 颜色校正
【发布时间】:2012-09-02 19:50:27
【问题描述】:

使用 OpenCV。

我有一个 RGB 图像,每个值都是一个浮点数。 我还有一个标准的颜色校正矩阵 3x4。

在图像上“应用”这个矩阵的最快方法是什么?

如果你不懂色彩校正……这是一个简单的矩阵运算。

如果图像看起来像这样(每个像素是 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 矩阵中的所有值都是常数。

谢谢。

【问题讨论】:

  • 我不明白。你有一个 rgb 并且你想要一个 rgba 回来吗?还是您希望矩阵将其视为 rgba 并具有 rgb 结果的 rgb?通常,变换(我认为)会给你最快的乘法,因为它是优化的。甚至不得不增加开销来转换颜色 CV_BGR2RGBA(加上将 1.0 复制到新的 alpha),它仍然可能比手写矢量化代码以外的任何东西都快。
  • 'A' 不是 Alpha 通道,只是一个要乘以 1 的 const 以便添加

标签: opencv emgucv


【解决方案1】:

乘以颜色校正矩阵的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。当谈到矩阵数学,行与列,哪个是第一位的时,我非常有阅读障碍。

【讨论】:

  • 感谢您的回答,您能否解释一下这是如何完成的,因为我不熟悉转换(这是 CvMul 吗?)。我正在使用 Image 对象,是否需要在执行此操作之前对其进行整形?
  • 我怀疑 cv::transform 可能是一个很好的“你读过所有文档了吗?”作业问题,因为它(对我而言)隐藏在 opencv2refman 中的一堆 RNG 和 SVD 描述下方。我又回去读了一遍,嘿,小心!它应该完全符合您的要求,使用 4X3 矩阵。
  • @Gilad 有关如何将图像放入 Mat 的详细信息超出了您的问题范围,并且对于 openCV 非常基本。您应该接受这个答案,因为这是将颜色校正矩阵应用于 openCV 中的图像的最快方法。
【解决方案2】:

如果您确定矩阵中的值以 RGB 格式存储(默认情况下 OpenCV 在 BGR 模式下读取它们),您可以继续进行简单的矩阵乘法运算。您只需要创建包含您指定的 RGB 值的正确矩阵,即 1,R,G,B 1,R,G,B, ...,原始图像中每个像素1行

你可以这样做(在 C++ 中)

// 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

【讨论】:

  • 谢谢。似乎有很多关于重新排列数据的操作,所以我觉得它的工作速度会很慢,但我会测试一下。
  • 最长的运算应该是矩阵乘法,其他大部分运算应该很快。重塑是 O(1),拆分和合并涉及将值从一个数组复制到另一个数组,但这非常快。您必须检查数学,但 Bobbi 的答案也可以完成这项工作,并且应该更快,因为它直接对数据进行操作而无需修改它。这是两行代码!以前从未使用过变换功能,但一定会记住它。
猜你喜欢
  • 2016-12-12
  • 2018-06-04
  • 1970-01-01
  • 2015-08-13
  • 2021-05-23
  • 2018-08-19
  • 2013-01-03
  • 2022-12-10
  • 1970-01-01
相关资源
最近更新 更多