深度学习中各种图像库的图片读取方式总结
在数据预处理过程中,经常需要写python代码搭建深度学习模型,不同的深度学习框架会有不同的读取数据方式(eg:Caffe的python接口默认BGR格式,Tensorflow默认RGB格式),经常需要借助python图像库来读取图像并进行一系列的图像处理工作。
这篇文章总结了Python图像库处理数据的基本方式:
1.Opencv
2.PIL(pillow)
3.matplotlib.image
4.scipy.misc
5.skimage
6.Tensorflow
opencv: cv2.imread
opencv是最常用的图像处理库
基本图像操作:
import cv2
import numpy as np
#读入图片:默认彩色图,cv2.IMREAD_GRAYSCALE灰度图,cv2.IMREAD_UNCHANGED包含alpha通道
img = cv2.imread('aa.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 转换为灰度图
img1 = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) # 转换为RGB
cv2.imshow('src',img)
cv2.imshow('gray',gray)
cv2.imshow('RGB',img1)
print(img.shape) # (h,w,c)
print(img.size) # 像素总数目
print(img.dtype) # 像素类型
cv2.imwrite('test.jpg',img1) # 保存图像
cv2.waitKey()
值得注意的是:
1.opencv读进来的图片已经是一个numpy矩阵了,彩色图片维度是(高度,宽度,通道数)。数据类型是uint8。
2.opencv读进来的图片的通道排列是BGR,而不是主流的RGB
Caffe使用opencv处理图像的基本操作:
import os
import numpy as np
import cv2
import sys
caffe_root = './fancp/caffe/' #指定caffe路径
sys.path.insert(0, caffe_root + 'python')
import caffe
def predict(path, deploy, weight):
net = caffe.Net( deploy, weight, caffe.TEST)
batch_size, channels, height, width = net.blobs['data'].data.shape
X = np.zeros([1,channels,height,width], dtype = np.float32) # caffe的输入格式[N,C,H,W]
img = cv2.imread(path).astype(np.float32)# 读取图片,并进行类型转换
Img = cv2.resize(img,(102,102))[11:90,11:90,::-1]# Resize以及ROI操作
img -= 127.5
img /= 128.0 # 归一化操作
img = np.transpose(img,(2,0,1)) # 通道转换,有H,W,C转变成 C,H,W
#在深度学习搭建CNN时,往往要做相应的图像数据处理,比如图像要扩展维度,比如扩展成(batch_size,channels,height,width)。
img=np.expand_dims(img,axis=0)
X[0,:,:,:] = img
net.blobs['data'].data[...] = X
output = net.forward()
output = output['logits'][0]
print(output) # 输出结果
return 0
if __name__ == '__main__':
#caffe.set_device(0)
#caffe.set_mode_gpu()
caffe.set_mode_cpu()
model_def = '**.prototxt'
model_weights = '**.caffemodel'
image = 'test.jpg'
result = predict(image, model_def, model_weights)
PIL:PIL.Image.open
PIL即Python Imaging Library,也即为我们所称的Pillow,是一个很流行的图像库,它比opencv更为轻巧,正因如此,它深受大众的喜爱。
图像的基本操作:
from PIL import Image
import numpy as np
img = Image.open('aa.jpg')
print(img.format)
print(img.size) #注意,省略了通道。 (w,h)
print(img.mode) #L为灰度图,RGB为真彩色,RGBA为加了透明通道
img.show() # 显示图片
gray = img.convert('L') # 转化为灰度图
gray.show()
#pillow读进来的图片不是矩阵,我们将图片转矩阵
arr = np.array(img)
print(arr.shape)
print(arr.dtype)
#矩阵再转为图像
new_im = Image.fromarray(arr)
new_im.save('test.png')
注:
1.PIL读进来的图像是一个对象,而不是我们所熟知的numpy 矩阵。
2.PIL的通道顺序是RGB
图像操作:
#分离合并通道
r, g, b = img.split()
img = Image.merge("RGB", (b, g, r))
img = img.copy() #复制图像
#ROI获取
img3 = Image.open('1.jpg')
roi = img3.crop((0,0,300,300)) #(左上x,左上y,右下x,右下y)坐标
roi.show()
matplotlib:matplotlib.image.imread
matplotlib多用于科学绘图
图像的基本操作:
import matplotlib.pyplot as plt
import numpy as np
image = plt.imread('aa.jpg')
plt.imshow(image)
plt.axis('off') #也可以关闭显示x,y轴上的数字
plt.show()
#plt.imread读入的就是一个矩阵,跟opencv一样,但彩图读进的是RGB,与opencv有区别
print(image.shape) # (h,w,c)
print(image.size)
print(image.dtype)
综合例子:
import matplotlib.pyplot as plt
import numpy as np
im_lol1 = plt.imread('aa.jpg')
im_lol2 = plt.imread('aa.jpg')
figure = plt.figure(figsize=(10,5)) # 调整显示图片的大小
'''
figsize参数:指定绘图对象的宽度和高度,单位为英寸;dpi参数指定绘图对象的分辨率,
即每英寸多少个像素,缺省值为80。因此本例中所创建的图表窗口的宽度为8*80 = 640像素
'''
plt.axis("off")#不显示刻度
ax = figure.add_subplot(121) # 图片以1行2列的形式显示
plt.axis('off')
ax.imshow(im_lol1) #第一张图
ax.set_title('image 1')#给图片加titile
ax = figure.add_subplot(122)
plt.axis('off')
ax.imshow(im_lol2)
ax.set_title('image 2')#给图片加titile
plt.savefig('twp.jpg')
plt.show()
scipy.misc:scipy.misc.imread
图像的基本操作:
from scipy import misc
import matplotlib.pyplot as plt
im = misc.imread('aa.jpg')
print(im.dtype)
print(im.size)
print(im.shape)
misc.imsave('misc1.png',im)
plt.imshow(im)
plt.show()
注:imread和imsave在后来的版本将会被弃用,现在使用imageio.imread和imageio.imwrite。
深度学习中使用misc:
from scipy import misc
import numpy as np
import matplotlib.pyplot as plt
image = misc.imread('./fancp/aa.jpg')
image = misc.imresize(image, (112,96))
image = image.astype(np.float32)
image -= 127.5
image /= 128.0
image = image[10:89,10:89,:]
image = image.transpose(2, 0, 1)
print(image.shape)
skimage:skimage.io.imread
图像的基本操作:
from skimage import io
from skimage import color
im = io.imread('aa.jpg')
print(im.shape) # numpy矩阵,(h,w,c)
print(im.dtype)
print(im.size)
im3 = color.rgb2grey(im)# 灰度化处理
io.imshow(im3)
io.imsave('sk.png',im)
注:图像也是以numpy array形式读入
Tensorflow:tf.image.decode
1.TensorFlow函数:tf.image.decode_bmp
tf.image.decode_bmp函数:
tf.image.decode_bmp(
contents,
channels=0,
name=None
)
将BMP编码图像的第一帧解码为uint8张量。
attr channels表示解码图像的期望数量的颜色通道。
接受的值是:
0:使用BMP编码图像中的通道数量。
3:输出RGB图像。
4:输出RGBA图像。
参数:
contents:string类型的Tensor,0维,BMP编码的图像。
channels:可选的int,默认为0。
name:操作的名称(可选)。
返回值:
函数返回uint8类型的Tensor。
2.TensorFlow函数:tf.image.decode_jpeg
tf.image.decode_jpeg函数:
tf.image.decode_jpeg(
contents,
channels=0,
ratio=1,
fancy_upscaling=True,
try_recover_truncated=False,
acceptable_fraction=1,
dct_method='',
name=None
)
将JPEG编码图像解码为uint8张量。
attr channels表示解码图像的期望数量的颜色通道。
接受的值是:
0:使用JPEG编码图像中的通道数量。
1:输出灰度图像。
3:输出RGB图像。
如果需要,JPEG编码的图像将被转换以匹配请求的颜色通道数量。
attr ratio允许在解码过程中将图像缩小整数倍。允许的值为:1、2、4和8。这比稍后缩小图像要快得多。
参数:
contents:string类型的Tensor,0维,JPEG编码的图像。
channels:可选的int,默认为0,解码图像的颜色通道数量。
ratio:可选的int,默认为1,缩小比例。
fancy_upscaling:可选的bool,默认为True,如果为true,则使用更慢但更好的色度平面升级(仅限yuv420 / 422)。
try_recover_truncated:可选的bool,默认为False,如果为true,则尝试从截断的输入中恢复图像。
acceptable_fraction:可选的float,默认为1,在截断输入之前所需的最小行数被接受。
dct_method:可选的string,默认为"",用于指定用于解压缩的算法提示的字符串;默认为“”,映射到系统特定的默认值。当前有效值为[“INTEGER_FAST”,“INTEGER_ACCURATE”]。
name:操作的名称(可选)。
返回值:
该tf.image.decode_jpeg函数将返回uint8类型的Tensor。
3.TensorFlow函数:tf.image.decode_png
tf.image.decode_png函数:
tf.image.decode_png(
contents,
channels=0,
dtype=tf.uint8,
name=None
)
将PNG编码的图像解码为uint8或uint16张量。
attr channels表示解码图像的期望数量的颜色通道。
接受的值是:
0:使用PNG编码图像中的通道数量。
1:输出灰度图像。
3:输出RGB图像。
4:输出RGBA图像。
如果需要,将PNG编码的图像转换为与请求的颜色通道数匹配。
此操作还支持解码JPEG和非动画GIF,因为界面相同,但使用tf.image.decode_image将更清晰。
参数:
contents:string类型的Tensor,0维,PNG编码的图像。
channels:可选的int,默认为0,解码图像的颜色通道数量。
dtype:可选的tf.DType,其来自:tf.uint8,tf.uint16,默认为tf.uint8。
name:操作的名称(可选)。
返回值:
该函数返回dtype类型的Tensor。
4.TensorFlow函数:tf.image.decode_image
tf.image.decode_image函数
tf.image.decode_image(
contents,
channels=None,
name=None
)
decode_bmp,decode_gif,decode_jpeg和decode_png的方便函数。
检测图像是否为BMP,GIF,JPEG或PNG,并执行相应的操作将输入字节string转换为类型uint8的Tensor。
注意: decode_gif返回一个4维数组[num_frames、高度、宽度、3],而不是decode_bmp、decode_jpeg和decode_png,后者返回3维数组[height, width, num_channels]。如果您使用BMP、JPEG或PNG文件混合GIF文件,请确保在构造图表时考虑到这一点。
参数:
contents:0-D string,编码的图像字节。
channels:可选的int,默认为0,解码图像的颜色通道数量。
name:操作的名称(可选)
返回值:
对于BMP、JPEG和PNG图像,形状为[height, width, num_channels]或者对于GIF图像,形状为[num_frames, height, width, 3]的类型为uint8的Tensor。
可能引发的异常:
ValueError:通道数量不正确。
5.TensorFlow将raw格式转换为张量
tf.decode_raw函数
decode_raw (
bytes ,
out_type ,
little_endian = None ,
name = None
)
将字符串的字节重新解释为数字的向量。
ARGS:
bytes:字符串类型的张量。所有元素的长度必须相同。
out_type:一个选自:tf.half,tf.float32,tf.float64,tf.int32,tf.uint8,tf.int16,tf.int8 以及 tf.int64 的 tf.DType 。
little_endian:可选的 bool 值,默认为 True。输入字节是否为小字节顺序。忽略存储在单个字节 (如 uint8) 中的 out_type 值。
name:操作的名称(可选)。
返回:
out_type 类型的张量。一个比输入字节多一个维度的张量。添加的维度的大小将等于字节的元素的长度除以要表示 out_type 的字节数。
总结:
除了opencv读入的彩色图片以BGR顺序存储外,其他所有图像库读入彩色图片都以RGB存储。
除了PIL读入的图片是img类之外,其他库读进来的图片都是以numpy 矩阵。
参考:
https://www.cnblogs.com/skyfsm/p/8276501.html
https://www.w3cschool.cn/tensorflow_python/
注:博众家之所长,集群英之荟萃。