Генератор данных Pytorch для извлечения 2D-изображений из множества 3D-кубов

#python #computer-vision #pytorch #data-generation

Вопрос:

Я изо всех сил пытаюсь создать генератор данных в PyTorch для извлечения 2D-изображений из множества 3D-кубов, сохраненных в .dat формате

Существует в общей сложности 200 3D-кубики, каждый из которых имеет определенную 128*128*128 форму. Теперь я хочу извлечь 2D-изображения из всех этих кубов по длине и ширине.

Например, a является ли куб размером 128*128*128

Поэтому я хочу извлечь все 2D-изображения по длине, т. Е., [:, i, :] что даст мне 128 2D-изображений по длине, и аналогично я хочу извлечь по ширине [:, :, i] , т. Е., что даст мне 128 2D-изображений по ширине. Поэтому я получаю в общей сложности 256 2D-изображений из 1 3D-куба, и я хочу повторить весь этот процесс для всех 200 кубов, предоставив мне 51200 2D-изображений.

До сих пор я пробовал очень простую реализацию, которая работает нормально, но для запуска требуется примерно 10 минут. Я хочу, чтобы вы, ребята, помогли мне создать более оптимальную реализацию с учетом сложности времени и пространства. Прямо сейчас мой текущий подход имеет временную сложность O(n2), можем ли мы продолжить его, чтобы уменьшить временную сложность

Я предоставляю ниже текущую реализацию

 from os.path import join as pjoin
import torch
import numpy as np
import os
from tqdm import tqdm
from torch.utils import data


class DataGenerator(data.Dataset):

    def __init__(self, is_transform=True, augmentations=None):

        self.is_transform = is_transform
        self.augmentations = augmentations
        self.dim = (128, 128, 128)

        seismicSections = [] #Input
        faultSections = [] #Ground Truth
        for fileName in tqdm(os.listdir(pjoin('train', 'seis')), total = len(os.listdir(pjoin('train', 'seis')))):
            unrolledVolSeismic = np.fromfile(pjoin('train', 'seis', fileName), dtype = np.single) #dat file contains unrolled cube, we need to reshape it
            reshapedVolSeismic = np.transpose(unrolledVolSeismic.reshape(self.dim)) #need to transpose the axis to get height axis at axis = 0, while length (axis = 1), and width(axis = 2)

            unrolledVolFault = np.fromfile(pjoin('train', 'fault', fileName),dtype=np.single)
            reshapedVolFault = np.transpose(unrolledVolFault.reshape(self.dim))

            for idx in range(reshapedVolSeismic.shape[2]):
                seismicSections.append(reshapedVolSeismic[:, :, idx])
                faultSections.append(reshapedVolFault[:, :, idx])

            for idx in range(reshapedVolSeismic.shape[1]):
                seismicSections.append(reshapedVolSeismic[:, idx, :])
                faultSections.append(reshapedVolFault[:, idx, :])

        self.seismicSections = seismicSections
        self.faultSections = faultSections

    def __len__(self):
        return len(self.seismicSections)

    def __getitem__(self, index):

        X = self.seismicSections[index]
        Y = self.faultSections[index]

        return X, Y
 

Пожалуйста, Помогите!!!

Ответ №1:

почему бы не сохранить только 3D-данные в mem и не позволить __getitem__ методу «нарезать» их на лету?

 class CachedVolumeDataset(Dataset):
  def __init__(self, ...):
    super(...)
    self._volumes_x = # a list of 200 128x128x128 volumes
    self._volumes_y = # a list of 200 128x128x128 volumes

  def __len__(self):
    return len(self._volumes_x) * (128   128)

  def __getitem__(self, index):
    # extract volume index from general index:
    vidx = index // (128   128)
    # extract slice index
    sidx = index % (128   128)
    if sidx < 128:
      # first dim
      x = self._volumes_x[vidx][:, :, sidx]
      y = self._volumes_y[vidx][:, :, sidx]
    else:
      sidx -= 128
      # second dim
      x = self._volumes_x[vidx][:, sidx, :]
      y = self._volumes_y[vidx][:, sidx, :]
    return torch.squeeze(x), torch.squeeze(y)