【问题标题】:Apply MatplotLib or custom colormap to OpenCV image将 MatplotLib 或自定义颜色图应用于 OpenCV 图像
【发布时间】:2019-03-01 02:42:51
【问题描述】:

OpenCV 的颜色图数量有限。 MatplotLib 有更多的颜色图,但将这些颜色图应用于给定的 OpenCV 图像并不简单。使用 Python API 时,如何将下面页面中的 MatplotLib 颜色图应用于 OpenCV 图像?这类似于将自定义颜色图应用于给定图像。

https://matplotlib.org/examples/color/colormaps_reference.html

【问题讨论】:

    标签: python opencv matplotlib visualization


    【解决方案1】:

    对于 Python >= 2.7,cmapy 以方便的方式封装了此功能。安装它:

    Python 2.7:

    pip install cmapy
    

    Python 3.x:

    pip3 install cmapy
    

    或者,对于 Anaconda(来自 conda-forge):

    conda install -c conda-forge cmapy 
    

    并像这样使用它:

    import cv2
    import matplotlib.pyplot as plt
    import cmapy
    
    # Read image.
    img = cv2.imread('imgs/woman.png')
    
    # Colorize.
    img_colorized = cv2.applyColorMap(img, cmapy.cmap('viridis'))
    
    # Display
    plt.imshow(img_colorized)
    plt.show()
    

    不同的颜色图给出这样的结果:

    查看所有可用的颜色图here

    免责声明:我写了 cmapy(因为我需要这个功能用于另一个项目),在内部,它与其他答案几乎相同。

    【讨论】:

    • 到目前为止最简单的方法。我花了很长时间尝试使用 LUT 在 cv2 中定义我自己的颜色图,但一无所获。然后我切换到 MatplotLib 的 cmaps 和 cmapy 几乎立即完成。我真的不能推荐这个。
    【解决方案2】:

    在 OpenCV 的最新版本(从 3.3 开始)中,applyColorMap 的重载允许您提供自定义颜色图(1 或 3 通道)。我已经修改了verified.human 的代码以简单地生成一个适合与此函数一起使用的颜色图。

    我已经采取了更多的机会来简化代码:

    • 当您将bytes 参数设置为True 时,ScalarMappable.to_rgba 可以直接返回字节(范围为 0-255)。
    • 我们可以使用具有负步长的数组索引来移除 Alpha 通道,以及一步从 RGB 切换到 BGR

    代码:

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    
    def get_mpl_colormap(cmap_name):
        cmap = plt.get_cmap(cmap_name)
    
        # Initialize the matplotlib color map
        sm = plt.cm.ScalarMappable(cmap=cmap)
    
        # Obtain linear color range
        color_range = sm.to_rgba(np.linspace(0, 1, 256), bytes=True)[:,2::-1]
    
        return color_range.reshape(256, 1, 3)
    
    
    image_gray = cv2.imread('cage.png', cv2.IMREAD_GRAYSCALE)
    image_bgr = cv2.applyColorMap(image_gray, get_mpl_colormap('bwr'))
    
    cv2.imshow('image with colormap', image_bgr)
    cv2.waitKey()
    

    【讨论】:

    • 指出颜色图的形状应为 (256, 1, 3),从而节省了我的时间!
    【解决方案3】:

    回答我自己的问题,因为我没有在 StackOverflow 上找到简单的解决方案:

    def apply_custom_colormap(image_gray, cmap=plt.get_cmap('seismic')):
    
        assert image_gray.dtype == np.uint8, 'must be np.uint8 image'
        if image_gray.ndim == 3: image_gray = image_gray.squeeze(-1)
    
        # Initialize the matplotlib color map
        sm = plt.cm.ScalarMappable(cmap=cmap)
    
        # Obtain linear color range
        color_range = sm.to_rgba(np.linspace(0, 1, 256))[:,0:3]    # color range RGBA => RGB
        color_range = (color_range*255.0).astype(np.uint8)         # [0,1] => [0,255]
        color_range = np.squeeze(np.dstack([color_range[:,2], color_range[:,1], color_range[:,0]]), 0)  # RGB => BGR
    
        # Apply colormap for each channel individually
        channels = [cv2.LUT(image_gray, color_range[:,i]) for i in range(3)]
        return np.dstack(channels)
    
    
    image_gray = cv2.imread('./lena.jpg', cv2.IMREAD_GRAYSCALE)
    image_bgr = apply_custom_colormap(image_gray, cmap=plt.get_cmap('bwr'))
    
    cv2.imshow('image with colormap', image_bgr)
    cv2.waitKey(0)
    

    生成图像:

    【讨论】:

      猜你喜欢
      • 2015-09-12
      • 2021-05-03
      • 2021-03-13
      • 2023-03-04
      • 2020-09-28
      • 1970-01-01
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多