两种读取数据构建成深度学习数据集的方法
1 训练验证数据在同一文件夹中
# 将高分影像转换为jpg格式,进行训练,这里用到的是8位深度的3波段的jpg图像,建样本建成了这样的了
# 实际上获得的高分影像应该是4波段16维深度,这个可能需要再考虑一下怎么做
import tensorflow as tf
import numpy as np
import os
import matplotlib.pyplot as plt
import glob
import matplotlib as mpl
import time
from Experiment_GF2.nets.unet import Unet_model
from tensorflow.keras import backend as K
# 使用cpu
#os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
# 使用cpu的时候需要把这个删除了
physical_device = tf.config.experimental.list_physical_devices("GPU")
tf.config.experimental.set_memory_growth(physical_device[0], True)
# 下面这行代码是为了绘图时显示中文
mpl.rcParams['font.sans-serif'] = ["SimHei"]
# 开始计时
time_start=time.time()
######################################### 1 获取图像和图像预处理
## 1.1 读取图像并进行打乱,生成数据集,这里是随机挑选了验证集
imgs = glob.glob(r'H:\01HTutorWork\3GF2\3Code\PestDetect3\dataset\images\*.jpg')
labels = glob.glob(r'H:\01HTutorWork\3GF2\3Code\PestDetect3\dataset\labels\*.png')
## 验证集单独存在一个文件夹里
# imgs_val = glob.glob(r'I:\5GF2\5dataset\5dataset_jpg\3naturedatajpg\*.jpg')
# labels_val = glob.glob(r'I:\5GF2\5dataset\5dataset_jpg\1labelsPNG\*.png')
# 这里注意一定要让图片和标签一一对应,本例中通过验证是对应的,但是一般都需要安名称进行重新排序,这样确保一致
# 这里进行一个乱序,为了让图像训练时,不至于每个批次的图像属于同一类,
# 当然语义分割中不需要进行乱序,因为本身每张图像就包括各种类型,本例中是因为有17个城市拍的照片,所以还是进行了排序
print(len(imgs),len(labels))
index= np.random.permutation(len(imgs))
imgs = np.array(imgs)[index]
labels = np.array(labels)[index]
# 检验标签是否对齐
for i in range(len(imgs)):
img = imgs[i].split("\\")[-1]
label = labels[i].split("\\")[-1]
if img[:-4]!=label[:-4]:
print("出错了"*1000)
train_number = int(len(imgs)*0.8)
imgs_val = imgs[train_number:]
labels_val = labels[train_number:]
imgs = imgs[:train_number]
labels = labels[:train_number]
# 检验标签是否对齐
for i in range(len(imgs_val)):
kk_img = imgs_val[i].split("\\")[-1]
kk_label = labels_val[i].split("\\")[-1]
if kk_img[:-4]!=kk_label[:-4]:
print("出错了"*1000)
print("训练图像数量:", len(imgs))
print(imgs[566:570])
print("训练标签数量:", len(labels))
print(labels[566:570])
print("验证图像数量:", len(imgs_val))
print(imgs_val[10:12])
print("验证标签数量:", len(labels_val))
print(labels_val[10:12])
dataset_train = tf.data.Dataset.from_tensor_slices((imgs, labels))
dataset_val = tf.data.Dataset.from_tensor_slices((imgs_val, labels_val))
## 1.2 图像预处理
# 1 读取图像
# 2 图像裁剪,先将img图像和label图像进行拼接,拼接成4通道影像,然后裁剪成网络需要的大小
# 3 图像翻转
# 4 图像归一化
### 1.2.1 读取图像
def read_png_img(path):
"读取原始3通道的图像"
img = tf.io.read_file(path)
img = tf.image.decode_jpeg(img, channels=3)
return img
def read_png_label(path):
"读取单通道的语义分割图像"
img = tf.io.read_file(path)
img = tf.image.decode_png(img, channels=1)
return img
### 1.2.2 剪切图像,本例中没有对图像进行裁剪,因为在测试集做的时候也需要resize成同样大小,这样会降低数据样本质量和准确率
### 另外因为本实验输入图像都是640*640,都是同样大小,如果不是同样大小,必须进行裁剪,让它们大小一样
def crop_img(img, mask):
concat_img = tf.concat([img, mask], axis=-1)
#concat_img = tf.image.resize(concat_img, (280,280), method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
crop_img1 = tf.image.random_crop(concat_img, [256,256,4])
# 如果直接用[:,:,3]那最后一个维度就没了,就是二维的了
# return crop_img1[:,:,:3], crop_img1[:,:,3]
# print(img_crop.shape, label_crop.shape)
# (256, 256, 3) (256, 256)
return crop_img1[:,:,:3], crop_img1[:,:,3:]
# print(img_crop.shape, label_crop.shape)
# (256, 256, 3) (256, 256, 1)
# 这样才能保留最后一个维度
### 1.2.3 归一化
def normal(img, mask):
"这里的两个输入分别代表图像和标签图像"
# 归一化到-1到1之间,如果除以255就归一化到了0-1之间
img = tf.cast(img, tf.float32)/127.5-1
# 这里不除以会超出34或者2类的限制
mask = mask/255
mask = tf.cast(mask, tf.int32)
return img, mask
### 1.2.4 进行图像的反转和整体的预处理实现
#处理后的图像的形状(256, 256, 3),(256, 256, 1)
def load_image_train(img_path, mask_path):
"对图像进行处理,输出的都是3维的"
# 1 先进行读取
img = read_png_img(img_path)
mask = read_png_label(mask_path)
# 2 再进行裁剪
img, mask = crop_img(img, mask)
# 3 再进行随即反转
if tf.random.uniform(())>0.5:
img = tf.image.flip_left_right(img)
mask = tf.image.flip_left_right(mask)
# 4 再进行归一化
img, mask = normal(img, mask)
return img, mask
def load_image_test(img_path, mask_path):
"对测试图像进行处理,输出的都是3维的"
# 1 先进行读取
img = read_png_img(img_path)
mask = read_png_label(mask_path)
# 2 进行裁剪
img, mask = crop_img(img, mask)
#img = tf.image.resize(img, (256, 256))
#mask = tf.image.resize(mask, (256, 256))
# 3 再进行归一化
img, mask = normal(img, mask)
return img, mask
# 让计算机根据cpu自动读取线程数
auto = tf.data.experimental.AUTOTUNE
dataset_train = dataset_train.map(load_image_train, num_parallel_calls = auto)
dataset_val = dataset_val.map(load_image_test, num_parallel_calls = auto)
2 训练验证数据在不同文件夹
import tensorflow as tf
import numpy as np
import os
import matplotlib.pyplot as plt
import glob
import matplotlib as mpl
import time
from Experiment_GF2.nets.unet import Unet_model
from tensorflow.keras import backend as K
# 使用cpu
#os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
# 使用cpu的时候需要把这个删除了
physical_device = tf.config.experimental.list_physical_devices("GPU")
tf.config.experimental.set_memory_growth(physical_device[0], True)
# 下面这行代码是为了绘图时显示中文
mpl.rcParams['font.sans-serif'] = ["SimHei"]
# 开始计时
time_start=time.time()
######################################### 1 获取图像和图像预处理
## 1.1 读取图像并进行打乱,生成数据集,这里是随机挑选了验证集
imgs = glob.glob(r'H:\01HTutorWork\3GF2\3Code\PestDetect3\dataset\images\*.jpg')
labels = glob.glob(r'H:\01HTutorWork\3GF2\3Code\PestDetect3\dataset\labels\*.png')
## 验证集单独存在一个文件夹里
imgs_val = glob.glob(r'I:\5GF2\5dataset\5dataset_jpg\3naturedatajpg\*.jpg')
labels_val = glob.glob(r'I:\5GF2\5dataset\5dataset_jpg\1labelsPNG\*.png')
# 这里注意一定要让图片和标签一一对应,本例中通过验证是对应的,但是一般都需要安名称进行重新排序,这样确保一致
# 这里进行一个乱序,为了让图像训练时,不至于每个批次的图像属于同一类,
# 当然语义分割中不需要进行乱序,因为本身每张图像就包括各种类型,本例中是因为有17个城市拍的照片,所以还是进行了排序
index= np.random.permutation(len(imgs))
imgs = np.array(imgs)[index]
labels = np.array(labels)[index]
# 检验标签是否对齐
for i in range(len(imgs)):
img = imgs[i].split("\\")[-1]
label = labels[i].split("\\")[-1]
if img[:-4]!=label[:-4]:
print("出错了"*1000)
index= np.random.permutation(len(imgs_val))
imgs_val = np.array(imgs_val)[index]
labels_val = np.array(labels_val)[index]
# 检验标签是否对齐
for i in range(len(imgs_val)):
kk_img = imgs_val[i].split("\\")[-1]
kk_label = labels_val[i].split("\\")[-1]
if kk_img[:-4]!=kk_label[:-4]:
print("出错了"*1000)
print("训练图像数量:", len(imgs))
print(imgs[566:570])
print("训练标签数量:", len(labels))
print(labels[566:570])
print("验证图像数量:", len(imgs_val))
print(imgs_val[10:12])
print("验证标签数量:", len(labels_val))
print(labels_val[10:12])
dataset_train = tf.data.Dataset.from_tensor_slices((imgs, labels))
dataset_val = tf.data.Dataset.from_tensor_slices((imgs_val, labels_val))
## 1.2 图像预处理
# 1 读取图像
# 2 图像裁剪,先将img图像和label图像进行拼接,拼接成4通道影像,然后裁剪成网络需要的大小
# 3 图像翻转
# 4 图像归一化
### 1.2.1 读取图像
def read_png_img(path):
"读取原始3通道的图像"
img = tf.io.read_file(path)
img = tf.image.decode_jpeg(img, channels=3)
return img
def read_png_label(path):
"读取单通道的语义分割图像"
img = tf.io.read_file(path)
img = tf.image.decode_png(img, channels=1)
return img
### 1.2.2 剪切图像,本例中没有对图像进行裁剪,因为在测试集做的时候也需要resize成同样大小,这样会降低数据样本质量和准确率
### 另外因为本实验输入图像都是640*640,都是同样大小,如果不是同样大小,必须进行裁剪,让它们大小一样
def crop_img(img, mask):
concat_img = tf.concat([img, mask], axis=-1)
#concat_img = tf.image.resize(concat_img, (280,280), method=tf.image.ResizeMethod.NEAREST_NEIGHBOR)
crop_img1 = tf.image.random_crop(concat_img, [256,256,4])
# 如果直接用[:,:,3]那最后一个维度就没了,就是二维的了
# return crop_img1[:,:,:3], crop_img1[:,:,3]
# print(img_crop.shape, label_crop.shape)
# (256, 256, 3) (256, 256)
return crop_img1[:,:,:3], crop_img1[:,:,3:]
# print(img_crop.shape, label_crop.shape)
# (256, 256, 3) (256, 256, 1)
# 这样才能保留最后一个维度
### 1.2.3 归一化
def normal(img, mask):
"这里的两个输入分别代表图像和标签图像"
# 归一化到-1到1之间,如果除以255就归一化到了0-1之间
img = tf.cast(img, tf.float32)/127.5-1
# 这里不除以会超出34或者2类的限制
mask = mask/255
mask = tf.cast(mask, tf.int32)
return img, mask
### 1.2.4 进行图像的反转和整体的预处理实现
#处理后的图像的形状(256, 256, 3),(256, 256, 1)
def load_image_train(img_path, mask_path):
"对图像进行处理,输出的都是3维的"
# 1 先进行读取
img = read_png_img(img_path)
mask = read_png_label(mask_path)
# 2 再进行裁剪
img, mask = crop_img(img, mask)
# 3 再进行随即反转
if tf.random.uniform(())>0.5:
img = tf.image.flip_left_right(img)
mask = tf.image.flip_left_right(mask)
# 4 再进行归一化
img, mask = normal(img, mask)
return img, mask
def load_image_test(img_path, mask_path):
"对测试图像进行处理,输出的都是3维的"
# 1 先进行读取
img = read_png_img(img_path)
mask = read_png_label(mask_path)
# 2 进行裁剪
img, mask = crop_img(img, mask)
#img = tf.image.resize(img, (256, 256))
#mask = tf.image.resize(mask, (256, 256))
# 3 再进行归一化
img, mask = normal(img, mask)
return img, mask
# 让计算机根据cpu自动读取线程数
auto = tf.data.experimental.AUTOTUNE
dataset_train = dataset_train.map(load_image_train, num_parallel_calls = auto)
dataset_val = dataset_val.map(load_image_test, num_parallel_calls = auto)
## 1.2 图像预处理结束
## 1.3 进行图像的shuffer和批次生成
# 这里是设置的一些参数
EPOCHS = 300
LEARNING_RATE = 0.0001
BATCH_SIZE = 8 # 32
BUFFER_SIZE = 300
Step_per_epoch = len(imgs)//BATCH_SIZE
Val_step = len(imgs_val)//BATCH_SIZE
dataset_train = dataset_train.shuffle(BUFFER_SIZE).batch(BATCH_SIZE)
dataset_val = dataset_val.batch(BATCH_SIZE)