Вопрос или проблема
Примечание: Я извлек кадр для всех видео и сохранил его в папке с тем же именем, что и видео
train_data, class, video —> Это папки
img –> это jpg файлы, так что у каждого класса много видео, я извлек изображение для каждого видео и сохранил его в папку с именем видео, откуда извлекаются кадры.
Структура моего набора данных выглядит примерно так;
Всего извлеченных изображений для каждого видео = 28
Всего классов = 101
Всего видео = 10619
Всего изображений = 301169
Длительность = 16
Шаг = 4
для каждого видео ==> сначала считывает первые 16 изображений, затем пропускает следующие 4 изображения и считывает с 5-го до 20-го, пропуская следующие четыре изображения, снова считывает с 9-го изображения до 24, а затем в конце до 28 для каждого видео.
Всего количество выборок будет 4 для каждого видео ==> [16, 20, 24, 28] (28 извлеченных кадров)
каждая выборка содержит 16 кадров с размером 112x112x3.
Общее количество выборок для всех классов = num_sample_for_each_video * общее количество видео = 4 * 10619 = 42142 (приблизительно, потому что выборка может быть 3 в некоторых видео)
Может кто-нибудь сказать, как я могу загрузить это в DataLoader в PyTorch?
формат данных выглядит примерно так;
[[img1_filename,img2_filename...,img16_filename],label1], [[img1_filename,img2_filename...,img16_filename],label2],...]
[[[16 изображений (0-16)], label1]], [[16 изображений (4,20)], label2], [[16 изображений (9,24)], label3], [[16 изображений (13,28)], label3]]
Я написал этот код,
X_train = []
y_train = []
for data in tqdm(data): # Цикл по каждой партии
# Загрузка изображения (X)
x = data[0]
y = data[1]
temp_data_list = []
for img in x:
try:
img = cv2.imread(img)
# примените любую предобработку здесь
# img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# img = self.preprocess_image(img)
temp_data_list.append(img)
except Exception as e:
print(e)
print('ошибка чтения файла: ', img)
# Читать метку (y)
# label = label_names[y]
# Добавить пример в массивы
X_train.append(temp_data_list)
y_train.append(y)
Поведение загрузки данных, которое вы описываете, похоже, не охватывается никакими классами Dataset
по умолчанию, поэтому вам придется создать пользовательский. Общая структура Dataset
в pytorch, которая может использоваться в DataLoader
, это класс, который наследует от Dataset
и имеет два метода, __len__
и __getitem__
для получения количества выборок и извлечения выборки из набора данных соответственно. Это будет выглядеть примерно так:
from pathlib import Path
from torch.utils.data import Dataset
class CustomDataset(Dataset):
def __init__(self, directory):
self.directory = directory
self.images = Path(self.directory).glob("**/*.jpg")
def __len__(self):
return len(self.images)
def __getitem__(self, index):
# реализуйте вашу пользовательскую логику, которая загружает и
# преобразует изображения по мере необходимости
pass
Вам придется определить логику, которую вы описали в методе __getitem__
(и, возможно, также строку, которая извлекает пути к изображениям, так как вы упоминаете, что несколько изображений объединяются в одну выборку). Как только вы определите всю необходимую логику в вашем пользовательском наборе данных, вы сможете использовать этот набор данных в DataLoader.
Ответ или решение
Чтобы загрузить кастомные данные в PyTorch DataLoader, вам необходимо создать собственный класс Dataset, который будет наследовать от PyTorch Dataset
и реализует методы __len__
и __getitem__
. Это позволит вам настроить загрузку данных в соответствии с вашими требованиями и структурой папок.
Шаг 1: Создание класса CustomDataset
В вашем случае, структура данных представляет собой изображения, извлеченные из видео, где каждая выборка содержит 16 изображений и соответствующую метку. Ниже представлен пример реализации этого класса:
import os
import cv2
import numpy as np
from pathlib import Path
import torch
from torch.utils.data import Dataset, DataLoader
class CustomDataset(Dataset):
def __init__(self, root_dir, transform=None):
self.root_dir = Path(root_dir)
self.transform = transform
self.data = []
self.labels = []
# Сбор данных и меток
for class_folder in os.listdir(self.root_dir):
class_path = self.root_dir / class_folder
if os.path.isdir(class_path): # Проверка, что это папка
for video in os.listdir(class_path):
video_path = class_path / video
if os.path.isdir(video_path): # Проверка, что это папка
frames = sorted(video_path.glob("*.jpg")) # Сортируем файлы для последовательности
# Генерация выборок
num_samples = max(0, len(frames) - 16) // 4 + 1
for i in range(num_samples):
start_index = i * 4
frame_indices = list(range(start_index, start_index + 16))
if frame_indices[-1] < len(frames): # Проверка выхода за границы
self.data.append([str(frames[idx]) for idx in frame_indices])
self.labels.append(class_folder) # Используем имя папки как метку
def __len__(self):
return len(self.data)
def __getitem__(self, index):
# Загрузка изображений
frame_paths = self.data[index]
images = []
for img_path in frame_paths:
img = cv2.imread(img_path)
if img is not None:
img = cv2.resize(img, (112, 112)) # Изменение размера
images.append(img)
else:
print(f'Ошибка загрузки изображения: {img_path}')
images = np.array(images) # Преобразуем в NumPy массив
label = self.labels[index]
if self.transform:
images = self.transform(images) # Применение трансформаций, если есть
return images, label
# Использование CustomDataset с DataLoader
root_dir = './train_data' # Укажите путь к вашему набору данных
dataset = CustomDataset(root_dir)
dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
# Пример итерации по DataLoader
for batch_images, batch_labels in dataloader:
print(batch_images.shape, batch_labels)
Шаг 2: Объяснение кода
-
Инициализация: В методе
__init__
происходит инициализация класса, где мы проходимся по папкам и формируем список изображений и меток. -
Длина набора данных: Метод
__len__
возвращает общее количество образцов данных, что необходимо для DataLoader. -
Получение данных: Метод
__getitem__
загружает изображения по заданному индексу и применяет, при необходимости, предобработку. Мы используем OpenCV для загрузки изображений и изменения их размера до 112×112. -
Создание DataLoader: Мы создаем экземпляр
DataLoader
, используя наш классCustomDataset
, указывая размер пакета и возможность перемешивания данных для эффективного обучения.
Шаг 3: Обработка ошибок
Убедитесь, что при загрузке изображений вы обрабатываете возможные ошибки, например, если файл отсутствует или файл оказал не изображением. В приведенном выше примере добавляется вывод сообщений об ошибках.
Заключение
Теперь у вас есть полноценное решение для загрузки вашего кастомного набора данных в PyTorch. Это позволит вам эффективно осуществлять обучение модели, используя сложные датасеты. Не забывайте экспериментировать с предварительной обработкой изображений и параметрами загрузки, чтобы повысить качество обучения вашей нейронной сети.