Использование пользовательских изображений для Tensorflow.js в node.js или браузере - PullRequest
0 голосов
/ 22 декабря 2018

Пример Tensorflow.js cnn хорош, и я решил потренироваться со своими пользовательскими изображениями персонажей (локальные изображения, подобные этому imgur. Также доступны как элементы img браузера).Однако я не могу повторить тест, потому что код примеров использует предварительно обработанные изображения данных.

Я скопировал приведенный здесь пример (https://github.com/tensorflow/tfjs-examples/blob/master/mnist-node/README.md) и добавил требуемые пакеты js узла. Пример успешно выполнен.Но я понял, что не могу изменить данные этого примера, потому что он загружает предварительно обработанные данные, как показано ниже.

const BASE_URL = 'https://storage.googleapis.com/cvdf-datasets/mnist/';
const TRAIN_IMAGES_FILE = 'train-images-idx3-ubyte';
const TRAIN_LABELS_FILE = 'train-labels-idx1-ubyte';
const TEST_IMAGES_FILE = 't10k-images-idx3-ubyte';
const TEST_LABELS_FILE = 't10k-labels-idx1-ubyte';

Я сделал изображения того же формата с помощью MNIST (28 * 28), поэтому я подумал, чтоЯ мог просто изменить поезд и проверить данные, но потерпел неудачу, потому что я не знаю, что такое idx3-ubyte формат. URL data.js файлов здесь .

Как я могу сгенерировать такой же ubyte файлов? Или Как использовать локальные изображения или элемент img напрямую?

update Я проверил часть чтения файла data.js и смог создать тот же формат файла. Он также имеет значения заголовка.

 
async function loadImages(filename) {
  const buffer = await fetchOnceAndSaveToDiskWithBuffer(filename);

  const headerBytes = IMAGE_HEADER_BYTES;
  const recordBytes = IMAGE_HEIGHT * IMAGE_WIDTH;

  const headerValues = loadHeaderValues(buffer, headerBytes);
  assert.equal(headerValues[0], IMAGE_HEADER_MAGIC_NUM);
  assert.equal(headerValues[2], IMAGE_HEIGHT);
  assert.equal(headerValues[3], IMAGE_WIDTH);

  const images = [];
  let index = headerBytes;
  while (index < buffer.byteLength) {
    const array = new Float32Array(recordBytes);
    for (let i = 0; i < recordBytes; i++) {
      // Normalize the pixel values into the 0-1 interval, from
      // the original 0-255 interval.
      array[i] = buffer.readUInt8(index++) / 255;
    }
    images.push(array);
  }

  assert.equal(images.length, headerValues[1]);
  return images;
}

async function loadLabels(filename) {
  const buffer = await fetchOnceAndSaveToDiskWithBuffer(filename);

  const headerBytes = LABEL_HEADER_BYTES;
  const recordBytes = LABEL_RECORD_BYTE;

  const headerValues = loadHeaderValues(buffer, headerBytes);
  assert.equal(headerValues[0], LABEL_HEADER_MAGIC_NUM);

  const labels = [];
  let index = headerBytes;
  while (index < buffer.byteLength) {
    const array = new Int32Array(recordBytes);
    for (let i = 0; i < recordBytes; i++) {
      array[i] = buffer.readUInt8(index++);
    }
    labels.push(array);
  }

  assert.equal(labels.length, headerValues[1]);
  return labels;
}

 
 getData_(isTrainingData) {
    let imagesIndex;
    let labelsIndex;
    if (isTrainingData) {
      imagesIndex = 0;
      labelsIndex = 1;
    } else {
      imagesIndex = 2;
      labelsIndex = 3;
    }
    const size = this.dataset[imagesIndex].length;
    tf.util.assert(
        this.dataset[labelsIndex].length === size,
        `Mismatch in the number of images (${size}) and ` +
            `the number of labels (${this.dataset[labelsIndex].length})`);

    // Only create one big array to hold batch of images.
    const imagesShape = [size, IMAGE_HEIGHT, IMAGE_WIDTH, 1];
    const images = new Float32Array(tf.util.sizeFromShape(imagesShape));
    const labels = new Int32Array(tf.util.sizeFromShape([size, 1]));

    let imageOffset = 0;
    let labelOffset = 0;
    for (let i = 0; i < size; ++i) {
      images.set(this.dataset[imagesIndex][i], imageOffset);
      labels.set(this.dataset[labelsIndex][i], labelOffset);
      imageOffset += IMAGE_FLAT_SIZE;
      labelOffset += 1;
    }

    return {
      images: tf.tensor4d(images, imagesShape),
      labels: tf.oneHot(tf.tensor1d(labels, 'int32'), LABEL_FLAT_SIZE).toFloat()
    };
  }
}

Ниже приведен код генератора.

const {createCanvas, loadImage} = require('canvas');
const tf = require('@tensorflow/tfjs');
require('@tensorflow/tfjs-node');

const fs = require('fs');

const util = require('util');

// const writeFile = util.promisify(fs.writeFile);
// const readFile = util.promisify(fs.readFile);

(async()=>{

      const canvas = createCanvas(28,28);
      const ctx = canvas.getContext('2d');

      const ch1 = await loadImage('./u.png');
      const ch2 = await loadImage('./q.png');
      const ch3 = await loadImage('./r.png');
      const ch4 = await loadImage('./c.png');
      const ch5 = await loadImage('./z.png');

      console.log(ch1);
      
      ctx.drawImage(ch1, 0, 0);
      const ch1Data = tf.fromPixels(canvas, 1);
      ctx.drawImage(ch2, 0, 0);
      const ch2Data = tf.fromPixels(canvas, 1);
      ctx.drawImage(ch3, 0, 0);
      const ch3Data = tf.fromPixels(canvas, 1);
      ctx.drawImage(ch4, 0, 0);
      const ch4Data = tf.fromPixels(canvas, 1);
      ctx.drawImage(ch5, 0, 0);
      const ch5Data = tf.fromPixels(canvas, 1);

      // console.log(await ch1Data.data());
      const b1 = Buffer.from(await ch1Data.data());
      const b2 = Buffer.from(await ch2Data.data());
      const b3 = Buffer.from(await ch3Data.data());
      const b4 = Buffer.from(await ch4Data.data());
      const b5 = Buffer.from(await ch5Data.data());

      const buffers = [b1,b2,b3,b4,b5];

      const labels = [0,1,3,2,4,0,1,2,1,0,3,0,2,3,4,0,];

      const Images = [];

      const size = labels.length;
      for(var i = 0; i < size;i++){
            Images.push(buffers[labels[i]]);

      }
      const imageHeaderBytes = 16;
      const imageRecordBytes = 28 * 28;
      const labelHeaderBytes = 8;
      const labelRecordBytes = 1;
      let imageBuffer = Buffer.alloc(imageHeaderBytes + size * imageRecordBytes);
      let labelBuffer = Buffer.alloc(labelHeaderBytes + size * labelRecordBytes);
      
      const imageHeaderValues = [2051, size, 28, 28];
      const labelHeaderValues = [2049, size];
      for (let i = 0; i < 4; i++) {
            // Header data is stored in-order (aka big-endian)
            imageBuffer.writeUInt32BE(imageHeaderValues[i], i * 4);
      }
      for (let i = 0; i < 2; i++) {
            // Header data is stored in-order (aka big-endian)
            labelBuffer.writeUInt32BE(labelHeaderValues[i], i * 4);
      }
      let imageindex = imageHeaderBytes;
      let labelindex = labelHeaderBytes;
      for(let i = 0; i < size; i++){
            // imageBuffer = Buffer.concat([imageBuffer, Images[i]]);
            // labelBuffer= Buffer.concat([labelBuffer, Buffer.from([labels[i]])]);
            // labelBuffer= Buffer.concat([labelBuffer, Buffer.from([labels[i]])]);
            const image = Images[i];
            let index = 0;
            while(index < image.byteLength){
                  imageBuffer.writeUInt8(image[index], imageindex);
                  index++;
                  imageindex++;
            }
            labelBuffer.writeUInt8(labels[i], labelindex++);
      }

      fs.writeFileSync('./testGeneratedImageBuffer', imageBuffer);
      fs.writeFileSync('./testGeneratedLabelBuffer', labelBuffer);


})();

1 Ответ

0 голосов
/ 22 декабря 2018

«ubyte» означает «неподписанный байт».Это относится к 8-разрядному целому числу без знака.Каждый из двух файлов images -ubyte * содержит ряд 8-разрядных целых чисел без знака.Каждое целое число представляет собой пиксель в изображении MNIST и имеет значение> = 0 и <= 255. </p>

Вот как изображения представляются на уровне пикселей.Теперь давайте посмотрим на уровень целого изображения, состоящего из 28 строк и 28 столбцов.Для представления изображения требуется 28 * 28 = 784 таких целых числа.В файле они организованы таким образом, что первые 28 целых чисел соответствуют первой строке, следующие 28 целых чисел соответствуют второй строке и т. Д.

Все изображения в наборе данных представлены следующим образомway и их целые числа объединяются, чтобы сформировать содержимое файла image -ubyte.Почему есть два таких файла?Это связано с тем, что train-images-idx3-ubyte является обучающим набором данных, а t10k-images-idx3-ubyte является тестовым набором данных.

Два других файла ( метки -байт) являются метками для изображений MNIST.Как и image -убайтные файлы, они содержат uint8 (т. Е. 8-разрядные целые числа без знака).Но вместо значений 0-255 файлы меток имеют значения> = 0 и <= 9, поскольку в наборе данных MNIST всего 10 классов изображений. </p>

Надеюсь, это понятно.

...