【问题标题】:Converting RGB into LMS model using C++ and OpenCV使用 C++ 和 OpenCV 将 RGB 转换为 LMS 模型
【发布时间】:2018-07-06 06:03:47
【问题描述】:

我正在尝试将具有 RGB 颜色空间的图像转换为 LMS 模型。我从this paper 得到的变换矩阵值。我读了这个Question : RGB to LMS color space conversion with OpenCV,我们参考了同一篇论文,我已经按照答案中的所有说明进行操作。

为了确保我的代码运行良好,我将原始 RGB 转换为 LMS,然后使用第一个矩阵的逆矩阵将 LMS 转换回 RGB,并查看输出是否与原始图像匹配。

但输出与原始图像源不匹配。 这是我的代码: [更新]

void test(const Mat &original, Mat &pic, int rows, int cols)
{
    for (int i = 0; i < original.rows; i++) {
        for (int j = 0; j < original.cols; j++) {
        //RGB into LMS
            pic.at<Vec3b>(i, j)[0] =    original.at<Vec3b>(i, j)[0] * 1.4671 + 
                                        original.at<Vec3b>(i, j)[1] * 0.1843 + 
                                        original.at<Vec3b>(i, j)[2] * 0.003;   //B-->S
            pic.at<Vec3b>(i, j)[1] =    original.at<Vec3b>(i, j)[0] * 3.8671 + 
                                        original.at<Vec3b>(i, j)[1] * 27.1554 + 
                                        original.at<Vec3b>(i, j)[2] * 3.4557;   //G-->M
            pic.at<Vec3b>(i, j)[2] =    original.at<Vec3b>(i, j)[0] * 4.1194 + 
                                        original.at<Vec3b>(i, j)[1] * 43.5161 + 
                                        original.at<Vec3b>(i, j)[2] * 17.8824;  //R-->L


            //LMS back into RGB
            pic.at<Vec3b>(i, j)[0] = pic.at<Vec3b>(i, j)[0] * 0.6935 + pic.at<Vec3b>(i, j)[1] * -0.0041 + pic.at<Vec3b>(i, j)[2] * -0.0004;   //S-->B
            pic.at<Vec3b>(i, j)[1] = pic.at<Vec3b>(i, j)[0] * -0.1136 + pic.at<Vec3b>(i, j)[1] * 0.0540 + pic.at<Vec3b>(i, j)[2] * -0.0102;   //M-->G
            pic.at<Vec3b>(i, j)[2] = pic.at<Vec3b>(i, j)[0] * 0.1167 + pic.at<Vec3b>(i, j)[1] * -0.1305 + pic.at<Vec3b>(i, j)[2] * 0.0809;   //L-->R

        }
    }
}

主要

int main(int argv, char** argc){
Mat original= imread("original.png", CV_LOAD_IMAGE_COLOR);
int rows = original.rows;
int cols = original.cols;

Mat pic(rows, cols, CV_8UC3);

test(original, pic, rows, cols);
imwrite("pic.png", pic);
}

有什么建议吗?任何帮助将不胜感激。

【问题讨论】:

  • 在从 BGR 转换为 RGB 再转换为 LMS 并返回时,我不断收到红色图像。你遇到过这个问题吗?
  • 嗨@LoganJahnke 我没有遇到同样的问题。另外,我没有在 LMS 之前先从 BGR 转换为 RGB。您可以通过切换LMS矩阵变换(LMS --> SML)将BGR直接转换为LMS。
  • 好吧,我实际上使用了另一个网站上一个非常相似的问题的答案。答案建议使用方法transform()。但是,我现在看到您使用reshape() 的其他帖子。我可能得试试。

标签: c++ opencv image-processing rgb


【解决方案1】:

注意事项:

  1. OpenCV 以 BGR 而非 RGB 的顺序对通道进行排序。
  2. 新通道的值是先前通道的所有 3 个通道的值的加权和。

因此,您的转换不正确。考虑以下获取通道S的代码,

//B-->S    
pic.at<Vec3b>(i, j)[0] = original.at<Vec3b>(i, j)[0] * (0.0030, 0.1843, 1.4671);

应该是

pic.at<Vec3b>(i, j)[0] = original.at<Vec3b>(i, j)[0] * 1.4671 + 
                         original.at<Vec3b>(i, j)[1] * 0.1843 + 
                         original.at<Vec3b>(i, j)[2] * 0.03

其他通道(即 L 和 M)的转换也应相应更改。

一般情况下,如果cvtColor无法进行颜色转换,则应考虑使用矩阵乘法进行。

也就是说,将转换矩阵存储为Mat对象,然后将其与图像的Mat对象相乘,得到想要的结果。这将比使用 for 循环执行转换要快得多,因为 OpenCV 可能会在后台使用优化的 BLAS 例程来执行乘法运算。另外,代码会更加紧凑和干净。

this post 中的答案应该让您了解如何实现这一点。

更新

更新后,您的错误是当您从 LSM 转换回 BGR 时,pic.at&lt;Vec3b&gt;(i, j)[0] 会存储 B 通道的像素值,因此它不再包含 L 通道的值。然后,在计算 G 和 R 通道的值时继续使用该值。

同样,当你计算 R 通道的值时,pic.at&lt;Vec3b&gt;(i, j)[0]pic.at&lt;Vec3b&gt;(i, j)[1] 不再是 S 和 M 通道的值。

请注意,BGR 图像中的通道是所有 3 个 LMS 通道值的混合,反之亦然。

您应该为每个新输出(LMS 图像和最终 BGR 图像)创建一个新矩阵并相应地存储值。那应该可以解决您的错误。

我在帖子中提到了 -0.0003678,因为这是该条目的更精确值。您可以通过反转原始转换矩阵来获得此值。

【讨论】:

  • 您好,感谢您的指正和推荐!我知道 BGR 订单。我也一直在使用 Mat 图像源,并且将矩阵存储为 Mat 对象。但我仍然无法得到预期的结果(请参阅我更新的代码)。我对使用 reshape 很感兴趣,但我很想在那之前完成这项工作。
  • 您好,感谢您的更新。我尝试使用 2 个不同的函数来转换 RGB - LMS 和 LMS - RGB,但似乎我仍然难以解析该值。当我有进展时,我会再次更新。我还使用 Matlab 检查了逆矩阵的条目。似乎值 -0.0004 已经正确。
  • 您好,谢谢!现在我完全理解了我的变量存储问题中缺少的部分并修复了它。只是为了确保..因为结果仍然与原始结果不同,是从 RGB-LMS 转换,然后 LMS 回到 RGB 可逆吗?就像,我们实际上可以得到与原始相同的输出?
  • 由于舍入误差会有一些细微的差异,但从感觉上看应该是相同的。也就是说,您通过从 LMS 转换回 RGB 获得的 RGB 图像应该看起来与原始图像相同。如果没有,那么您的代码可能还有其他问题。
  • 感谢您的信息!现在要尝试重塑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-29
  • 2023-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多