第三章 解析Opencv, Matplotlib, PIL以及三者之间的转换,三者对JPG和PNG读取和写入(工具)

117 篇文章 2 订阅
57 篇文章 0 订阅

推荐网站
OpenCV
Matplotlib
Pillow


Opencv, Matplotlib, PIL以及三者之间的转换

1. Opencv

opencv的基本图像类型可以和numpy数组相互转化,因此可以直接调用torch.from_numpy(img) 将图像转换成tensor

  • 读取: img=cv2.imread(path)
    OpenCV读取图像后返回的是一个代表图像的numpy.ndarray,采用的格式是(H,W,C),通道顺序为BGR, 取值范围[0,255], dtype=uint8
import cv2
def read_img_cv(path):
	img_cv=cv2.imread(path)
	return img_cv
  • 显示: cv2.imshow(name,img)
import cv2
def show_img_cv(img_cv):
	cv2.imshow("Image", img_cv)
	cv2.waitKey(0)  # 暂停显示图片,数字0代表按键后 0 ms执行
  • 保存: cv2.imwrite(path, img)
import cv2
def save_img_cv(img_cv,path):
	cv2.imwrite(path, img_cv)  # 保存图片

2. Matplotlib

matplotlib 是python仿照matlab绘图开发的图像绘制库。使用matplotlib绘图时,可以读取tesnornumpy数据类型。

  • 读取: img=mpimg.imread(path)

如果是灰度图:返回(H,W)形状的数组
如果是RGB图像,返回(H, W, 3) 形状的数组,图片通道顺序为RGB
如果是RGBA图像,返回(H.W, 4) 形状的数组, 图片通道顺序为RGBA

此外,PNG 图像以浮点数组 (0-1) dtype=float32的形式返回,所有其他格式都作为 int 型数组dtype=uint8返回,位深由具体图像决定。

import matplotlib.image as mpimg
def read_img_mat(path):
	img_mat=mpimg.imread(path)
	return img_mat
  • 显示: plt.imshow(img) plt.show()
  1. 显示彩色图
import matplotlib.pyplot as plt
# 如果在jupyter notebook中显示,需要添加如下一行代码
%matplotlib inline

def show_img_mat(img_mat):
	plt.imshow(img_mat)
	plt.axis('off')
	plt.show()
  1. 显示灰度图
    matplotlib显示图像,默认以三通道显示图像,我们需要在plt.imshow()里添加参数gray
def show_img_gray(img_gray):
	plt.imshow(img_gray,cmap='gray')
	plt.axis('off')
	plt.show()
  1. 显示Image类型图片
def show_img_pil(img_pil):
	plt.imshow(img_pil)
	plt.axis('off')
	plt.show()
  • 保存: plt.imsave(name,img)
def save_img_pil(img_pil,name):
	plt.imsave(name,img_pil)

3. PIL

PIL是python对于图像处理的基本库。
图像的模式如下图,比如1: 二值图,L灰度图,P: 8位彩色图,RGB:24位彩色图(每个通道8位)例如jpg图像,RGBA : 相比RGB多了alpha通道(不透明度)例如png图像
可以使用img.convert(mode) 转换模式。
在这里插入图片描述

  • 读取: img=Image.open(path)
    读到的是一个PIL.xxxImageFIie的类型。
import PIL
from PIL import Image
def read_img_pil(path):
	img_pil=Image.open(path) # PIL Image 类型
	return img_pil
  • 显示:image.show()
def show_img_pil(img_pil):
	img_pil.show()
  • 保存: image.save(path)
def save_img_pil(img_pil,path):
	img_pil.save(path)

4. 三者的区别和相互转换


三者的区别

  • Opencv 的数据类型是Numpy数组,通道顺序为BGR
  • Matplotlib 的数据类型是Numpy数组, 通道顺序是RGB
  • PIL 的数据类型是PIL.Image类,通道顺序是RGB

三种图像处理库相互转换

  • OpencvMatplotlib之间的相互转换
# cv->mat
def cv2mat(img_cv):
	img_mat=cv2.cvtColor(img_cv,cv2.COLOR_BGR2RGB) # 将颜色通道从BGR改变成RGB
	# 另一种等价写法
	# img_mat=img_cv[:,:,::-1]
	return img_mat

def mat2cv(img_mat): # 将颜色通道从RGB改变成BGR
	img_cv=img_mat[:,:,::-1]
	return img_cv
  • MatplotlibPIL之间的相互转换
    np.asarry(img) img->array
    Image.fromarray(array) array->img
# mat->PIL
#方法1:三通道的转换
def mat2PIL_RGB(img_mat):
	img_pil=Image.fromarray(img_mat.astype('uint8'))
	# unit8 是无符号的8位整形,用astype [0,255]截断处理
	# 另外一种写法
	# img_pil= Image.fromarray(np.unit8(img_mat))
	return img_pil 

# 方法2: 四通道的转换
def mat2PIL_RGBA(img_mat):
	img_pil=Image.fromarray(img_mat.astype('uint8')).convert('RGB')
	return img_pil

# 方法三:使用torchvision的库函数
from torchvision import transforms
def mat2PIL_trans(img_mat):
	trans=transformers.ToPILImage()
	img_pil=trans(img_mat)
	return img_pil
	
'''PIL->mat'''

def PIL2mat(img_pil):
	img_mat=np.array(img_pil) # 深拷贝
	# 如果是jpg格式,通道顺序是RGB, (H,W,3)
	# 如果是png格式,通道顺序是RGBA, (H,W,4)
	# 返回的类型均是`numpy.ndarray`, `dtype=unit8`, 取值返回[0,255]
	# 或者也可以采用浅拷贝
	# img_mat=np.asarray(img_pil)
	return img_mat

'''区间变换'''
# [0,255]->[0,1] 
def PIL2mat_norm(img_pil):
	img_mat=np.asarray(img_pil)/255.0
	return img_mat
# [0,1]->[0,255]
def mat_255(img_mat):
	img_mat=(np.maximum(img_mat, 0) / img_mat.max()) * 255.0 
	img_mat=np.unit8(img_mat)
  • OpencvPIL之间的相互转换
# cv->PIL
#方法1:三通道的转换
def cv2PIL_RGB(img_cv):
	img_rgb = img_cv[:,:,::-1] # OpenCV 的通道顺序为 BGR, 转换成RGB
	# nparray 
	img_pil= Image.fromarray(np.uint8(img_rgb))
	return img_pil 

# 方法2: 四通道的转换
def cv2PIL_RGBA(img_cv):
	img_rgb = img_cv[:,:,::-1]
	img_pil=Image.fromarray(img_rgb.astype('uint8')).convert('RGB')
	return img_pil

# 方法三:使用torchvision的库函数
from torchvision import transforms
def cv2PIL_trans(img_cv):
	img_rgb = img_cv[:,:,::-1]
	trans=transformers.ToPILImage()
	img_pil=trans(img_rgb)
	return img_pil
	
# PIL->cv
def PIL2cv(img_pil):
	img_ary=np.array(img_pil) # 深拷贝,通道顺序是 RGB, (H,W,C)
	# 或者也可以采用深拷贝
	# img_ary=np.asarray(img_pil)
	img_cv=img_ary[:,:,-1]
	return img_cv

三种格式和Tensor之间的相互转换

  • numpy格式转成Tensor
import torch
def nparray2tensor(npary):
	ts=torch.from_numpy(npary)
	# 如果需要修改成浮点类型
	# ts=torch.from_numpy(npary).float()
	return ts
  • PIL和numpy格式转成Tensor
    可以利用torchvision 中transforms.ToTensor()
    该函数可以将PIL 中的Image 或者 numpy.ndarray(dtype=unit8): 大小 (H,W,C)、范围[0,255] 转化成torch.FloatTensor: 大小(C,H,W)、范围[0.0,1.0]
from torchvision import transforms
# img_pil: Image
trans=transforms.ToTensor() 
tens=trans(img_pil) # (C,H,W) [0.0,1,0]
# tens_hwc=tens.transpose((1,2,0))

5. Torchvision 中的相关转换库

5.1 ToPILImage([mode])

CLASS
torchvision.transforms.ToPILImage(mode=None)
  • 功能

    将tensor或ndarray转换为PIL图像——这不会缩放值。这个转换不支持torchscript。

    转换形状为C x H x Wtorch.*Tensor或形状为H x W x Cnumpy ndarrayPIL图像,同时保留值范围。

  • 参数

    • mode(PIL.Image mode)
      

      输入数据的颜色空间和像素深度(可选)。mode为None时(默认)对输入数据有如下假设 :

      • 输入为4通道时,假设模式为RGBA。
      • 如果输入为3通道,则假设为RGB模式。
      • 输入为2路时,假设为LA模式。
      • 如果输入有1个通道,模式由数据类型(即int、float、short)确定。

5.2 ToTensor

CLASS
torchvision.transforms.ToTensor
  • 功能:

    将PIL图像或ndarray转换为tensor,并相应地缩放。这个转换不支持torchscript。

    转换PIL Image或在[0,255]区间内的numpy.ndarray (H x W x C)[0.0,1.0]区间内的torch.FloatTensor (C x H x W)。其中PIL Image属于其中一种模式(L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1);如果numpy.Ndarray的dtype = np.uint8
    在其他情况下,张量在不缩放的情况下返回。

5.3 PILToTensor

CLASS
torchvision.transforms.PILToTensor
  • 功能

    将PIL图像转换为相同类型的张量-这不会缩放值。这个转换不支持torchscript。

    PIL Image (H x W x C)转换为形状(C x H x W)的张量。

对JPG和PNG读取和写入

特性OpenCVMatplotlibPillow
文件读写cv2.imread/imwriteplt.imread/imsaveImage.open/save
颜色空间BGRRGBRGB
透明度支持仅 PNGPNG 和 JPGPNG 和 JPG
压缩有损无损有损/无损
适用场景图像处理/分析图像显示/可视化图像处理/编辑

备注:

RGB(红绿蓝)和BGR(蓝绿红)是两种表示颜色的方式,它们在像素颜色的排列上有所不同。
RGB 表示红、绿、蓝三个通道,通常按照顺序排列为 (R, G, B)。
BGR 表示蓝、绿、红三个通道,通常按照顺序排列为 (B, G, R)。

opencv

import cv2

# 打开PNG图片文件
png_image = cv2.imread('image.png', cv2.IMREAD_UNCHANGED)  # 使用cv2.IMREAD_UNCHANGED标志以保持透明度信息
# 打开JPG图片文件
jpg_image = cv2.imread('image.jpg')

# 创建新的图像(例如:创建一个黑色的200x200图片)
import numpy as np
new_image = np.zeros((200, 200, 3), dtype=np.uint8)  # 创建一个全为黑色的图像

# 保存PNG图像
cv2.imwrite('new_image.png', new_image)  
# 保存JPG图像
cv2.imwrite('new_image.jpg', new_image)

matplotlib

import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np

# 打开PNG图片文件
png_image = mpimg.imread('image.png')
plt.imshow(png_image)
plt.axis('off')  # 关闭坐标轴
plt.savefig('saved_image.png', bbox_inches='tight', pad_inches=0)  # 保存为PNG格式

# 打开JPG图片文件
jpg_image = mpimg.imread('image.jpg')
plt.imshow(jpg_image)
plt.axis('off')  # 关闭坐标轴
plt.savefig('saved_image.jpg', bbox_inches='tight', pad_inches=0)  # 保存为JPG格式

# 创建一个新的图像(例如:创建一个红色的200x200图像)
new_image = np.zeros((200, 200, 3), dtype=np.uint8)
new_image[:, :] = [255, 0, 0]  # 将新图像设为红色

# 保存新图像为PNG格式
plt.imshow(new_image)
plt.axis('off')  # 关闭坐标轴
plt.savefig('new_image.png', bbox_inches='tight', pad_inches=0)

# 保存新图像为JPG格式
plt.imshow(new_image)
plt.axis('off')  # 关闭坐标轴
plt.savefig('new_image.jpg', bbox_inches='tight', pad_inches=0)

pillow

from PIL import Image

# 打开PNG图片文件
png_image = Image.open('image.png')

# 打开JPG图片文件
jpg_image = Image.open('image.jpg')

# 创建新的图像(例如:创建一个红色的200x200图像)
new_image = Image.new('RGB', (200, 200), color = (255, 0, 0))

# 保存PNG图像
new_image.save('new_image.png')

# 保存JPG图像
new_image.save('new_image.jpg')

解读二

pillow opencv matplotlib读写图片有什么区别

from PIL import Image
import numpy as np
import cv2
from matplotlib import pyplot as plt

file_path = '1.png'

读彩色图像

区别:

  1. opencv-python读出来的是BGR颜色通道的
  2. PIL读出的是PIL类格式的,而cv和plt是numpy数组
# 读取彩色图像 都是H×W×C

img1 = cv2.imread(file_path)  # BGR
img2 = plt.imread(file_path)  # RGB
img3 = np.array(Image.open(file_path))  # RGB
BRG和RGB格式互转
# 用opencv-python
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
image_bgr = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2BGR)

# 利用数组切片 
# 因为shape是H×W×C,BGR倒着读就是RGB
image_rgb = image_bgr[:, :, ::-1] 

读灰色图像

区别:

  1. plt没法读取时设置读灰色图像,但是可以在plt.imshow()的时候设置按照灰度图显示
# 以灰度图方式读取 
img4 = cv2.imread(file_path, flags=cv.IMREAD_GRAYSCALE)
img6 = np.array(Image.open(file_path).convert("L"))

# img5 = plt.imread(file_path) 
# plt没法以灰度方式读取,只能在imshow的时候以灰度方式显示plt.imshow(a, cmap='viridis', interpolation='nearest')
opencv的flags参数
常数效果
cv2.IMREAD_COLOR1读取图像时保留颜色通道(默认值)
cv2.IMREAD_GRAYSCALE0以灰度模式读取图像
cv2.IMREAD_UNCHANGED-1以包含 alpha 通道的方式读取图像

保存图像

matplotlib:

plt保存原理是先创建画板,然后把图像绘制上去。

这会导致保存图像出现白边,以及像素大小与想要的大小不符的现象。不推荐使用!!

plt.imshow(image)
plt.savefig('output.png', bbox_inches='tight', transparent=True, dpi=300, figsize=(6, 4))
opencv:

简单好用

cv2.imwrite("output.jpg", img) # img是numpy数组
pillow:

必须先转PIL对象才能保存

# 使用PIL保存NumPy数组为图像
image = Image.fromarray(numpy_array)

# 保存图像
image.save("output.png")

显示图像

区别:

  1. PIL调用系统默认的图片查看工具
  2. opencv和matplotlib有自己的可视化工具,且matplotlib可以集成在Pycharm的SciView
# PIL 
image = Image.open("image.jpg")
image.show()

# opencv 
image = cv2.imread("image.jpg")
cv2.imshow("Image", image)
cv2.waitKey(0) # 修改等待时间可以用于展示视频帧
cv2.destroyAllWindows()

# matplotlib
plt.imshow(img)
plt.show()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小酒馆燃着灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值