深度学习 Day10——T10数据增强

  • 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
  • 🍖 原作者:K同学啊 | 接辅导、项目定制

文章目录

  • 前言
  • 一、我的环境
  • 二、代码实现与执行结果
    • 1.引入库
    • 2.设置GPU(如果使用的是CPU可以忽略这步)
    • 3.导入数据
    • 4.查看数据
    • 5.加载数据
    • 6.再次检查数据
    • 7.配置数据集
    • 8.可视化数据
    • 9.构建CNN网络模型
    • 10.编译模型
    • 11.训练模型
    • 12.模型评估
  • 三、知识点详解
    • 1.图像增强
    • 1.1TensorFlow 之中进行图像数据增强
      • 1.1.1使用 tf.keras 的预处理层进行图像数据增强
      • 1.1.2 使用 tf.image 进行数据增强
    • 1.2自定义增强函数
    • 1.3 图像增强数据与原始数据合并作为新样本
  • 总结


前言

本文将采用CNN实现猫狗识别。简单讲述实现代码与执行结果,并浅谈涉及知识点。
关键字:图像增强

一、我的环境

  • 电脑系统:Windows 11
  • 语言环境:python 3.8.6
  • 编译器:pycharm2020.2.3
  • 深度学习环境:TensorFlow 2.10.1
  • 显卡:NVIDIA GeForce RTX 4070

二、代码实现与执行结果

1.引入库

from PIL import Image
import numpy as np
from pathlib import Path
import tensorflow as tf
from tensorflow.keras import datasets, layers, models, regularizers
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping
from tensorflow.keras.applications.vgg16 import VGG16
from tensorflow.keras import layers, models, Input
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout, BatchNormalization
from tqdm import tqdm
import tensorflow.keras.backend as K
import matplotlib.pyplot as plt
import warnings

warnings.filterwarnings('ignore')  # 忽略一些warning内容,无需打印

2.设置GPU(如果使用的是CPU可以忽略这步)

'''前期工作-设置GPU(如果使用的是CPU可以忽略这步)'''
# 检查GPU是否可用
print(tf.test.is_built_with_cuda())
gpus = tf.config.list_physical_devices("GPU")
print(gpus)
if gpus:
    gpu0 = gpus[0]  # 如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True)  # 设置GPU显存用量按需使用
    tf.config.set_visible_devices([gpu0], "GPU")

执行结果

True
[PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]

3.导入数据

数据链接: 猫狗数据

'''前期工作-导入数据'''
data_dir = r"D:\DeepLearning\data\CatDog"
data_dir = Path(data_dir)

4.查看数据

'''前期工作-查看数据'''
image_count = len(list(data_dir.glob('*/*.png')))
print("图片总数为:", image_count)
image_list = list(data_dir.glob('cat/*.png'))
image = Image.open(str(image_list[1]))
# 查看图像实例的属性
print(image.format, image.size, image.mode)
plt.imshow(image)
plt.show()

执行结果:

图片总数为: 3400
JPEG (512, 512) RGB

在这里插入图片描述

5.加载数据

 '''数据预处理-加载数据'''
batch_size = 64
img_height = 224
img_width = 224
"""
关于image_dataset_from_directory()的详细介绍可以参考文章:https://mtyjkh.blog.csdn.net/article/details/117018789
"""
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=12,
    image_size=(img_height, img_width),
    batch_size=batch_size)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=12,
    image_size=(img_height, img_width),
    batch_size=batch_size)
# 我们可以通过class_names输出数据集的标签。标签将按字母顺序对应于目录名称。
class_names = train_ds.class_names
print(class_names)

运行结果:

Found 3400 files belonging to 2 classes.
Using 2720 files for training.
Found 3400 files belonging to 2 classes.
Using 680 files for validation.
['cat', 'dog']

6.再次检查数据

'''数据预处理-再次检查数据'''
# Image_batch是形状的张量(32,180,180,3)。这是一批形状180x180x3的32张图片(最后一维指的是彩色通道RGB)。
# Label_batch是形状(32,)的张量,这些标签对应32张图片
for image_batch, labels_batch in train_ds:
    print(image_batch.shape)
    print(labels_batch.shape)
    break

运行结果

(64, 224, 224, 3)
(64,)

7.配置数据集

AUTOTUNE = tf.data.AUTOTUNE


def preprocess_image(image, label):
    return (image / 255.0, label)


# 归一化处理
train_ds = train_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
val_ds = val_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)
test_ds = test_ds.map(preprocess_image, num_parallel_calls=AUTOTUNE)

train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)

8.可视化数据

'''数据预处理-可视化数据'''
plt.figure(figsize=(18, 3))
for images, labels in train_ds.take(2):
    for i in range(8):
        ax = plt.subplot(1, 8, i + 1)
        plt.imshow(images[i].numpy().astype("uint8"))
        plt.title(class_names[labels[i]], fontsize=40)
        plt.axis("off")
# 显示图片
plt.show()

在这里插入图片描述

9.构建CNN网络模型

#VGG16
def VGG16(class_names, img_height, img_width):
    model = models.Sequential([
        # 1
        layers.Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same',
                      input_shape=(img_height, img_width, 3)),
        layers.Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # 2
        layers.Conv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # 3
        layers.Conv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # 4
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # 5
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # FC
        layers.Flatten(),
        layers.Dense(4096, activation='relu'),
        layers.Dense(4096, activation='relu'),
        layers.Dense(len(class_names), activation='softmax')
      ])
    return model
model = VGG16(class_names, img_height, img_width)
model.summary()

网络结构结果如下:

Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 224, 224, 64)      1792      
                                                                 
 conv2d_1 (Conv2D)           (None, 224, 224, 64)      36928     
                                                                 
 max_pooling2d (MaxPooling2D  (None, 112, 112, 64)     0         
 )                                                               
                                                                 
 conv2d_2 (Conv2D)           (None, 112, 112, 128)     73856     
                                                                 
 conv2d_3 (Conv2D)           (None, 112, 112, 128)     147584    
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 56, 56, 128)      0         
 2D)                                                             
                                                                 
 conv2d_4 (Conv2D)           (None, 56, 56, 256)       295168    
                                                                 
 conv2d_5 (Conv2D)           (None, 56, 56, 256)       590080    
                                                                 
 conv2d_6 (Conv2D)           (None, 56, 56, 256)       590080    
                                                                 
 max_pooling2d_2 (MaxPooling  (None, 28, 28, 256)      0         
 2D)                                                             
                                                                 
 conv2d_7 (Conv2D)           (None, 28, 28, 512)       1180160   
                                                                 
 conv2d_8 (Conv2D)           (None, 28, 28, 512)       2359808   
                                                                 
 conv2d_9 (Conv2D)           (None, 28, 28, 512)       2359808   
                                                                 
 max_pooling2d_3 (MaxPooling  (None, 14, 14, 512)      0         
 2D)                                                             
                                                                 
 conv2d_10 (Conv2D)          (None, 14, 14, 512)       2359808   
                                                                 
 conv2d_11 (Conv2D)          (None, 14, 14, 512)       2359808   
                                                                 
 conv2d_12 (Conv2D)          (None, 14, 14, 512)       2359808   
                                                                 
 max_pooling2d_4 (MaxPooling  (None, 7, 7, 512)        0         
 2D)                                                             
                                                                 
 flatten (Flatten)           (None, 25088)             0         
                                                                 
 dense (Dense)               (None, 4096)              102764544 
                                                                 
 dense_1 (Dense)             (None, 4096)              16781312  
                                                                 
 dense_2 (Dense)             (None, 2)                 8194      
                                                                 
=================================================================
Total params: 134,268,738
Trainable params: 134,268,738
Non-trainable params: 0
_________________________________________________________________

10.编译模型

'''编译模型'''
#设置初始学习率
initial_learning_rate = 1e-4
opt = tf.keras.optimizers.Adam(learning_rate=initial_learning_rate)
model.compile(optimizer=opt,
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

11.训练模型

'''训练模型'''
epochs = 10
history = model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=epochs,
    shuffle=False
)

训练记录如下:

Epoch 1/10

43/43 [==============================] - 42s 606ms/step - loss: 0.6830 - accuracy: 0.5511 - val_loss: 0.7328 - val_accuracy: 0.6630
Epoch 2/10
43/43 [==============================] - 17s 384ms/step - loss: 0.4927 - accuracy: 0.7614 - val_loss: 0.3283 - val_accuracy: 0.8714
Epoch 3/10
43/43 [==============================] - 17s 385ms/step - loss: 0.2113 - accuracy: 0.9165 - val_loss: 0.1986 - val_accuracy: 0.9221
Epoch 4/10
43/43 [==============================] - 17s 385ms/step - loss: 0.1173 - accuracy: 0.9555 - val_loss: 0.0977 - val_accuracy: 0.9620
Epoch 5/10
43/43 [==============================] - 17s 385ms/step - loss: 0.0561 - accuracy: 0.9798 - val_loss: 0.0789 - val_accuracy: 0.9728
Epoch 6/10
43/43 [==============================] - 17s 385ms/step - loss: 0.0483 - accuracy: 0.9816 - val_loss: 0.0578 - val_accuracy: 0.9783
Epoch 7/10
43/43 [==============================] - 17s 385ms/step - loss: 0.0457 - accuracy: 0.9838 - val_loss: 0.0551 - val_accuracy: 0.9783
Epoch 8/10
43/43 [==============================] - 17s 385ms/step - loss: 0.0372 - accuracy: 0.9875 - val_loss: 0.0985 - val_accuracy: 0.9692
Epoch 9/10
43/43 [==============================] - 17s 385ms/step - loss: 0.0324 - accuracy: 0.9915 - val_loss: 0.0264 - val_accuracy: 0.9873
Epoch 10/10
43/43 [==============================] - 17s 385ms/step - loss: 0.0109 - accuracy: 0.9967 - val_loss: 0.0408 - val_accuracy: 0.9891
2/2 [==============================] - 0s 116ms/step - loss: 0.0615 - accuracy: 0.9922
Accuracy 0.9921875


12.模型评估

'''模型评估'''
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(len(loss))
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)

执行结果
在这里插入图片描述

2/2 [==============================] - 0s 116ms/step - loss: 0.0615 - accuracy: 0.9922
Accuracy 0.9921875

三、知识点详解

1.图像增强

在深度学习中,有的时候训练集不够多,或者某一类数据较少,或者为了防止过拟合,让模型更加鲁棒性,data augmentation是一个不错的选择。
通过数据增强,我们可以将一些已经存在的数据进行相应的变换(可以选择将这些变换之后的数据增加到新的原来的数据集之中,也可以直接在原来的数据集上进行变换),从而实现数据种类多样性的增加。
对于图片数据,常见的数据增强方式包括:

  • 随机水平翻转:
  • 随机的裁剪;
  • 随机调整明亮程度;
  • 其他方式等

1.1TensorFlow 之中进行图像数据增强

在 TensorFlow 之中进行图像数据增强的方式主要有两种:

  • 使用 tf.keras 的预处理层进行图像数据增强;
  • 使用 tf.image 进行数据增强。

1.1.1使用 tf.keras 的预处理层进行图像数据增强

使用 tf.keras 的预处理层进行图像数据增强要使用的最主要的 API 包括在一下包之中:

tf.keras.layers.experimental.preprocessing

在这个包之中,我们最常用的数据增强 API 包括:

tf.keras.layers.experimental.preprocessing.RandomFlip(mode): 将输入的图片进行随机翻转,一般我们会取 mode=“horizontal” ,因为这代表水平旋转;而 mode=“vertical” 则代表随机进行上下翻转;
tf.keras.layers.experimental.preprocessing.RandomRotation§: 按照旋转角度(单位为弧度) p 将输入的图片进行随机的旋转;
tf.keras.layers.experimental.preprocessing.RandomContrast§:按照 P 的概率将输入的图片进行随机的图像色相翻转;
tf.keras.layers.experimental.preprocessing.CenterCrop(height, width):使用 height * width 的大小的裁剪框,在数据的中心进行裁剪。
该API有两种使用方式:一个是将其嵌入model中,一个是在Dataset数据集中进行数据增强

方式一:嵌入model中
调用方式如下

# tf.keras.layers.experimental.preprocessing图像增强 第一个层表示进行随机的水平和垂直翻转,而第二个层表示按照 0.2 的弧度值进行随机旋转。
data_augmentation = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical",input_shape=(img_height, img_width, 3)),
  tf.keras.layers.experimental.preprocessing.RandomRotation(0.2),
])
model = tf.keras.Sequential([
  data_augmentation,
  layers.Conv2D(16, 3, padding='same', activation='relu'),
  layers.MaxPooling2D(),
])
# 图像增强 可视化效果图
for images, labels in train_ds.take(1):
    # Add the image to a batch.
    image = tf.expand_dims(images[0], 0)
    plt.figure(figsize=(8, 8))
    for i in range(9):
        augmented_image = data_augmentation(image)
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(augmented_image[0])
        plt.axis("off")
    plt.show()
    break

本文案例使用如下

data_augmentation = tf.keras.Sequential([
  tf.keras.layers.experimental.preprocessing.RandomFlip("horizontal_and_vertical",input_shape=(img_height, img_width, 3)),
  tf.keras.layers.experimental.preprocessing.RandomRotation(0.2),
])
#方式一图像增强:tf.keras.layers.experimental.preprocessing方式实现的图像增强,嵌入模型中
#只有在模型训练时(Model.fit)才会进行增强,在模型评估(Model.evaluate)以及预测(Model.predict)时并不会进行增强操作
def VGG16_aug0(class_names, img_height, img_width):
    model = models.Sequential([
        data_augmentation,
        # 1
        layers.Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same',
                      input_shape=(img_height, img_width, 3)),
        layers.Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # 2
        layers.Conv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=128, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # 3
        layers.Conv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=256, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # 4
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # 5
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.Conv2D(filters=512, kernel_size=(3, 3), activation='relu', padding='same'),
        layers.MaxPool2D(pool_size=(2, 2), strides=2),
        # FC
        layers.Flatten(),
        layers.Dense(4096, activation='relu'),
        layers.Dense(4096, activation='relu'),
        layers.Dense(len(class_names), activation='softmax')
      ])
    return model
model = VGG16_aug0(class_names, img_height, img_width) # 方式一图像增强
model.summary()

# 图像增强 可视化效果图
for images, labels in train_ds.take(1):
    # Add the image to a batch.
    image = tf.expand_dims(images[0], 0)
    plt.figure(figsize=(8, 8))
    for i in range(9):
        augmented_image = data_augmentation(image)
        ax = plt.subplot(3, 3, i + 1)
        plt.imshow(augmented_image[0])
        plt.axis("off")
    plt.show()
    break

在这里插入图片描述

在这里插入图片描述

方式二:在Dataset数据集中进行数据增强
本文案例使用如下

#方式二图像增强:tf.keras.layers.experimental.preprocessing方式实现的图像增强.在Dataset数据集中进行数据增强
AUTOTUNE = tf.data.AUTOTUNE

def prepare(ds):
    ds = ds.map(lambda x, y: (data_augmentation(x, training=True), y), num_parallel_calls=AUTOTUNE)
    return ds
train_ds1 = prepare(train_ds)

'''训练模型'''
epochs = 20
history = model.fit(
    train_ds1,
    validation_data=val_ds,
    epochs=epochs    
)

在这里插入图片描述
本文试验效果并不理想

1.1.2 使用 tf.image 进行数据增强

使用 tf.image 是 TensorFlow 最原生的一种增强方式,使用这种方式可以实现更多、更加个性化的数据增强。

其中包含的数据增强方式主要包括:

tf.image.flip_left_right (img):将图片进行水平翻转;
tf.image.rgb_to_grayscale (img):将 RGB 图像转化为灰度图像;
tf.image.adjust_saturation (image, f):将 image 图像按照 f 参数进行饱和度的调节;
tf.image.adjust_brightness (image, f):将 image 图像按照 f 参数进行亮度的调节;
tf.image.central_crop (image, central_fraction):按照 p 的比例进行图片的中心裁剪,比如如果 p 是 0.5 ,那么裁剪后的长、宽就是原来图像的一半;
tf.image.rot90 (image):将 image 图像逆时针旋转 90 度。
可以看到,很多的 tf.image 数据增强方式并不提供随机化选项,因此我们需要手动进行随机化。

也正是因为上述特性,tf.image 数据增强主要用在一些自定义的模型之中,从而可以实现数据增强的自定义化。

参考链接在 TensorFlow 之中进行数据增强

1.2自定义增强函数

import random
# 这是大家可以自由发挥的一个地方
def aug_img(image,label):
    seed = (random.randint(0, 9), 0)
    # 随机改变图像对比度
    stateless_random_brightness = tf.image.stateless_random_contrast(image, lower=0.1, upper=1.0, seed=seed)
    return stateless_random_brightness,label
train_ds2 = train_ds.map(aug_img, num_parallel_calls=AUTOTUNE)

# 图像增强 可视化效果图
for images, labels in train_ds.take(1):
    # Add the image to a batch.
    image = tf.expand_dims(images[0], 0)
    plt.figure(figsize=(8, 8))
    for i in range(9):
        augmented_image = aug_img(image)
        ax = plt.subplot(3, 3, i + 1)
        # plt.imshow(augmented_image[0].numpy().astype("uint8"))
        plt.imshow(augmented_image[0][0])
        plt.axis("off")
    plt.show()
    break

在这里插入图片描述
在这里插入图片描述
效果也不是很理想,知道调用方法就行,针对不同案例实现图像增强

1.3 图像增强数据与原始数据合并作为新样本

操作步骤如下:

  • 读取原始数据并图像增强
  • 保存增强效果图
  • 将原始数据与新生成的增强数据一起符号链接到新目录

读取原始数据并图像增强,保存增强效果图

from pathlib import Path
import cv2
import matplotlib.pyplot as plt
import warnings

warnings.filterwarnings('ignore')  # 忽略一些warning内容,无需打印
def saveaugimg(imgfile,newdir,prefix="aug_"):

    # cv2保存中文路径的图像
    imgFile = imgfile  # 读取文件的路径
    img = cv2.imread(imgFile, flags=1)  # flags=1 读取彩色图像(BGR)
    img1 = cv2.flip(img, 2)  # 水平翻转
    img2 = cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)
    # plt.imshow(img2)
    # plt.show()
    saveFile = imgfile.replace(r"D:\DeepLearning\data\CatDog", newdir)  # 带有中文的保存文件路径
    newname=prefix+str(Path(imgfile).name)
    saveFile = Path(saveFile).parent / newname
    Path(saveFile).parent.mkdir(parents=True, exist_ok=True)  # 创建新文件夹
    # cv2.imwrite(saveFile, img)  # imwrite 不支持中文路径和文件名,读取失败,但不会报错!
    img_write = cv2.imencode(".jpg", img1)[1].tofile(saveFile)

dirs=r"D:\DeepLearning\data\CatDog"
newdir = r"D:\DeepLearning\data\CatDog_aug"
for p in Path(dirs).rglob("*"):
    if p.is_file():  # 如果是文件
        imgfile=str(p)
        saveaugimg(imgfile, newdir)

将原始数据与新生成的增强数据一起符号链接到新目录

from pathlib import Path


# 对目录dirs做符号链接
def createslinkbatfile(dirs, slinkdirs, batfile="slink.bat"):
    print(f"为{dirs}创建符号链接目录{slinkdirs}\n")
    # 创建符号链接目录
    Path(slinkdirs).mkdir(parents=True, exist_ok=True)

    # 创建bat文件,为了解决bat脚本中文输出乱码问题,
    # 我们需要在bat脚本开头添加chcp 65001来设置控制台编码格式为UTF-8。
    # 同时,我们还需要使用setlocal enabledelayedexpansion启用延迟变量扩展
    with open(batfile, 'a', encoding='utf-8') as file:
        file.write("@echo off\nchcp 65001\nsetlocal enabledelayedexpansion " + '\n')

    # 遍历目标目录下的文件夹及文件,创建符号链接cmd命令
    for p in Path(dirs).rglob("*"):
        slink = Path(str(p).replace(str(dirs), str(slinkdirs)))  # 替换符号链接文件夹目录
        if p.is_dir():  # 目录符号链接
            command = f"mklink /d \"{slink}\" \"{str(p)}\""
        else:  # 文件符号链接
            command = f"mklink \"{slink}\" \"{str(p)}\""

        # 将符号链接cmd命令写入bat文件
        with open(batfile, 'a', encoding='utf-8') as file:
            # 增加编码encoding='utf-8',解决中文乱码问题解决方法
            file.write(command + '\n')
            print(command)


# 对目录dirs做符号链接,生成后右击bat文件,选用管理员身份运行

Path("slink.bat").unlink(missing_ok=False)# 删除bat文件
dirs=r"D:\DeepLearning\data\CatDog"
newdirs = r"D:\DeepLearning\data\CatDog_aug"
slinkdirs = r"D:\DeepLearning\data\CatDog_all"
createslinkbatfile(dirs, slinkdirs)
createslinkbatfile(newdirs, slinkdirs)

部分bat内容同如下

@echo off
chcp 65001
setlocal enabledelayedexpansion 
mklink /d "D:\DeepLearning\data\CatDog_all\cat" "D:\DeepLearning\data\CatDog\cat"
mklink /d "D:\DeepLearning\data\CatDog_all\dog" "D:\DeepLearning\data\CatDog\dog"
mklink "D:\DeepLearning\data\CatDog_all\cat\flickr_cat_000002.jpg" "D:\DeepLearning\data\CatDog\cat\flickr_cat_000002.jpg"
mklink "D:\DeepLearning\data\CatDog_all\cat\flickr_cat_000003.jpg" "D:\DeepLearning\data\CatDog\cat\flickr_cat_000003.jpg"
mklink "D:\DeepLearning\data\CatDog_all\cat\flickr_cat_000004.jpg" "D:\DeepLearning\data\CatDog\cat\flickr_cat_000004.jpg"
mklink "D:\DeepLearning\data\CatDog_all\cat\flickr_cat_000005.jpg" "D:\DeepLearning\data\CatDog\cat\flickr_cat_000005.jpg"

tf.keras.preprocessing.image_dataset_from_directory()传入新的文件夹目录

data_dir1 = r"D:\DeepLearning\data\CatDog_all"  # 将自定义数据增强后的数据保存后,与原始数据一起合并加入样本中
data_dir = Path(data_dir1)

在这里插入图片描述

总结

通过本次的学习,学习到了几种图像增强调用方式,原文中增强方式均为增强数据替代原始数据加入训练集,本文加入将增强数据与原始数据一起合并作为样本的方法,本文中的增强方式加入案例,效果并没有很理想,跟数据集实际情况有关,可将本文提到的图像增强方式运用到其他案例中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/238205.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Vue3-05-计算属性使用详解

计算属性简介 计算属性的函数是 computed()。计算属性可以帮助我们处理有复杂逻辑的响应式数据的渲染, 从而代替 模板表达式 的写法。比如 : 一个数值类型的数组对象,我们希望页面展示的只有 偶数。 此时,就可以通过 计算属性 来…

美食大赛的题解

目录 原题描述: 题目描述: 输入格式: 输出格式: 样例输入: 样例输出: 数据规模: 题目大意: 主要思路: 注: 代码: 原题描述&#xff1a…

家具制造ERP软件包含哪些功能?家具制造业ERP系统哪个好

不同的家具有不同的用料、品质、制造工时、营销渠道等,而有些家具制造企业采用传统的管理方式在处理物料BOM、生产实际成本核算、库存盘点、供应商选择、班组计件核对、生产领用以及物料追溯等方面存在不少提升空间。 与此同时也有很多的皮具制造企业借助ERP软件优…

Qt的坐标系系统 - 3个坐标系,2个变换

参考: https://zhuanlan.zhihu.com/p/584048811https://www.zhihu.com/tardis/zm/art/634951149?source_id1005 小谈Qt的坐标系系统 Qt中有三个坐标系 设备坐标系窗口坐标系逻辑坐标系 设备坐标系: 即Device坐标系。也是物理坐标系。即真实的的物理坐标系。 …

[IDEA] 写代码时没有类型推断的解决方法

本示例使用scala, 其他语言同理 使用 .var 时会自动生成变量 使用快捷键 CtrlAtlv 一样 val abc "abc"但是这个变量没有显式表现类型 期望 val abc: String "abc" 解决方法

python自动化运维快速入门,python自动化运维教程

大家好,给大家分享一下python自动化运维需要掌握的技能,很多人还不知道这一点。下面详细解释一下。现在让我们来看看! 面向学员 熟练使用计算机,对Windows、Linux 有一点了解从业职或在校学生 对目前从事互联网运维,想…

23种设计模式之模板方法模式(模板模式)

23种设计模式之模板方法模式(模板模式) 文章目录 23种设计模式之模板方法模式(模板模式)设计思想模板方法的优缺点模板方法模式的缺点代码解析小结 设计思想 原文:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构…

网络基础(五):网络层协议介绍

目录 一、网络层 1、网络层的概念 2、网络层功能 3、IP数据包格式 二、ICMP协议 1、ICMP的作用和功能 2、ping命令的使用 2.1ping命令的通用格式 2.2ping命令的常用参数 2.3TypeCode:查看不同功能的ICMP报文 2.4ping出现问题 3、Tracert 4、冲突域 5、…

2024年骨传导蓝牙耳机排行榜前十,骨传导耳机品牌排行榜推荐

2024年骨传导蓝牙耳机排行榜前十,骨传导耳机品牌排行榜推荐 随着科技的飞速发展,骨传导蓝牙耳机已经成为了市场上备受欢迎的音频设备。这种神奇的耳机通过骨头传递声音,让你在享受音乐的同时,还能听到周围的环境,为你…

【触想智能】工业显示器的日常维护及分类知识分享

工业显示器不同于普通商业显示器,它的结构比较复杂,如果在使用的过程中出现产品故障,我们怎么处理呢?今天小编为大家介绍工业显示器日常维护以及分类方面的知识,希望对大家有所帮助。 1、 工业显示器整机无电。这其实是一个非常简…

class077 区间dp-下【算法】

class077 区间dp-下【算法】 算法讲解077【必备】区间dp-下 code1 括号区间匹配 // 完成配对需要的最少字符数量 // 给定一个由’[‘、’]‘、’(‘,’)‘组成的字符串 // 请问最少插入多少个括号就能使这个字符串的所有括号正确配对 // 例如当前串是 “([[])”&a…

python——第十七天

方法重写(overwrite) 、方法覆盖(override ):在继承的基础上,子类继承了父类的方法,如果不能满足自己使用,我们就可以重写或覆盖该方法 函数重载(overload): 在强数据类型的编程语言中(如Java、C、C等等): 函数名称…

C语言常用字符串

目录 1.什么是字符串 2.如何定义字符串 第3和第4定义的区别:3是字符串变量,4是字符串常量,不予许被修改 3.strlen和sizeof的区别 4.地址分配(malloc,realloc,free,memset) 案例 5.字符串拷贝(strcpy,strncpy) …

【每日一题】【12.11】1631.最小体力消耗路径

🔥博客主页: A_SHOWY🎥系列专栏:力扣刷题总结录 数据结构 云计算 数字图像处理 1631. 最小体力消耗路径https://leetcode.cn/problems/path-with-minimum-effort/这道题目的核心思路是:使用了二分查找和BFS &a…

【NR技术】NR NG-RAN整体架构 -网络接口以及无线协议框架(四)

1 引言 本博文介绍NR NG-RAN的网络节点间的接口以及无线协议框架。网络接口介绍包括RAN和NGC之间的NG接口;无线协议框架包括用户面和控制面协议。 2 NG接口 2.1 NG用户面接口 NG-U (user plane interface)是NG-RAN节点与UPF之间的接口。NG接口的用户平面协议栈如图…

1688以图搜图调用商品详情的API接口功能实现【附详细代码教程】

背景 在1688有个功能,就是上传图片,就可以找到类似的商品。如下 网址 :https://www.1688.com/ 这时候,我们可以使用程序来代替,大批量的完成图片上传功能。 实现思路 1、找到图片上传接口 post请求,for…

禾匠榜店商城系统 RCE漏洞复现

0x01 产品简介 禾匠榜店商城系统是浙江禾匠信息科技有限公司的一套基于PHP和MySQL的商城系统。 0x02 漏洞概述 禾匠榜店商城系统的api/testOrderSubmit模块下的preview方法存在命令执行漏洞,攻击者可以向服务器写入木马文件,直接获取服务器权限 0x03 漏洞概述 FOFA:bod…

【qt】Qt+OpenCv读取带有中文路径的图片

【opencv4.5.1版本】下载exe解压即可。。。https://opencv.org/releases/page/2/ 【qt5.15.2】 pro文件 QT core guigreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c17# You can make your code fail to compile if it uses deprecated APIs. # In order to …

2.Feign使用、上下文隔离及源码阅读

目录 概述使用配置pom.xmlfeign 接口编写controller 测试降级处理pom.xmlapplication.yml代码 Feign如何初始化及调用源码阅读初始化调用 feign的上下文隔离机制源码 结束 概述 阅读此文,可以知晓 feign 使用、上下文隔离及源码阅读。源码涉及两方面:fe…

elk:filebeat

elk:filebeat日志收集工具和logstash相同 filebeat是一个轻量级的日志收集工具,所使用的系统资源比logstash部署和启动时使用的资源要小的多。 filebeat可以运行在非java环境,他可以代替logstash在非java环境上收集日志。 filebeat无法实现数据的过滤…