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 шт):

Автор решения: CrazyElf

На 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. Или наоборот. Для изменения размеров картинки (с выкидыванием лишних пикселов или "достраиванием" недостающих) эта функция никак не подходит.
→ Ссылка
Автор решения: Hello war

Помогло следующее

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;
→ Ссылка