UNet网络模型:数据集制作

11 篇文章 0 订阅

UNet网络模型:数据集制作

一般语义分割的原始图片和标记图片在以下目录下:

image-20230924235329548

SegmentationClass:标记图片。

JPEGImages:原始图片。

数据集往往都是很多的图片等信息,对于数据集类来说,一个类里有所有数据的信息,并且可以用下标进行访问,就像访问数组一样。

在pytorch中有Dataset类,用于创建自定义数据集类。我们可以用继承Dataset类来实现数据集类。在一个数据集类中,需要确定数据集所在的位置,也要用__getitem__实现下标访问,用__len__实现数据集大小。

对于标记图片和原始图片可能大小或者格式不同,需要将这两个图片的格式统一。

代码参考UNet数据集制作及代码实现_哔哩哔哩_bilibili,根据该UP主的代码,加上我的个人整理和理解。(这个UP主的代码感觉很好,很规范

目录的树形结构:

data/ (path) 
 |
 |
 |------- SegmentationClass/
 |               |
 |               |-- 标记图像
 |               |-- ...
 |               |-- 标记图像
 |
 |
 |
 |
 |------- JPEGImages/
                |
                |-- 原始图像
                |-- ...
                |-- 原始图像

原始图像和标记图像处理

from PIL import Image # 用于读取和处理图像

# 用于加载图像并保存图像大小一致
# path表示图像文件的路径,size表示需要调整的目标大小,默认为(256, 256)
def keep_image_size_open(path, size = (256, 256)):

    # 通过Image.open(path)方法打开path路径的图像,并将返回的图像对象保存在变量img中。
    img = Image.open(path)
    # 获取输入图像的最大边长
    tmp = max(img.size)
    # 创建一个新的空白图像对象mask,大小为(tmp, tmp),颜色为(0, 0, 0),即黑色。
    mask = Image.new("RGB", (tmp, tmp), (0,0,0))
    # 将原始图像img粘贴到mask图像对象的左上角,使得原始图像位于黑色背景之上。
    mask.paste(img, (0,0))
    # 将图像调整为目标大小,并返回调整后的图像对象mask。
    mask = mask.resize(size)
    return mask

数据集制作

import os # 路径操作
from torch.utils.data import Dataset # 继承 pytorch中的Dataset
from utils import * # 引入自己写的: 将原始图片和标记图片格式和规格统一
from torchvision import transforms # 用于数据预处理

################################################
#
#   transforms.Compose用于将多个变换操作组合在一起。
# 这里只有一个 ToTensor(),用于将图像数据转为张量格式
#
###############################################
transform = transforms.Compose([
    transforms.ToTensor()
])

##############################################
#
# 通过继承Dataset类,来实现自定义数据集类
#
##############################################
class MyDataset(Dataset):

    # path表示数据集的路径
    def __init__(self, path):
        self.path = path
        # path路径下的目录
        self.name = os.listdir(os.path.join(path, "SegmentationClass"))
    
    # 返回数据集长度
    def __len__(self):
        return len(self.name)
    
    # 实现下标访问
    def __getitem__(self, index):
        segment_name = self.name[index] # xx.png 得到的是:path/SegmentationClass/图像名字
        segment_path = os.path.join(self.path, "SegmentationClass", segment_name) # 得到标记图像路径
        # 得到原始图像路径。segment_name.replace(xxx,kkk) 表示如果标记图像和原始图像格式不同,进行后缀替代,进而得到正确的原始图像路径
        image_path = os.path.join(self.path, "JPEGImages", segment_name.replace("png", "jpg")) 

        # 将图像进行统一规格化
        segment_image = keep_image_size_open(segment_path)
        image = keep_image_size_open(image_path)

        # 返回经过transform处理后的图像张量
        return transform(image), transform(segment_image)

# 测试是否正确
if __name__ == "__main__":
    data = MyDataset(r"E:\Undergraduate\School\Scientific_research\ML\Machine_Learning\lab\图形分割\Unet模型总\data")
    print(data[0][0].shape)
    print(data[0][1].shape)

UNet网络制作

UNet数据集制作及代码实现_哔哩哔哩_bilibili

好的,以下是基于自己的数据集训练Unet模型的步骤: 1. 准备数据集:收集和整理训练数据,确保数据集中包含正确的标注信息。可以使用开源数据集,也可以自己制作数据集。 2. 数据增强:使用数据增强技术来扩充数据集,例如旋转、翻转、裁剪等操作,以增加数据集的多样性和数量。 3. 数据预处理:对数据进行预处理,例如对图像进行归一化、缩放等操作。 4. 构建模型:使用Keras或者PyTorch等框架,构建Unet模型,并根据实际需求进行修改和调整。 ```python from tensorflow.keras.models import Model from tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Dropout, UpSampling2D, concatenate def Unet(input_size): inputs = Input(input_size) # 编码器部分 conv1 = Conv2D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(inputs) conv1 = Conv2D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv1) pool1 = MaxPooling2D(pool_size=(2, 2))(conv1) conv2 = Conv2D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool1) conv2 = Conv2D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv2) pool2 = MaxPooling2D(pool_size=(2, 2))(conv2) conv3 = Conv2D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool2) conv3 = Conv2D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv3) pool3 = MaxPooling2D(pool_size=(2, 2))(conv3) conv4 = Conv2D(512, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool3) conv4 = Conv2D(512, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv4) drop4 = Dropout(0.5)(conv4) pool4 = MaxPooling2D(pool_size=(2, 2))(drop4) conv5 = Conv2D(1024, 3, activation='relu', padding='same', kernel_initializer='he_normal')(pool4) conv5 = Conv2D(1024, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv5) drop5 = Dropout(0.5)(conv5) # 解码器部分 up6 = Conv2D(512, 2, activation='relu', padding='same', kernel_initializer='he_normal')(UpSampling2D(size=(2, 2))(drop5)) merge6 = concatenate([drop4, up6], axis=3) conv6 = Conv2D(512, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge6) conv6 = Conv2D(512, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv6) up7 = Conv2D(256, 2, activation='relu', padding='same', kernel_initializer='he_normal')(UpSampling2D(size=(2, 2))(conv6)) merge7 = concatenate([conv3, up7], axis=3) conv7 = Conv2D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge7) conv7 = Conv2D(256, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv7) up8 = Conv2D(128, 2, activation='relu', padding='same', kernel_initializer='he_normal')(UpSampling2D(size=(2, 2))(conv7)) merge8 = concatenate([conv2, up8], axis=3) conv8 = Conv2D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge8) conv8 = Conv2D(128, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv8) up9 = Conv2D(64, 2, activation='relu', padding='same', kernel_initializer='he_normal')(UpSampling2D(size=(2, 2))(conv8)) merge9 = concatenate([conv1, up9], axis=3) conv9 = Conv2D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(merge9) conv9 = Conv2D(64, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv9) conv9 = Conv2D(2, 3, activation='relu', padding='same', kernel_initializer='he_normal')(conv9) # 输出层 outputs = Conv2D(1, 1, activation='sigmoid')(conv9) model = Model(inputs=inputs, outputs=outputs) return model ``` 5. 编写训练脚本: ```python import tensorflow as tf from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping # 加载数据 train_datagen = ImageDataGenerator( rescale=1./255, shear_range=0.2, zoom_range=0.2, horizontal_flip=True) train_generator = train_datagen.flow_from_directory( 'train/', target_size=(256, 256), batch_size=16, class_mode='binary') # 构建模型 model = Unet((256, 256, 3)) model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy']) # 设置回调函数 checkpoint = ModelCheckpoint('model.h5', monitor='val_loss', save_best_only=True, verbose=1) early_stop = EarlyStopping(monitor='val_loss', patience=10, verbose=1) # 训练模型 model.fit(train_generator, epochs=50, validation_data=val_generator, callbacks=[checkpoint, early_stop]) ``` 6. 模型评估:使用测试集对模型进行评估,并根据评估结果进行调整。 ```python val_datagen = ImageDataGenerator(rescale=1./255) val_generator = val_datagen.flow_from_directory( 'val/', target_size=(256, 256), batch_size=16, class_mode='binary') model.evaluate(val_generator) ``` 7. 模型应用:将训练好的模型用于实际应用中。 ```python from PIL import Image import numpy as np model = tf.keras.models.load_model('model.h5') img = Image.open('test.jpg') img = img.resize((256, 256)) img_array = np.array(img) img_array = np.expand_dims(img_array, axis=0) pred = model.predict(img_array) pred = np.squeeze(pred) pred = np.where(pred > 0.5, 1, 0) output = Image.fromarray(np.uint8(pred * 255)) output.show() ``` 以上是基于自己的数据集训练Unet模型的步骤,您可以根据实际情况进行调整和修改。如果您有其他问题,可以随时问我。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

golemon.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值