【问题标题】:Set colour limit axis in OpenCV 4 (c++) akin to Matlab's CAXIS在 OpenCV 4 (c++) 中设置颜色限制轴,类似于 Matlab 的 CAXIS
【发布时间】:2019-05-25 11:44:07
【问题描述】:

Matlab 提供了使用CAXIS 为当前轴设置颜色限制的功能。 OpenCV 有applyColorMap,可用于突出显示灰度图像中像素强度的差异,我认为该图像映射的像素范围为 0 - 255。

我是 Matlab/图像处理的新手,并被要求从 MatLab 移植一个简单​​的程序,该程序使用 CAXIS 函数来更改颜色图的“亮度”。我没有使用 Matlab 的经验,但似乎他们使用此功能来“降低”将像素映射到地图上更强烈的颜色所需的强度要求

即使用“JET”的颜色图

  • 当亮度 = 1 时,红色 = 255
  • 当亮度 = 10 时,红色 >= 25

matlab 程序允许读取和显示 16 位图像,这显然提供了更高的像素值,而我已经阅读和完成的所有内容都表明 OpenCV 仅支持 8 位图像(用于彩色图)

因此我的问题是,是否可以在 OpenCV 中提供类似的功能?如何设置颜色图的轴限制/如何缩放颜色图查找表,以便将“不太”强烈的像素缩放到更强烈的区域?

一个类似的问题是asked,回复说数组需要“标准化”,但不幸的是我不太清楚如何实现这一点,也无法回复答案,因为我没有足够的代表!

我已经继续使用cv::normalize 将数组中的最大值设置为 maxPixelValue/brightness,但这根本不起作用。

我也尝试过将我的 16 位图像转换为具有比例因子的 CV_8UC1,但无济于事。任何帮助将不胜感激!

【问题讨论】:

    标签: c++ matlab opencv image-processing


    【解决方案1】:

    在我看来,您可以使用 cv::normalize 将源图片中的值“裁剪”为您感兴趣的颜色图中的相应值。假设您希望将图像映射到 Jet 颜色图的蓝色区域那么你应该这样做:

    int minVal = 0, maxVal = 80;
    cv::normalize(src,dst, minVal, maxVal, cv::NORM_MINMAX);
    

    如果您打算应用某种自定义贴图,对于 1 或 3 通道 8 位图像来说相当容易,您只需要创建具有 255 个值(具有适当数量的通道)的 LUT 并使用 cv::LUT 应用它,更多关于它in this blog,另见dosc about LUT

    如果您正在处理的图像具有不同的深度、16 位甚至浮点数据,我想您需要做的就是编写如下函数:

    template<class T> 
    T customColorMapper(T input_pixel)
    {
        T output_pixel = 0;
        // do something with output_pixel basing on intput_pixel
        return output_pixel;
    }
    

    并将其应用于每个源图像像素,例如:

    cv::Mat dst_image = src_image.clone(); //copy data
    dst_image.forEach<TYPE>([](TYPE& input_pixel, const int* pos_row_col) -> void {
        input_pixel = customColorMapper<TYPE>(input_pixel);
    });
    

    当然TYPE 必须是有效类型。也许这个函数的特殊版本采用cv::Scalarcv::Vec3-如果您需要使用多个通道,这会很好。

    希望这会有所帮助!

    【讨论】:

    • 感谢您抽出宝贵时间回复。我尝试了您提到的一些技术,但无济于事。不幸的是,我不得不对要求有点模糊,否则我会分享更多的代码/打印屏幕。我确实设法让它通过!如果每个像素超过计算的阈值,我使用手动循环将每个像素设置为 MAX 值,如果不是,我乘以比例因子。有关更多信息,请参阅我更新的帖子。
    【解决方案2】:

    我设法复制了 MATLAB 行为,但不得不手动迭代每个像素并将值设置为图像深度的最大值或在需要时缩放值。

    我的代码看起来像这样

    cv::minMaxLoc(dst, &min, &max);
    
    double axisThreshold = floor(max / contrastLevel);
    
     for (int i = 0; i < dst.rows; i++)
        {
            for (int j = 0; j < dst.cols; j++)
            {
                short pixel = dst.at<short>(i, j);
                if (pixel >= axisThreshold)
                {
                    pixel = USHRT_MAX;
                }
                else
                {
                    pixel *= (USHRT_MAX / axisThreshold);
                }
                dst.at<short>(i, j) = cv::saturate_cast<short>(pixel);
            }
        }
    

    在我的示例中,我有一个调整对比度/亮度的滑块(我们称之为对比度,最初的实现称之为亮度)。

    当对比度/亮度改变时,程序将检索最大像素值,然后通过执行计算轴限制

    calculatedThreshold = 最大像素值/对比度

    超过阈值的每个像素都设置为 MAX,低于阈值的每个像素都乘以计算出的比例因子

    scale = MAX Pixel Value / computedThreshold。

    TBH 我不能说我完全理解它背后的数学原理。我只是反复试验,直到它奏效;该部门的任何帮助将不胜感激,但它似乎可以做我想做的事!

    我对最初的 matlab 实现和术语“亮度”的理解实际上是他们尝试缩放颜色图,以便图像“越亮”,每个像素映射到特定颜色的强度就越低颜色图。

    由于 applycolourmap 仅适用于 8 位图像,因此当亮度增加而颜色图轴值减小时,我们需要确保像素值相应缩放,以便它们现在与地图中“更高”的强度值匹配.

    我看过许多使用这种方法来更改对比度/亮度的 OPENCV 教程,但它们经常提倡使用优化的 convertTo(尤其是在您尝试使用 GPU 时)。但是据我所知,convertTo 统一应用 aplha/beta 值,而不是逐个像素地应用,因此我不能使用这种方法。

    如果我找到更合适的 OPENCV 函数来实现我想要的,我会更新这个问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-31
      • 1970-01-01
      • 2019-08-15
      • 1970-01-01
      • 1970-01-01
      • 2013-10-05
      • 2016-01-21
      • 2013-01-27
      相关资源
      最近更新 更多