图像弹性形变(Elastic Distortion)(代码)

本文介绍了如何通过U-net模型结合弹性形变技术扩充数据集,以应对图像分割任务中的样本不足问题。作者提供了一个Python代码片段,展示了如何对彩色图像进行仿射变换和随机弹性形变,以增加训练数据的多样性。
摘要由CSDN通过智能技术生成

最近在学习U-net,看到了它是通过弹性形变来扩充数据集,网络上搜了搜原理,参考数据增强:弹性变形(Elastic Distortion) - 知乎 (zhihu.com)

正巧大作业是相关于宝塔纹的图像分割,老师只给了12张图片,于是准备应用弹性形变扩充数据集。

代码如下:

import cv2
import numpy as np
import os.path
import copy

from numpy.random import random
from scipy.ndimage.filters import gaussian_filter
from scipy.ndimage.interpolation import map_coordinates

#参数
def elastic_para1(image, alpha, sigma,
                      alpha_affine, random_state=None):

    if random_state is None:
        random_state = np.random.RandomState(None)

    shape = image.shape
    shape_size = shape[:2]
    # Random affine
    center_square = np.float32(shape_size) // 2
    square_size = min(shape_size) // 3
    # pts1: 仿射变换前的点(3个点)
    pts1 = np.float32([center_square + square_size,
                       [center_square[0] + square_size,
                        center_square[1] - square_size],
                       center_square - square_size])
    # pts2: 仿射变换后的点
    pts2 = pts1 + random_state.uniform(-alpha_affine, alpha_affine,
                                       size=pts1.shape).astype(np.float32)
    return pts1,pts2
def elastic_para2(image,pts1,pts2,random_state=None):
    if random_state is None:
        random_state = np.random.RandomState(None)
    shape = image.shape
    shape_size = shape[:2]
# 仿射变换矩阵
    M = cv2.getAffineTransform(pts1, pts2)
    # 对image进行仿射变换.
    imageB = cv2.warpAffine(image, M, shape_size[::-1], borderMode=cv2.BORDER_REFLECT_101)
    return imageB
def para3(image, alpha, sigma,
                      alpha_affine, random_state=None):
    if random_state is None:
        random_state = np.random.RandomState(None)
    shape = image.shape
    shape_size = shape[:2]
    # generate random displacement fields
    # random_state.rand(*shape)会产生一个和shape一样打的服从[0,1]均匀分布的矩阵
    # *2-1是为了将分布平移到[-1, 1]的区间, alpha是控制变形强度的变形因子
    dx = gaussian_filter((random_state.rand(*shape) * 2 - 1), sigma) * alpha
    dy = gaussian_filter((random_state.rand(*shape) * 2 - 1), sigma) * alpha
    # generate meshgrid
    x, y = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
    # x+dx,y+dy
    return x,y,dx,dy

#单次变换
def _single_elastic(image,imageB,x, y,
                      dx, dy):
    shape = image.shape
    print(shape)
    indices = np.reshape(y + dy, (-1, 1)), np.reshape(x + dx, (-1, 1))
    elastic_image = map_coordinates(imageB, indices, order=1, mode='constant').reshape(shape)
    return elastic_image

def elastic(image, alpha, sigma,
                      alpha_affine, random_state=None):
    shape = image.shape
    print(shape)
    is_color = len(image.shape) == 3

    pts1,pts2 = elastic_para1(image[:,:,2], alpha, sigma, alpha_affine, random_state=None)
    x, y, dx, dy = para3(image[:,:,2], alpha, sigma, alpha_affine, random_state=None)

    if is_color:
        # 如果是彩色图像,则单独处理每个通道
        result_channels = []
        # for channel in range(image.shape[2]):
        a = 3
        for channel in range(a):
            imageB = elastic_para2(image[:, :, channel],pts1,pts2,random_state)
            result_channel = _single_elastic(image[:, :, channel],imageB,x,y,dx,dy)
            # [:, :, channel]切片,[所以行,所有列,通道]
            print(channel)
            result_channels.append(result_channel) # append往列表里加东西
        return np.stack(result_channels, axis=2)  # stack函数是用于沿着指定的轴将一系列数组堆叠起来的。
        # axis=2参数指定了新的轴是第三个维度(维度从0开始计数,所以0是高度,1是宽度,2是颜色通道)
    else:
        # 如果是单通道图像,直接处理
        return _single_elastic(image,x,y,dx,dy)

file_dir = r'E:/1_project/unet-pytorch-main/unet-pytorch-main/img/'
for img_name in os.listdir(file_dir):
    img_path = file_dir + img_name
    img = cv2.imread(img_path)
    img_elastic = elastic(img, 200, 80,80)

    cv2.imwrite(file_dir + img_name[0:-4] + '_elastic.jpg', img_elastic)
    print(img_name[0:-4])
cell形变前
cell形变后

宝塔纹形变前
宝塔纹形变后

原理代码参考:数据增强:弹性变形(Elastic Distortion) - 知乎 (zhihu.com)

其他数据增强方法:图像增强python代码_python图像增强代码越长越好-CSDN博客

深度学习小白,有不对的地方请大佬指正。

上边代码三通道(彩色)可以应用,单通道灰度图会变成三通道,因为我作业用的是彩色图片,所以这块我还没改。后续可能会更新。

我的代码水平差的很......努力学习中!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值