Opencv-python(cv2)图像读取、显示与保存,看这一篇就够了

图像读取之cv2.imread()函数

  opencv读取图像主要依赖于cv2.imread()函数,cv2.imread()的函数原型为Mat imread( const string& filename, int flags=1 ),其中Mat为Opencv最重要的数据结构,它在Opencv中被定义为一个类,它通过把图像视为一个矩阵来存储数据。作为类,它的属性包含了图像矩阵数据data、图像矩阵维度dims(如32*32图像维度为2)、图像矩阵行数等,关于Mat结构的详细介绍,可以参考OpenCV-Mat结构详解。需要注意的是,Opencv的函数可以直接处理numpy的数据类型——多维数组,这为我们在深度学习框架中保存图像、归一化图像等操作时使用opencv提供了极大方便,我猜测是因为Mat和多维数组都可以代表矩阵数据。
  在cv2.imread()中,它有两个形参,首先是图像的文件名(索引地址),第二个参数flags用于指定以什么样的格式来读取图像,它的取值有以下几种情况:
  (1)flags=1这也是默认情况,代表选择CV_LOAD_IMAGE_UNCHANGED方式,即采用保持原始格式的方式读取图像。比如待读取的图像原来是灰度图像,读取后还是灰度图像。
  (2)flags=2,这种情况代表选择CV_LOAD_IMAGE_GRAYSCALE方式,即以灰度图像格式读取图像。无论原始图像原来是什么格式,读取后都的结果都转变为灰度图像。
  (3)flags=3,这种情况代表选择CV_LOAD_IMAGE_COLOR方式,即以BGR格式读取图像。无论原始图像原来是什么格式,读取后都的结果都转变为BGR形式的三通道图像。
  需要特别注意的是:cv2.imread()函数读取RGB图像时,返回的图像格式的通道并不是按R、G、B排列的,而是按B、G、R顺序排列的!当然,如果你使用cv2.imread()读取RGB图像,又用cv2.imshow()显示图像,不会有什么问题。但如果你用cv2.imread()读取RGB图像,再用其他库方法显示,就很有可能出现问题了,参考matplotlib & visdom 的图片显示问题
  用法示例如下:

image = cv2.imread('D:\\code\\datasets\\facades\\train\\714.jpg', flags=1)

  
  
  • 1

imread函数的坑

  1. 图像文件名索引地址中不能出现任何中文字符
  2. 如果在windows系统下,文件名的索引地址的分隔符需要用“\\”而不是只用“\”,如其地址应为D:\\code\\datasets\\facades\\train\\714.jpg,而不是D:\code\datasets\facades\train\714.jpg,这是为了避免混淆转义字符与文件地址,如\train中的\t系统默认为是一个转义字符。
  3. 读取的图像如果通过numpy.asarray()转换为多维数组类型,即转换后的数组形状为[Height, Width, Channels],这和Tensorflow所期望的模型张量输入形状为[B,H,W,C]非常吻合,但是对于PyTorch而言,它所期望的模型张量输入的形状为[B, C, H, W],此时就需要将Channel维度前调。

图像显示之cv2.imshow()函数

  Opencv-python的图像显示一般使用cv2.imshow()函数,它由两个形参组成,一个是图像显示窗口的名称,另一个则是Mat类型的数据,其用法示例如下

image = cv2.imread('D:\\code\\datasets\\facades\\train\\714.jpg', flags=1)
cv2.imshow('Example',image)
cv2.waitKey(0)

  
  
  • 1
  • 2
  • 3

在Example窗口下的图像显示结果

imshow函数的坑

  1. 必须有两个形参,即第一个显示窗口名称的参数不能省略
  2. 一般需要在后面添加一个cv2.waitKey(0),代表由手动确定下一步操作,否则会出现显示图像一闪而过的情况,或是出现图像无响应的情况。
  3. 特别需要注意的是,对于不同数据格式的图像,imshow()函数会自动进行不同的归一化操作,详细情况请参考Opencv的imshow函数详解。需要记住的是,对于灰度值是32位浮点数的类型的图像而言(比如通常由深度神经网络得到的结果)imshow()函数会自动将每个像素值乘以255再进行显示,即将原图像素值的范围由[0,1]映射到[0,255],因而注意:期望显示的神经网络输出图像矩阵值必须要归一化到[0,1],而不必多此一举归一化到[0,255]再显示
  4. 还有一个坑在于,如果你用cv2.imread()读取RGB图像,再用其他库方法显示,就很有可能出现显示的图像和原本的图像颜色完全不一致!这是因为cv2.imread()函数读取RGB图像时,返回的图像格式的通道并不是按R、G、B排列的,而是按B、G、R顺序排列的!其示例可以参考matplotlib & visdom 的图片显示问题中给出的例图,这里也给出一段将B、G、R顺序转换为R、G、B顺序的代码:
b,g,r=cv2.split(image)
image=cv2.merge([r,g,b])

  
  
  • 1
  • 2

读取与显示图像常见报错提示

  1. cv2.error: OpenCV(4.1.0) C:\projects\opencv-python\opencv\modules\highgui\src\window.cpp:352: error: (-215:Assertion failed) size.width>0 && size.height>0 in function ‘cv::imshow’:
    这个报错的原因主要包括以下两点:1、路径中有中文字符;2、路径中使用了\被误认为转义字符
  2. 图像一闪而过,或出现图像未响应的情况:在cv2.imshow()后添加cv2.waitKey(0)
  3. 如果图像显示全黑或者过白这种不正常情况,可能是由于cv2.imshow()自动归一化的结果,这时需要进行特定的处理即可,参考Opencv的imshow函数详解

图像保存之cv2.imwrite()函数

  opencv_python中采用cv2.imwrite()函数来保存图像,它的使用范例如下:

img = cv2.imread("D:\\code\\datasets\\facades\\train\\716.jpg")
img = np.asarray(img).astype(float)
cv2.imwrite('D:\\code\\1.png',img)

  
  
  • 1
  • 2
  • 3

  cv2.imwrite()函数中的第一个形参'D:\\code\\1.png'期望存储的图像的文件名及地址,文件名的后缀格式可以是.jpg或者是.png,第二个形参img代表待存储的图像数据,可以是Mat类型或者Numpy的Ndarray(多维数组)在示例代码中就将其转变成了Numpy类型,这是因为方便转换成张量从而在深度学习框架加以运用

imwrite函数的坑

  cv2.imwrite()函数的坑在于它保存图像需要图像的像素灰度值动态范围是[0,255],上面已经提到,对于神经网络的输出图像,比如说GAN的生成图像其灰度值动态范围通常是[-1,1],其数据格式为32位,对于cv2.imshow()函数而言,需要将其动态范围通过cv2.normalize()函数转变到[0,1]才能正确显示(cv2.imshow()函数会自动处理),而对于cv2.imwrite()函数而言,则需要把它的动态范围转变到[0,255]才能正确保存。
  总而言之,对于深度学习的网络生成图像而言,如果想通过opencv进行图像显示,需要将灰度值动态范围调整到[0,1],如果想通过opencv进行图像保存,则需要将灰度值动态范围调整到[0,255]。

发布了34 篇原创文章 · 获赞 0 · 访问量 1001

猜你喜欢

转载自blog.csdn.net/forever_008/article/details/104053496