当前位置 主页 > 服务器问题 > Linux/apache问题 >
一、问题
在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'.