当前位置 主页 > 服务器问题 > Linux/apache问题 >

    OpenCV里的imshow()和Matplotlib.pyplot的imshow()的实现

    栏目:Linux/apache问题 时间:2019-11-26 10:39

    一、问题

    在Python里使用OpenCV时,一般是通过cv2.imread读入图片,然后用plt.imshow显示图片,但最近学习OpenCV时这样做的结果与预期的结果有较大的出入。查找资料后,才明白OpenCV里的imshow()和Matplotlib.pyplot的imshow()在使用上有一些区别,不注意的话很容易就会导致很奇怪的结果。

    下面的示例代码及运行结果显示了这种差异:

    import cv2
    import matplotlib.pyplot as plt
    
    #以灰度模式读入图片
    messi=cv2.imread('messi.jpg',0)
    
    #使用matplotlib.pyplot的imshow显示图片
    plt.imshow(messi),plt.title('messi_plt')
    plt.xticks([]),plt.yticks([]) #隐藏坐标轴
    plt.show()
    
    #使用opencv的imshow显示图片
    cv2.imshow('messi_cv',messi)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    运行结果如下:

    在这里插入图片描述

    左边是原图,中间是cv2.imshow的显示结果,右边是plt.imshow的显示结果。很明显地看到,明明是读入灰度图,plt.imshow的结果却更像是张彩图,这显然是有问题的。

    二、分析和解决办法

    为了比较和分析OpenCV里imshow()和Matplotlib.pyplot里imshow()这两者的差异,下面分别对显示彩图以及显示灰度图这两种情况来进行说明。

    彩色图

    对于彩色图片,一般由R,G,B三个通道构成。然而,需要注意的是,OpenCV里彩色图片加载时是按照BGR的顺序,Matplotlib里彩色图片加载时是按照RGB的顺序。所以,当我们用cv2.imread读入图片,用cv2.imshow来显示时自然是不会出问题的,但若用plt.imshow来显示就会出现问题,如下面的结果所示。
    这里省略示例代码(和上面的几乎相同,只是不要在cv2.imread里设置“0”这个参数即可),运行结果如下:

    在这里插入图片描述

    左边是原图,中间是cv2.imshow的显示结果,右边是plt.imshow的显示结果。显然,plt.imshow的结果出现了问题。
    为了解决这个问题,方法很简单,就是将通道R和通道B的内容调换一下,再用plt.imshow显示时就正常了。下面给出该方法的示例代码:

    import cv2
    import matplotlib.pyplot as plt
    
    #读入彩色图片
    messi=cv2.imread('messi.jpg',1)
    
    #使用matplotlib.pyplot的imshow显示图片
    plt.imshow(messi),plt.title('messi_plt')
    plt.xticks([]),plt.yticks([]) #隐藏坐标轴
    plt.show()
    
    ##调换r、b通道,生成rgb顺序的图片并显示
    b,g,r=cv2.split(messi) #通道的拆分
    messi_rgb=cv2.merge((r,g,b)) #通道的融合
    plt.imshow(messi_rgb),plt.title('messi_rgb_plt')
    plt.xticks([]),plt.yticks([])
    plt.show()
    
    #使用opencv的imshow显示图片
    cv2.imshow('messi_cv',messi)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    灰度图

    灰度图是单通道图片,按理说不会出现上面彩色图的那种问题,不管是用cv2.imshow显示还是用plt.imshow显示,结果都应该是一样的。然而,事实却并非如此(如最开始的示例所示)。我纠结了好久不知道原因是什么,一开始以为是opencv和matplotlib的版本不匹配,结果更新版本之后还是有这个问题。后来,去找来matplotlib的API文档才明白是咋回事。
    matplotlib.pyplot.imshow函数里,有一个参数是cmap,API文档里给出的说明是:

    cmap : str or Colormap, optional
    The Colormap instance or registered colormap name used to map scalar data to colors. This parameter is ignored for RGB(A) data. Defaults to rcParams[“image.cmap”] = ‘viridis'.