Brain Tumor Detection-CV 研究ノート 2 - データ拡張 (データ拡張)

1. 前処理後

CV データは、前処理後に次の仕様を満たす必要があります。

  • img、mask — 元の画像と切り取った画像のパスをそれぞれ保存する 2 つの配列 (str)
  • imgs、mask — 元のイメージと切り取ったイメージ (テンソル) をそれぞれ保存する 2 つの配列
  • マスクには 0 と 1 のみがあり、imgs 変数の型は torch.long です。

2. データの拡張

データ拡張は、データ ジェネレーターがデータをキャプチャするときに調整され、キャプチャされたデータはそれに応じて処理されてモデルに投入されます。現在、次の機能強化が計画されています: ランダム クロッピング (近接補間)、水平反転、

torchvision.transforms は、pytorchの画像前処理パッケージです。一般に、Compose は複数のステップを統合するために使用されます。これを使用して標準化操作を実行し、3 つのレイヤーの標準化と差異を入力できます。画像とセグメントの同期が失われる可能性があるため、トリミングなどの拡張機能は実行しないことをお勧めします。

tf = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.25, 0.25, 0.25])]
            )

トリミングは次のコードで実現できます。

def rand_crop(imgs, masks, h, w):
    """随机裁剪img与seg"""
    rect = torchvision.transforms.RandomCrop.get_params(imgs, (h, w))
    imgs = torchvision.transforms.functional.crop(imgs, *rect)
    masks = torchvision.transforms.functional.crop(masks, *rect)
    return imgs, masks

ただし、上記のコードの欠点は、このプロジェクトのファイルが npy ファイルであることです。numpy ファイルは、np.load で読み込んだ後、Image.formarray(np) または torch.tensor(np) で変換できますが、データは変換されています (-1 から 1)。直接変換プロセスの PIL テンソルは認識できないため、処理する必要があります。

したがって、最良の解決策は、np 独自の方法を使用してデータ拡張を実現することだと思われます。

  •         np.flip はランダムな反転を実装します (Fate は疑似サイコロです)。
def horiz_flip(imgs, segs, dice):
    Fate = randint(1, 100)
    if dice>=Fate:
        imgs = np.flip(imgs, 1) # 水平翻转
        segs = np.flip(segs, 1)
        # res2 = np.flip(img, 0)  # 垂直翻转
        # res3 = np.flip(img, -1) # 水平垂直翻转
        return imgs, segs
    else: return imgs, segs
  •         skimage.util に基づいてランダム ノイズを追加します。
import skimage

def add_noise(img):
    Fate = randint(1,100)
    if Fate <= 40:
        return img
    elif Fate<=70:
        "高斯噪声"
        img = skimage.util.random_noise(img, mode='gaussian', var=0.01)
        return img
    else:
        "椒盐噪声"
        img = skimage.util.random_noise(img, mode='s&p')
        return img
  • np.lib.pad に基づくランダムなトリミング:
    def random_crop(image, seg, crop_shape, padding=None):
        oshape = np.shape(image)
    
        if padding:
            oshape = (oshape[0] + 2 * padding, oshape[1] + 2 * padding)
            npad = ((padding, padding), (padding, padding),(0, 0))
            npad_seg = ((padding, padding), (padding, padding))
            print(oshape)
            print(npad)
            image_pad = np.lib.pad(image, pad_width=npad, mode='constant', constant_values=0)
            seg_pad = np.lib.pad(seg, pad_width=npad_seg, mode='constant', constant_values=0)
    
            nh = random.randint(0, oshape[0] - crop_shape[0])
            nw = random.randint(0, oshape[1] - crop_shape[1])
    
            image_crop = image_pad[nh:nh + crop_shape[0], nw:nw + crop_shape[1]]
            seg_crop = seg_pad[nh:nh + crop_shape[0], nw:nw + crop_shape[1]]
            return image_crop, seg_crop
        else:
            print("WARNING!!! nothing to do!!!")
            return image
    
    plt.figure(figsize=(5,5))
    img1 = np.load(img[1145])[:,:,:]
    seg1 = np.load(mask[1145])[:,:]
    plt.subplot(2,2,1)
    plt.imshow(img1, cmap='gray')
    plt.subplot(2,2,2)
    plt.imshow(seg1, cmap='gray')
    
    img1, seg1 = random_crop(img1, seg1, [224, 224], 16)
    plt.subplot(2,2,3)
    plt.imshow(img1, cmap='gray')
    plt.subplot(2,2,4)
    plt.imshow(seg1, cmap='gray')
    plt.tight_layout()
    plt.show()
  • ヒント: トレーニング モデルでは 3 チャネルを使用する必要があるため、上記の操作では 3 チャネル (RGB) 画像をトリミングできるはずです。imshow を使用すると問題が発生する可能性があります。別の記事を参照してください。
    noisy = np.clip(noisy, 0.0, 1.0)
    044fa1c4f1cf4002b5526567dc081f56.png

 

モデルの特定の効果によっては、ノイズの使用の効果が MRI 画像に良くない場合があります。

この時点で、画像の前処理と画像拡張が完了します。

補充する

  • 変換操作では、この操作により画像の空間情報が破壊されることがわかります。衛星画像、航空画像、医療画像などの画像の元の空間構造を破壊したくないため、画像を回転するときは、 90 度の倍数で回転させるのが最適です。
  • 非剛体変換は、医療画像の問題におけるデータを増強するのに役立ちます。次の非剛体変換クラスは主にアルバムで提供されます: ElasticTransform(弹性变换)GridDistortion(网格畸变) および OpticalDistortion(光学畸变)
  • albumentations ライブラリのメソッドを使用すると、非常に簡単にデータ拡張を実現できます。コードは下図に示すように、ランダムなトリミング (100% の確率)、ランダムな非破壊変換 (50% のランダムな垂直反転、50% のランダムな回転) を統合しています。 90度ごと)、80%確率的ランダム非剛体変換(弾性変換、グリッド歪み、光学歪みの確率比は1:1:2)、ランダム非空間変換(コントラストバランスの確率50%、50%)明るさとコントラストがランダムに変化する確率 (%))。上記skimageパッケージでノイズ追加も追加されました。
  • メソッドは img を返します。img["image"] は画像、img["mask"] はマーカーです。
  • from albumentations import *
    
    def augmentation(img, seg):
        img = Compose([
        # 随机裁剪
        RandomSizedCrop(min_max_height=(224, 224), height=224, width=224, interpolation=cv2.INTER_NEAREST, p=1),
    
        # 非破坏性转换
        VerticalFlip(p=0.5), # 随机垂直翻转
        RandomRotate90(p=0.5), # 随机旋转90度
        # 非刚体转换
        OneOf([
            ElasticTransform(p=0.5, interpolation=cv2.INTER_NEAREST), # 弹性变换
            GridDistortion(p=0.5, interpolation=cv2.INTER_NEAREST), # 网格畸变
            OpticalDistortion(p=1, distort_limit=2, shift_limit=0.5, interpolation=cv2.INTER_NEAREST) # 光学畸变
            ], p=0.8),
        # 非空间性转换
        RandomBrightnessContrast(p=0.5), # 随机改变亮度对比度
        ])(image=img, mask=seg)
        return img
    
    plt.figure(figsize=(5,5))
    img1 = np.load(img[1145])[:,:,:]
    seg1 = np.load(mask[1145])[:,:]
    plt.subplot(2,2,1)
    plt.imshow(img1)
    plt.subplot(2,2,2)
    plt.imshow(seg1, cmap='gray')
    
    img1 = augmentation(img1, seg1)
    plt.subplot(2,2,3)
    plt.imshow(img1["image"])
    plt.subplot(2,2,4)
    plt.imshow(img1["mask"], cmap='gray')
    plt.tight_layout()
    plt.show()

    3f0ae2ad0c3f4628acfe11036e0c7649.png

     

 

おすすめ

転載: blog.csdn.net/m0_59056870/article/details/126119271