angular - 使用带有tensorflow JS的自定义视觉导出模型并输入图像

标签 angular tensorflow tensorflow.js tensorflowjs-converter microsoft-custom-vision

我是 tensorflow.js 和 tensorflow 的新手

上下文:我们使用自定义视觉训练了一个模型,以从图像中识别头发长度:短、中、长。该模型已导出,我们想在本地使用 tensorflow js。自定义视觉导出的文件是*.pb文件和labels.txt文件。

我使用了 tensorflowjs_converter python 脚本,这是我用来将卡住模型 *.pb 转换为 json 模型的命令:

tensorflowjs_converter --input_format=tf_frozen_model --output_node_names='model_outputs' --output_json OUTPUT_JSON C:\python\tf_models\hairlength\model.pb C:\python\tf_models\exports\

然后我将这个 model.json 和分片粘贴到我的 Angular 客户端的 Assets 文件夹中。然后我尝试加载模型并给他一张图像来获得预测,但我得到的只是超出范围的索引值,因为我只需要 0:长,1:中,2:短发长度。这是控制台的捕获 prediction list

这是我在客户端( typescript )中用于预测的类:

import * as tf from '@tensorflow/tfjs';

// import {HAIRLENGTH_LABELS} from './hairlength';
import { FrozenModel } from '@tensorflow/tfjs';

const MODEL = 'assets/models/hairlength/model.json';
const INPUT_NODE_NAME = 'model_outputs';
const OUTPUT_NODE_NAME = 'model_outputs';
const PREPROCESS_DIVISOR = tf.scalar(255 / 2);

export class MobileNetHairLength {

  private model: FrozenModel;
  private labels = ['long', 'mid', 'short'];

  constructor() {}

  async load(){
    this.model = await tf.loadGraphModel(MODEL);
  }

  dispose() {
    if (this.model) {
      this.model.dispose();
    }
  }

  /**
   * Infer through MobileNet. This does standard ImageNet pre-processing before
   * inferring through the model. This method returns named activations as well
   * as softmax logits.
   *
   * @param input un-preprocessed input Array.
   * @return The softmax logits.
   */
  predict(input) {
    const preprocessedInput = tf.div(
        tf.sub(input, PREPROCESS_DIVISOR),
        PREPROCESS_DIVISOR);
    const reshapedInput =
        preprocessedInput.reshape([1, ...preprocessedInput.shape]);
    // tslint:disable-next-line:no-unused-expression
    return this.model.execute({[INPUT_NODE_NAME]: reshapedInput}, OUTPUT_NODE_NAME);
  }

  getTopKClasses(logits, topK: number) {
    const predictions = tf.tidy(() => {
      return tf.softmax(logits);
    });

    const values = predictions.dataSync();
    predictions.dispose();

    let predictionList = [];
    for (let i = 0; i < values.length; i++) {
      predictionList.push({value: values[i], index: i});
    }
    predictionList = predictionList
                         .sort((a, b) => {
                           return b.value - a.value;
                         })
                         .slice(0, topK);

    console.log(predictionList);
    return predictionList.map(x => {
      return {label: this.labels[x.index], value: x.value};
    });
  }
}

这是调用上面那个的类,我只给 Canvas 元素:

import 'babel-polyfill';
import * as tf from '@tensorflow/tfjs';
import { MobileNetHairLength } from './mobilenet-hairlength';

export class PredictionHairLength {

  constructor() {}

  async predict(canvas) {
    const mobileNet = new MobileNetHairLength();
    await mobileNet.load();
    const pixels = tf.browser.fromPixels(canvas);

    console.log('Prediction');
    const result = mobileNet.predict(pixels);
    const topK = mobileNet.getTopKClasses(result, 3);

    topK.forEach(x => {
      console.log( `${x.value.toFixed(3)}: ${x.label}\n` );
    });

    mobileNet.dispose();
  }
}

我的问题是:

convert python 命令是否正确?

我是否遗漏了客户端中的某些内容以获取正确的索引?

感谢您的宝贵时间和答复

如果您需要更多信息,我很乐意提供给您

2019 年 3 月 10 日更新

我确实使用 npm 将 tensorflowjs 更新到 1.0.0

我看到 FrozenModel 现在已被弃用

导出我的自定义视觉模型会给我一个 model.pb 和 labels.txt 文件,如下所示: custom vision exports

我已经尝试将这些文件与 python 一起使用,一切正常...... 我现在想将此 model.pb 文件转换为 model.json 文件以与 tensorflowjs 一起使用,为此我需要使用 tensorflowjs_converter,问题是转换此保存模型的文件结构无效,请参阅:https://www.tensorflow.org/guide/saved_model#structure_of_a_savedmodel_directory

唯一可行的是,如果我在转换器中使用 frozen_model 格式并给出输出节点名称:loss... 像这样 tensorflowjs_converter --input_format=tf_frozen_model --output_node_names='loss' --output_json OUTPUT_JSON C:\python\tf_models\hairlength\model.pb C:\python\tf_models\exports\

这些是我在运行上述命令时得到的输出: output files 然后我加载模型,这是我使用导出的 json 模型加载和预测的代码(我使用了 predict() 并删除了输入和输出节点,就像你告诉我的那样):

import * as tf from '@tensorflow/tfjs';
import { GraphModel } from '@tensorflow/tfjs';

const MODEL = 'assets/models/hairlength/model.json';
// const INPUT_NODE_NAME = 'Placeholder';
// const OUTPUT_NODE_NAME = 'loss';
const PREPROCESS_DIVISOR = tf.scalar(255 / 2);

export class MobileNetHairLength {

  private model: GraphModel;
  private labels = ['long', 'mid', 'short'];

  constructor() {}

  async load() {
    this.model = await tf.loadGraphModel(MODEL);
  }

  dispose() {
    if (this.model) {
      this.model.dispose();
    }
  }

  /**
   * Infer through MobileNet. This does standard ImageNet pre-processing before
   * inferring through the model. This method returns named activations as well
   * as softmax logits.
   *
   * @param input un-preprocessed input Array.
   * @return The softmax logits.
   */
  predict(input: tf.Tensor<tf.Rank>) {
    const preprocessedInput = tf.div(
      tf.sub(input.asType('float32'), PREPROCESS_DIVISOR),
      PREPROCESS_DIVISOR);
    const reshapedInput =
      preprocessedInput.reshape([...preprocessedInput.shape]);
    return this.model.predict(reshapedInput);
  }

  getTopKClasses(logits, topK: number) {
    const predictions = tf.tidy(() => {
      return tf.softmax(logits);
    });

    const values = predictions.dataSync();
    predictions.dispose();

    let predictionList = [];
    for (let i = 0; i < values.length; i++) {
      predictionList.push({value: values[i], index: i});
    }
    predictionList = predictionList
                         .sort((a, b) => {
                           return b.value - a.value;
                         })
                         .slice(0, topK);

    console.log(predictionList);
    return predictionList.map(x => {
      return {label: this.labels[x.index], value: x.value};
    });
  }
}

调用类是这个:

import 'babel-polyfill';
import * as tf from '@tensorflow/tfjs';
import { MobileNetHairLength } from './mobilenet-hairlength';

export class PredictionHairLength {

  constructor() {}

  async predict(canvas) {
    // Convert to tensor
      const mobileNet = new MobileNetHairLength();
      await mobileNet.load();
      const imgTensor = tf.browser.fromPixels(canvas);
      console.log(imgTensor);
      // Init input with correct shape
      const input = tf.zeros([1, 224, 224, 3]);
      // Add img to input
      input[0] = imgTensor;

      console.log('Prediction');
      const result = mobileNet.predict(input);
      console.log(result);

      const topK = mobileNet.getTopKClasses(result, 3);

      topK.forEach(x => {
        console.log( `${x.value.toFixed(3)}: ${x.label}\n` );
      });

      mobileNet.dispose();
  }
}

然后发送从网络摄像头流中获取的 Canvas 元素会给我这个错误: js error

由于文件结构错误,我如何运行格式为“已保存模型”的转换器命令?

为什么会出现“无法编译片段着色器错误,无限:tf-core.esm 中未声明的标识符”?

感谢您的宝贵时间和答复

最佳答案

我认为这是您代码中的一个简单错误:const INPUT_NODE_NAME = 'model_outputs'; 可能应该是 'model_inputs' 或任何它实际是什么。在这里,您将输出设置为输入图像,然后在不预测任何内容的情况下读回它。

关于angular - 使用带有tensorflow JS的自定义视觉导出模型并输入图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55020267/

相关文章:

javascript - 在 Angular 应用程序中将 FirebaseAuth.onAuthStateChanged 调用放在哪里?

c# - 我如何将 gzip 用于我的 Angular 项目?

python - tensorflow.keras.preprocessing.text.Tokenizer.texts_to_sequences 的 Numpy 数组给出了奇怪的输出,list([2]) 而不是 [[2]]

Angular 5 Reactive Forms - 单选按钮组

html - 证明内容 : center does not work in IE11

tensorflow - Keras 后端中的逻辑 AND/OR

python-3.x - 将自己的图像转换为 MNIST 的图像

javascript - Tensorflow vs Tensorflow JS 浮点算术计算的不同结果

Tensorflow js VS Tensorflow Lite

javascript - 从 Tensorflow.js 文本毒性检测模型返回 'predictions'