tensorflowjs: показать предсказанный массив в виде изображения

#javascript #html #promise #html5-canvas #tensorflow.js

#javascript #HTML #обещание #html5-холст #tensorflow.js

Вопрос:

Как и в следующем js-коде, я загружаю модель как обещание: tf.loadLayersModel('../tfjs-models/hadwritten-digits/model.json')

Теперь я использую model.predict, который вернет тензор формы (1, 128, 128, 1), то есть одно изображение в оттенках серого. Сейчас у меня много проблем с обещаниями и ожиданиями. У меня есть холст с известным идентификатором в index.html , я хочу поместить изображение в. Сейчас нужна помощь.

 async function generate() {

    let input =  document.getElementById("slider").value
    console.log(`Random Noisy Input Mean is ${input}`)

    tf.loadLayersModel('../tfjs-models/hadwritten-digits/model.json').then(async (model) => {

    tensor = tf.tensor([randomnormal(100, input, 0.5)]);
    result = await model.predict(tensor).array()
    document.getElementById("myCanvas").getContext("3d").putImageData(
        new ImageData(Uint8ClampedArray.from(result), 1, 1), 1, 1);
    });
}
 

Ошибка

 model.js:39 Uncaught (in promise) TypeError: Cannot read property 'putImageData' of null
    at model.js:39
 

Я очень новичок в javascript, python является моим основным языком.
Мне нужно было создать интерфейс для моей модели GAN. И я чувствовал себя более предприимчивым, используя tfjs, чем предоставляя результаты из flask или django. Так что любая помощь будет для меня очень важна 🙂

Решаемая

 async function generate() {

    let input =  document.getElementById("slider").value
    console.log(`Random Noisy Input Mean is ${input}`)

    inputtensor = tf.tensor([randomnormal(100, input, 0.5)]);
    outputtensor = await model.predict(inputtensor)

    result = outputtensor.mul([1, 1, 1, 1]).dataSync()
    for(var i=0;i<result.length;i  ){
        result[i]=result[i]*255.0   128.0;
    }
    document.getElementById("myCanvas").getContext("2d").putImageData(
        new ImageData(Uint8ClampedArray.from(result), 128, 128), 1, 1);

}

var model;

tf.loadLayersModel('../tfjs-models/hadwritten-digits/model.json').then(async (resolve) => {
    model=resolve
});
 

Ответ №1:

В коде необходимо изменить несколько вещей

  • 3d На данный момент контекста нет, есть 2d контекст.
  • Кроме того, Uint8ClampedArray ожидает сглаживания массива. Поэтому вместо использования array (соответственно arraySync ), оно должно быть data (соответственно dataSync ).
  • ImageData ожидает ширину и высоту изображения. Маловероятно, что ширина и высота изображения равны 1 пикселю каждый. Поэтому может потребоваться изменить параметры, заданные для ImageData

короткий пример

 tensor = tf.ones([5, 5, 4]);
new ImageData(Uint8ClampedArray.from(tensor.dataSync()), 5, 5);
 

Комментарии:

1. Это работает, мне просто нужен еще один бит, мой массив изображений имеет оттенки серого. Итак, как поместить изображение, если tensor = tf.ones([5, 5, 1])

2. Вам нужно будет увеличить последнее измерение (канал) до 3. Может помочь следующее: tf.ones([5, 5, 1]).mul([1, 1, 1]) или tf.ones([5, 5, 1]).mul(new Array(3).fill(1))

3. .mul([1, 1, 1, 1]) ты имел в виду? да, наконец-то это работает. Спасибо.

4. Да, плюс прозрачность. Это должно быть 4 вместо 3