keras之语义分割ImageDataGenerator with masks as labels

本文探讨了在语义分割任务中如何通过数据增强来提升模型性能,详细介绍了使用Keras ImageDataGenerator进行旋转、翻转、缩放等操作,并确保增强后的图像与其mask保持一致性的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

与普通的分类不同的是 ,语义分割出来的mask和label都是图片,要是有旋转,颠倒等增强数据集,要保持mask和label一一对应,需要对图片生成器进行处理,用随机种子seed去解决这个问题

 

1.

datagen = ImageDataGenerator( rotation_range=4) and then you could use
for batch in datagen.flow(x, batch_size=1,seed=1337 ): with random seed and use datagen.flow once on X and then on the mask y and save the batches. This should do the same rotations on both X and y, but maybe dont work with ZCA and other normalizations.

2. 

i dont know if you can use batchsize > 1. If you look at the example on the page, they treat x as 1 image. Ok they did this just for plotting reasons but i dont know if this would also work for batchsizes > 1. I would Loop over my imageset and set x to the current image, then apply the imagegenerator like in the example and then use the same generator again on the mask like
mask=[] img=[]
for batch in datagen.flow(x, batch_size=1, seed=1337): img.append(batch)

for batch in datagen.flow(ymask, batch_size=1, seed=1337): mask.append(batch)

3.目录方式

data_gen_args = dict(width_shift_range=0.2, height_shift_range=0.2)
image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)
seed = 1
image_generator = image_datagen.flow_from_directory('raw/train_image', target_size=(img_rows,img_cols),
                                                        class_mode=None, seed=seed, batch_size=batchsize, color_mode='grayscale')
mask_generator = mask_datagen.flow_from_directory('raw/train_mask', target_size=(img_rows,img_cols),
                                                       class_mode=None, seed=seed, batch_size=batchsize, color_mode='grayscale')

train_generator = zip(image_generator, mask_generator)

model.fit_generator(train_generator, steps_per_epoch=5635/batchsize, epochs=100, verbose=1)

4.

def applyImageAugmentationAndRetrieveGenerator():
    from keras.preprocessing.image import ImageDataGenerator

# We create two instances with the same arguments
data_gen_args = dict(rotation_range=90.,
                     width_shift_range=0.1,
                     height_shift_range=0.1,
                     zoom_range=0.2
                     )
image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)

# Provide the same seed and keyword arguments to the fit and flow methods
seed = 1

image_generator = image_datagen.flow_from_directory('dataset/train_images',
                                                    target_size=(360,480),    
                                                    class_mode=None,
                                                    seed=seed,
                                                    batch_size = 32)

mask_generator = mask_datagen.flow_from_directory('dataset/train_masks',
                                                  target_size=(360,480),  
                                                  class_mode=None,
                                                  seed=seed,
                                                  batch_size = 32)

#Combine generators into one which yields image and masks
#print(image_generator[0])
#print(mask_generator[0])
train_generator = zip(image_generator, mask_generator)
return train_generator




#引用

segmentation_model.fit_generator(training_generator,
                                 steps_per_epoch=186, 
                                 epochs=50,
                                 verbose=1
                                 )

5.   当获取到的是矩阵的mask和label

def train_generator(img_dir, label_dir, batch_size, input_size):
    list_images = os.listdir(img_dir)
    shuffle(list_images) #Randomize the choice of batches
    ids_train_split = range(len(list_images))
    while True:
         for start in range(0, len(ids_train_split), batch_size):
            x_batch = []
            y_batch = []
            end = min(start + batch_size, len(ids_train_split))
            ids_train_batch = ids_train_split[start:end]
            for id in ids_train_batch:
                img = cv2.imread(os.path.join(img_dir, list_images[id]))
                img = cv2.resize(img, (input_size[0], input_size[1]))
                mask = cv2.imread(os.path.join(label_dir, list_images[id].replace('jpg', 'png')), 0)
                mask = cv2.resize(mask, (input_size[0], input_size[1]))
                mask = np.expand_dims(mask, axis=2)
                x_batch.append(img)
                y_batch.append(mask)

            x_batch = np.array(x_batch, np.float32) / 255.
            y_batch = np.array(y_batch, np.float32)

            yield x_batch, y_batch

 

Without the hassle of organizing the folders for the case that one map matches on one mask as the answer above, we can use .flow()
my working code:
`def augmentationForTrainImageAndMask(imgs, masks):

data_gen_args = dict(rotation_range=40.,
width_shift_range=0.1,
height_shift_range=0.1,
zoom_range=0.2,
horizontal_flip=True,
fill_mode='nearest'
)

image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)

seed = 1
image_datagen.fit(imgs, augment=True, seed=seed)
mask_datagen.fit(masks, augment=True, seed=seed)

image_generator = image_datagen.flow(imgs,
                                     seed=seed,
                                     batch_size=batch_size,
                                     shuffle=False)

mask_generator = mask_datagen.flow(masks,
                                   seed=seed,
                                   batch_size=batch_size,
                                   shuffle=False)

return zip(image_generator, mask_generator)`

 

地址:https://github.com/keras-team/keras/issues/3059 

### 语义分割中边界损失函数的实现方法 #### 边界损失函数的重要性 在语义分割任务中,边界损失函数被广泛应用于提升模型对物体边界的敏感程度。通过优化边界区域的表现,可以有效改善分割结果的质量[^1]。 #### 常见的边界损失函数及其特性 常用的边界损失函数包括但不限于 Dice Loss、Focal Loss 和 Boundary Loss。这些损失函数的设计旨在解决不同类型的挑战,例如类别不平衡或边缘细节丢失等问题[^3]。 - **Dice Loss**: 主要用于衡量预测掩码真实掩码之间的相似度。其定义如下: ```python import torch import torch.nn as nn class DiceLoss(nn.Module): def __init__(self, smooth=1e-5): super(DiceLoss, self).__init__() self.smooth = smooth def forward(self, pred, target): intersection = (pred * target).sum() union = pred.sum() + target.sum() dice_coefficient = (2.0 * intersection + self.smooth) / (union + self.smooth) return 1 - dice_coefficient ``` - **Boundary Loss**: 特别针对物体边界设计的一种损失函数,适用于需要精确捕捉对象轮廓的任务: ```python from scipy.ndimage.morphology import distance_transform_edt def compute_boundary_loss(pred_mask, true_mask): """ Compute boundary loss between predicted and ground truth masks. Args: pred_mask: Predicted mask tensor of shape (batch_size, height, width). true_mask: Ground truth mask tensor of the same shape. Returns: Scalar value representing the boundary loss. """ # Convert to numpy arrays for morphological operations pred_np = pred_mask.detach().cpu().numpy() true_np = true_mask.cpu().numpy() batch_size = pred_np.shape[0] total_loss = 0 for i in range(batch_size): dist_pred = distance_transform_edt(1 - pred_np[i]) dist_true = distance_transform_edt(1 - true_np[i]) boundary_loss = ((dist_pred - dist_true)**2).mean() total_loss += boundary_loss return total_loss / batch_size ``` #### 使用 PyTorch 或 TensorFlow 的实现建议 无论是使用 PyTorch 还是 TensorFlow,都可以灵活地自定义损失函数来适应特定需求: ##### PyTorch 实现 PyTorch 提供了强大的自动求导功能以及丰富的工具库支持复杂的张量操作。上述 `compute_boundary_loss` 函数即是一个简单的例子[^4]。 ##### TensorFlow 实现 对于 TensorFlow 用户而言,可以通过 Keras 自定义层或者直接编写损失函数完成类似的功能。以下是基于 TensorFlow 的简单示例: ```python import tensorflow as tf def boundary_loss(y_true, y_pred): """ Custom boundary loss function implemented using TensorFlow. Args: y_true: Tensor containing the ground truth labels. y_pred: Tensor containing the model predictions. Returns: A scalar value indicating the computed boundary loss. """ # Perform Euclidean Distance Transform on binary masks edt_true = tf.numpy_function(distance_transform_edt, [y_true], Tout=tf.float32) edt_pred = tf.numpy_function(distance_transform_edt, [y_pred], Tout=tf.float32) diff_squared = tf.square(edt_pred - edt_true) mean_diff = tf.reduce_mean(diff_squared) return mean_diff ``` #### 总结 边界损失函数的选择应综合考虑具体的应用场景和技术约束条件。尽管深度学习模型具备高性能和强鲁棒性的优势[^2],但在实际部署过程中仍需注意计算资源消耗和数据标注成本高等潜在问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值