【问题标题】:matplotlib changes the color of BRG in every layermatplotlib 改变每一层 BRG 的颜色
【发布时间】:2023-03-17 05:41:01
【问题描述】:

我遇到了问题。我正在尝试使用 OpenCV 和 matplotlib 显示 BGR、蓝色层、绿色层和红色层。

我知道 OpenCV 将图像读取为 BGR,matplotlib 将图像读取为 RGB,因此我先将 RGB 转换为 BGR 并设法打印原始图片,但是当我尝试打印蓝色层、绿色层和红色层时结果发现每一层的颜色仍然没有转换。`

    import cv2 as cv
    from matplotlib import pyplot as plt

    img = cv.imread('baboon.png')

    bgr = cv.cvtColor(img, cv.COLOR_RGB2BGR)

    B = bgr [: ,: ,0]
    G = bgr [: ,: ,1]
    R = bgr [: ,: ,2]

   plt.subplot (2, 2, 1)
   plt.imshow (bgr)
   plt.xticks([]), plt.yticks([])
   plt.title('BGR')

   plt.subplot (2 , 2, 2)
   plt.imshow (B)
   plt.xticks([]), plt.yticks([])
   plt.title('Blue Layer')

   plt.subplot (2 , 2, 3)
   plt.imshow (G)
   plt.xticks([]), plt.yticks([])
   plt.title('Green Layer')

   plt.subplot (2 , 2, 4)
   plt.imshow (R)
   plt.xticks([]), plt.yticks([])
   plt.title('red layer')
   plt.show ()

代码的结果

为什么它看起来没有转换?

【问题讨论】:

    标签: python opencv matplotlib


    【解决方案1】:

    您正在绘制不是灰度渐变的单通道数据with a colormap

    为每个.imshow()添加一个合适的cmap=参数,例如

    plt.imshow(G, cmap=plt.get_cmap("Greys"))
    

    示例

    正如 cmets 中所讨论的,OP 希望使用与通道相关的颜色图来显示每个通道。

    您可以使用LinearSegmentedColormap 来生成这些。我还冒昧地用循环替换了重复的代码。

    import cv2 as cv
    from matplotlib import pyplot as plt
    from matplotlib.colors import LinearSegmentedColormap
    
    img = cv.imread("lenna.png")
    
    bgr = cv.cvtColor(img, cv.COLOR_RGB2BGR)
    
    B = bgr[:, :, 0]
    G = bgr[:, :, 1]
    R = bgr[:, :, 2]
    b_map = LinearSegmentedColormap.from_list("B", ["#000", "#00f"])
    g_map = LinearSegmentedColormap.from_list("G", ["#000", "#0f0"])
    r_map = LinearSegmentedColormap.from_list("R", ["#000", "#f00"])
    
    for i, (title, matrix, cmap) in enumerate([
        ("BGR", bgr, None),
        ("Blue", B, b_map),
        ("Green", G, g_map),
        ("Red", R, r_map),
    ], 1):
        plt.subplot(2, 2, i)
        plt.imshow(matrix, cmap=cmap)
        plt.xticks([])
        plt.yticks([])
        plt.title(title)
    
    plt.show()
    

    输出是

    扩展示例

    这是一个显示 HSV 和 YCbCr 结果的示例。 (获得那些 YCbCr 色带是一两件事......)

    import cv2 as cv
    import numpy as np
    from matplotlib import pyplot as plt
    from matplotlib.colors import LinearSegmentedColormap
    from matplotlib.cm import get_cmap
    
    # Build color ramps in YCbCr space
    filler = np.full(255, 128)
    ramp = np.linspace(0, 255, 255)
    ch0_ramp = np.rot90(np.dstack((ramp, filler, filler))).astype("uint8")
    ch1_ramp = np.rot90(np.dstack((filler, ramp, filler))).astype("uint8")
    ch2_ramp = np.rot90(np.dstack((filler, filler, ramp))).astype("uint8")
    y_ramp = 1 - (cv.cvtColor(ch0_ramp, cv.COLOR_YCrCb2RGB)[:, 0] / 255)
    cr_ramp = cv.cvtColor(ch1_ramp, cv.COLOR_YCrCb2RGB)[:, 0] / 255
    cb_ramp = cv.cvtColor(ch2_ramp, cv.COLOR_YCrCb2RGB)[:, 0] / 255
    
    # Build color maps
    b_map = LinearSegmentedColormap.from_list("B", ["#000", "#00f"])
    g_map = LinearSegmentedColormap.from_list("G", ["#000", "#0f0"])
    r_map = LinearSegmentedColormap.from_list("R", ["#000", "#f00"])
    h_map = get_cmap("hsv")
    s_map = LinearSegmentedColormap.from_list("S", ["#888", "#0f0"])
    v_map = LinearSegmentedColormap.from_list("V", ["#000", "#fff"])
    y_map = LinearSegmentedColormap.from_list("Y", y_ramp)
    cr_map = LinearSegmentedColormap.from_list("Cr", cr_ramp)
    cb_map = LinearSegmentedColormap.from_list("Cb", cb_ramp)
    
    # Load material
    
    bgr = cv.imread("lenna.png")
    rgb = cv.cvtColor(bgr, cv.COLOR_BGR2RGB)
    hsv = cv.cvtColor(bgr, cv.COLOR_BGR2HSV)
    ycc = cv.cvtColor(bgr, cv.COLOR_BGR2YCrCb)
    
    # Draw all the things!
    for i, (title, matrix, cmap) in enumerate(
        [
            ("BGR", rgb, None),
            ("Red", rgb[:, :, 0], r_map),
            ("Green", rgb[:, :, 1], g_map),
            ("Blue", rgb[:, :, 2], b_map),
            ("Hue", hsv[:, :, 0], h_map),
            ("Sat", hsv[:, :, 1], s_map),
            ("Val", hsv[:, :, 2], v_map),
            ("Y", ycc[:, :, 0], y_map),
            ("Cr", ycc[:, :, 1], cr_map),
            ("Cb", ycc[:, :, 2], cb_map),
        ],
        0,
    ):
        plt.subplot(4, 3, 1 + i + (2 if i else 0))
        plt.imshow(matrix, cmap=cmap)
        plt.xticks([])
        plt.yticks([])
        plt.title(title)
    
    plt.show()
    

    输出是

    【讨论】:

    • 但为什么它应该是一个灰度渐变?是因为它会转换为1和0吗?例如在蓝色层中,蓝色的所有东西都变成白色或 1。
    • 问题是 RGB 通道本身并没有真正的“红色”或“绿色”或“蓝色”,它们只是灰度。您需要将它们填充回 BGR(其他通道为零)或使用带有通道自身渐变的颜色图。
    • 如果在 YCbCr 或 HSV 渠道中怎么办?它的工作原理与 RGB 相同吗?我对每个.imshow() 都尝试了cmap=plt.get_cmap("Greys"),但结果似乎不对。
    • @AmandaKamphoff 你必须弄清楚什么是适合 HSV 的感知颜色图(你如何表示饱和度的变化?灰色到“只是一些颜色”?);对于 YCbCr,您可以从 en.wikipedia.org/wiki/YUV#/media/File:Barn-yuv.png 获得一些灵感
    • @AmandaKamphoff 我硬着头皮添加了 HSV 和 YCbCr 示例 :)
    【解决方案2】:

    当您分离三个 B/G/R 通道时,您正在将 3 通道图像转换为最能以灰度图像表示的单通道图像。

    你需要在imshow中添加cmap='gray',使它看起来像真正的灰度图像。

    plt.subplot (2, 2, 1)
    plt.imshow (bgr)
    plt.xticks([]), plt.yticks([])
    plt.title('BGR')
    
    plt.subplot (2 , 2, 2)
    plt.imshow (B, cmap= 'gray')
    plt.xticks([]), plt.yticks([])
    plt.title('Blue Layer')
    
    plt.subplot (2 , 2, 3)
    plt.imshow (G, cmap= 'gray')
    plt.xticks([]), plt.yticks([])
    plt.title('Green Layer')
    
    plt.subplot (2 , 2, 4)
    plt.imshow (R, cmap= 'gray')
    plt.xticks([]), plt.yticks([])
    plt.title('red layer')
    plt.show ()
    

    看右边两张图片中鼻子的颜色。红鼻子在红色层中由白色表示,但在蓝色层中不是这样,因为鼻子像素值在蓝色层中为 0,即黑色。 在分离的通道图像中,通道的颜色将在 0-1 尺度上取 1 附近的值,在 0-255 尺度上取 255 附近的值。这个 1 在灰度图像中用 WHITE 表示。

    如果您真的想看到蓝色/红色/绿色 - 使用 cmap,如下所示:

    plt.subplot (2, 2, 1)
    plt.imshow (bgr)
    plt.xticks([]), plt.yticks([])
    plt.title('BGR')
    
    plt.subplot (2 , 2, 2)
    plt.imshow (B, cmap= 'Blues')
    plt.xticks([]), plt.yticks([])
    plt.title('Blue Layer')
    
    plt.subplot (2 , 2, 3)
    plt.imshow (G, cmap= 'Greens')
    plt.xticks([]), plt.yticks([])
    plt.title('Green Layer')
    
    plt.subplot (2 , 2, 4)
    plt.imshow (R, cmap= 'Reds')
    plt.xticks([]), plt.yticks([])
    plt.title('red layer')
    plt.show ()
    

    【讨论】:

    • 那些是白色到彩色的地图,这与 OP 想要的相反......
    • 起初这行bgr = cv.cvtColor(img, cv.COLOR_RGB2BGR) 不是必需的,但是当我尝试运行时,bgr 变量的颜色不是原始颜色。然后基于某处的堆栈溢出答案(我不记得这个问题)它说“OpenCV 将图像读取为 BGR,matplotlib 将图像读取为 RGB”因此我添加了该行,结果与原始结果相同
    猜你喜欢
    • 2015-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    • 2013-04-15
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多