图片读取与保存
cv2.imread
import cv2
im = cv2.imread(img_path) # 若无法读取,返回 None, cv2.imread(path, flags) flags: cv2.IMREAD_COLOR, cv2.IMREAD_GRAYSCALE, cv2.IMREAD_UNCHANGED
type(im) # numpy.ndarray
im.shape # 高,宽,通道 (1047, 1920, 3)
''' cv2.imread 导入的图片格式为 BGR,而不是平常的 RGB, 通过matplotlit.pyplot.imshow 可以看出 BGR 与 RGB 的区别'''
im_RGB = cv2.cvtColor(im, cv2.COLOR_BGR2RGB) # 将 BGR 格式转换为 RGB 格式, cv2.COLOR_BGR2GRAY 转换为灰度格式, cv2.COLOR_BGR2HSV 转换为 HSV 格式
im_resize = cv2.resize(im, (128, 128))
''' 保存图片, cv2.imwrite()
cv2.imwrite('new_.jpg', im) # 注意这里需要保存 BGR 格式的图片,若是保存 RGB 格式的,图片颜色显示不对。
##对于JPEG,其表示的是图像的质量,用0-100的整数表示,默认为95。 ##注意,cv2.IMWRITE_JPEG_QUALITY类型为Long,必须转换成int。
cv2.imwrite('new_.jpg', img1, [int(cv2.IMWRITE_JPEG_QUALITY), 5])
##对于png图片,第三个参数表示的是压缩级别。##cv2.IMWRITE_PNG_COMPRESSION,从0到9,压缩级别越高,图像尺寸越小。默认级别为3
cv2.imwrite('new_.png', img1, [int(cv2.IMWRITE_JPEG_QUALITY), 5])
''' 显示图片 '''
cv2.namedWindow("im")
cv2.imshow('im',image_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
PIL.Image (Python Image Library)
from PIL import Image
im = image.open(img_path)
print(im.format) # 'JPEG'
print(im.size) # '(464,331) (宽,高)
print(im.mode) # RGB
im.show() # 显示图片
import numpy as np
np_img = np.array(im) # 将PIL的Image格式转换为 ndarray 格式 (高,宽,通道)
im.resize((128, 128)) # 修改图片大小
im.save('new_image.png') # 保存图片
import matplotlib.pyplot as plt
plt.imshow(im)
matplotlib.image.imread
import matplotlib.image as mpimg
import numpy as np
im = mpimg.imread(img_path)
type(im) # numpy.ndarray, RGB 格式。
im.shape # 高,宽,通道 (1047, 1920, 3)
plt.savefig('new_.jpg')
from skimage import io # scikit-image
from skimage import io
im = io.imread(img_path)
im.shape # 高,宽,通道 (1047, 1920, 3)
type(im) # numpy.ndarray, RGB 格式
io.imsave('new_.jpg', im)
io.imshow(im)
plt.imshow(im)
import imageio
批量获取图片:
import glob
''' glob 可以查找符合特定规则的文件路径名。查找文件只用到三个匹配符:”*”, “?”, “[]”;”*”匹配0个或多个字符;
”?”匹配单个字符;”[]”匹配指定范围内的字符,如:[0-9]匹配数字;
glob.glob返回所有匹配的文件路径列表。
它只有一个参数pathname,定义了文件路径匹配规则,这里可以是绝对路径,也可以是相对路径。 '''
glob.glob(os.path.join(folder, '*.png')) # 获取文件列表
import skimage.io as io
from skimage import data_dir
s = 'd:\pic\*.jpg'
coll = io.ImageCollection(s) # coll 是个图片集合, 可以通过列表索引获取具体的图片, 可以有第二个参数 load_func,可以是自定义的函数。
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
from torchvision import transforms
'''
DataLoader 能够自动生成一个多线程的迭代器,针对 Dataset 数据集, 利用torch自带的数据集加载后就是Dataset数据集,或者通过 ImageFolder 将自己硬盘上的图片加载成 Dataset 格式。、
'''
transform = transforms.Compose([
transforms.CenterCrop(size),
transforms.RandomCrop(size, padding = 0),
transforms.Resize((256, 256)),
transforms.RandomVerticalFlip(p=0.5),
transforms.RandomHorizontalFlip(p=0.5),
**transforms.ToTensor(),**
transforms.Normalize(mean = (0.5, 0.5, 0.5), std = (0.5, 0.5, 0.5))
dset = ImageFolder(root = 'E:\pic\', transform = None, transform = transform, loader = default_loader) # 只能取 root 路径下的直接文件夹作为分类,再往下的子文件夹会归到一类中。 dset文件类型: torchvision.datasets.folder.ImageFolder;
len(dset) # 子文件夹的数量
dset[0] # (, 0), 这里 如果没有transforms.ToTensor(), 则为 PIL.Image 格式,如果有 transforms.ToTensor(), 则为Tensor 格式。 如果想用 DataLoader,则必须有 transforms.ToTensor()。
dset[0][0] # 图片
dset[0][1] # 索引
'''
把一个取值范围是[0,255]的PIL.Image或者shape为(H,W,C)的numpy.ndarray,转换成形状为[C,H,W],取值范围是[0,1.0]的torch.FloadTensor
'''
'''
他有以下成员变量:
* self.classes - 用一个list保存, 保存分类的名称(文件夹的名称) ['cde', 'check']
* self.class_to_idx - 类名对应的 索引,分类名称与索引的对应关系) {'cde': 0, 'check': 1}
* self.imgs - 保存(img-path, class) tuple的list [('E:\\pic\\cde\\照片 558.jpg', 0), ('E:\\pic\\check\\abc\\image.png', 1)]
'''
dataloader = DataLoader(dset, batch_size = 2, shuffle = True, num_workers = 3)
dataiter = iter(dataloader)
'''
- dataloader本质是一个可迭代对象,使用iter()访问,不能使用next()访问;
- 使用iter(dataloader)返回的是一个迭代器,然后可以使用next访问;
- 也可以使用`for inputs, labels in dataloaders`进行可迭代对象的访问;
- 一般我们实现一个datasets对象,传入到dataloader中;然后内部使用yeild返回每一次batch的数据;
'''
keras.preprocessing.image.load_img
import numpy as np
from keras.utils import to_categorical
from keras.preprocessing import image
from keras.applications.resnet50 import ResNet50 # 加载默认模型,如果有已经存在,则直接加载,否则下载。 路径:C:\Users\你的用户名\.keras\models
file_path = './dogs-vs-cats/train/cat.1.jpg'
img = image.load_img(file_path, target_size = (224, 224))
type(img) # PIL.Image.Imgage
x = image.img_to_array(img) # 转换为 numpy.ndarray 格式 (224, 224, 3)
x = np.expand_dims(x, axis = 0) # 增加一个维度 (1, 224, 224, 3), 模型本身要求输入尺寸是(None, 224, 224, 3),这个None表示batch,意思是你要输入多少张图片模型是不知道的,所以就用None来表示,而当你输入图片的时候,shape必须跟模型输入的shape保持一致才能输入。
model = ResNet50(weights='imagenet')
model.predict(x)
keras 多张图片:
'''
以下代码适用模型预测。多张图片输入思想也很简单,就是把同一个类别的图片文件夹底下所有的图片用for循环load进来,然后加到一个list里面,最后concatenate起来。
适用情况:
图片数量:多张
适用场景:模型预测
图片尺寸:统一
'''
import numpy as np
from keras.preprocessing import image
from keras.applications.resnet50 import ResNet50
import glob
file_path = 'E:/pic/'
f_names = glob.glob(file_path + '*.jpg')
imgs = []
for i in range(len(f_names)):
img = image.load_img(f_names[i], target_size=(224, 224))
arr_img = image.img_to_array(img)
arr_img = np.expand_dims(arr_img, axis=0)
imgs.append(arr_img)
x = np.concatenate([x for x in imgs]) # concatenate的作用是把shape为(0, 224, 224, 3)的每张图片tensor,打包成shape为(batch, 224, 224, 3)的tensor,这样就能实现批量预测或批量训练了。
print("predicting...")
model = ResNet50(weights='imagenet')
y = model.predict(x)
print("Completed!")
很多情况下,你并不能使用以上这些方法来直接输入数据去训练或者预测,原因是你的数据集太大了,没办法把所有的图片都载入到内存当中。那keras的data generator就派上用场了,当你的模型需要训练数据的时候,generator会自动从cpu生成一批图片,喂到GPU里面让模型进行训练,依次循环,直到训练结束。
适用情况:
图片数量:大批量
适用场景:模型预测、训练
图片尺寸:可不统一
'''
ImageDataGenerator:
通过实时数据增强生成张量图像数据批次。数据将不断循环(按批次)。
有很多参数对应于图像处理,如图像翻转,均值设为0,除以标准差,旋转,缩放,通道转换,填充,自定义函数。
其中 data_format:图像数据格式,{"channels_first", "channels_last"} 之一。"channels_last" 模式表示图像输入尺寸应该为 (samples, height, width, channels),"channels_first" 模式表示输入尺寸应该为 (samples, channels, height, width)。默认为 在 Keras 配置文件 ~/.keras/keras.json 中的 image_data_format 值。如果你从未设置它,那它就是 "channels_last"。
flow_from_directory:
生成 (x, y) 元组的 DirectoryIterator,其中 x 是一个包含一批尺寸为 (batch_size, *target_size, channels)的图像的 Numpy 数组,y 是对应标签的 Numpy 数组。
directory: 目标目录的路径。
* target_size: 整数元组 (height, width),默认:(256, 256)。所有的图像将被调整到的尺寸。
* color_mode: "grayscale", "rbg" 之一。默认:"rgb"。图像是否被转换成 1 或 3 个颜色通道。
**class_mode: "categorical", "binary", "sparse", "input" 或 None 之一。默认:"categorical"。决定返回的标签数组的类型: ------- 这里需要与model.compile中的损失函数相对应,既标签格式。**
* "categorical" 将是 2D one-hot 编码标签,
* "binary" 将是 1D 二进制标签,"sparse" 将是 1D 整数标签,
* "input" 将是与输入图像相同的图像(主要用于自动编码器)。
* 如果为 None,不返回标签(生成器将只产生批量的图像数据,对于 model.predict_generator(), model.evaluate_generator() 等很有用)。请注意,如果 class_mode 为 None,那么数据仍然需要驻留在 directory 的子目录中才能正常工作。
其他 有 batch_size,默认32, shuffle,保存 等等。
'''
from keras.preprocessing.image import ImageDataGenerator
from keras.applications.resnet50 import ResNet50
trn_path = './dogs-vs-cats/train/'
val_path = './dogs-vs-cats/val/'
generator = ImageDataGenerator()
trn_data = generator.flow_from_directory(trn_path, batch_size=32, target_size=(224, 224), class_mode='sparse')
val_data = generator.flow_from_directory(val_path, batch_size=32, target_size=(224,224), class_mode='sparse')
model = ResNet50(weights='imagenet')
model.compile(optimizer='sgd', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit_generator(trn_data, steps_per_epoch=200, epochs=50, validation_data=val_data, validation_steps=80)
图像处理方法
压缩数据中维度为1的维度, numpy.squeeze()
模型是不能直接对图片进行卷积操作的,必须先转化为numpy数组才能输入模型里面去,而且如果数据集的图片尺寸不统一,也有不同的操作细节。
keras 模型保存路径: C:\Users\你的用户名.keras\models
notop代表是否包括顶层的全连接层,默认include_top=True,包括全连接层。
tf -- tensorflow 或者 CNTK
th -- theano