ValueError : cannot reshape array of size 9556497 into shape (150,150,3) Keras .Net
Есть сверточная нейросеть. Первый слой такой
model.Add(new Conv2D(input_shape: new Shape(150, 150, 3), filters: 32, kernel_size: (3, 3).ToTuple()));
При загрузке картинок таким способом проблем не возникает
var datagen = new ImageDataGenerator(rescale: 1.0f / 255);
var testGenerator = datagen.FlowFromDirectory(@"Путь к папке с картинками",
target_size: (150, 150).ToTuple(),
batch_size: 16,
class_mode: "binary");
Но я хочу прогонять по 1 картинке. Для этого использую
var img = ImageUtil.LoadImg(@"Путь к картинке");
NDarray x = ImageUtil.ImageToArray(img);
x = x.reshape(16,150,150,3);
И получаю исключение ValueError : cannot reshape array of size 9556497 into shape (16,150,150,3)".
Пытался по разному настроить reshape, но нейросеть всегда выдает результат "1." либо исключение с размером. Как преобразовать картинку, также как сделал это datagen.FlowFromDirectory?
UPD1: Понимаю, что невозможно решейпнуть в нужную мне матрицу. Тогда подскажите как мне преобразовать изображения к нужному входному шейпу?
Примечание Если я делаю шейп из 3х измерений, то нейросеть ругается почему всего 3, а не 4 входных значения, почему?
Ответы (2 шт):
На C# должно быть аналогично тому, как это делается на Python, вот я попробовал в Google Colab:
from keras.preprocessing import image
img = image.load_img("/usr/local/share/jupyter/kernels/ir/logo-64x64.png");
img = image.img_to_array(img.resize((150,150)))
print(img.shape)
Вывод:
(150, 150, 3)
Т.е. получилась картинка размером 150x150, 3 цвета (изначальная картинка тут была 64x64, как видно из названия файла). Наверняка в C# у img тоже есть метод resize.
И ещё раз повторю тезисы из комментариев: не нужно путать resize и reshape.
resizeменяет размеры картинки (высоту и ширину), при этом остальные параметры картинки не меняются. Количество байтов данных картинки при этом, естественно, изменяется пропорционально изменению размеров сторон картинки.reshapeменяет размеры многомерного массива под нужный вам образец, но при этом общее число байт данных в массиве остаётся неизменным. Эта функция нужна для того, чтобы, например, из 64 байт данных вытянутых "линеечкой" сделать матрицу 8x8. Или наоборот. Для изменения размеров картинки (с выкидыванием лишних пикселов или "достраиванием" недостающих) эта функция никак не подходит.
Помогло следующее
var img = ImageUtil.LoadImg(@"Путь к фото",
target_size: new Keras.Shape(150,150,3)); // Здесь устанавливаем новый размер картинки т.е. 150 на 150 пикселей и 3 канала RGB
NDarray x = ImageUtil.ImageToArray(img); // Загружаем в массив
//Решейпим
// 1е значение, количество примеров т.е. = 1
// 2, 3 значение шейпа который мы указали ранее, т.е. высота/ширина или наоборот
// 4 последние значение шейпа, т.е. количество каналов
// + преобразование во float и деление на 255, что делалось в ImageDataGenerator в параметре rescale
x = x.reshape(1, x.shape[0], x.shape[1], x.shape[2]).astype(np.float32) / 255f;