对ML和tensorflow来说很新鲜!
我用http://cloud.annotations.ai创建了一个对象检测模型,允许训练和转换不同格式的模型,tfjs (model_web)也是如此。该网站还提供了在浏览器中运行模型的样板(react )。就像你做的一样--可能是相同的代码,没有花足够的时间。
所以我让这个模型在浏览器中运行,给出对照片中物体的预测,考虑到我给出的例子数量和预测分数(0.89),结果非常好。给定的包围盒也很好。
但是,不幸的是,我没有“一段视频”来分析浏览器中的一帧一帧,我有很多视频。因此,我决定切换到node.js,按原样移植代码。你猜怎么着?TF.js依赖于DOM和浏览器组件,几乎没有使用Node的示例。所以没什么大不了的,只是花了一个早上找出所有缺失的部分。最后,我能够在分割成帧的视频上以相当快的速度运行我的模型--尽管在我已经使用tfjs节点时有了"Hello,使用tfjs节点来获得速度“的横幅,但是结果似乎很奇怪。将同一张图片与相同的model_web文件夹进行比较,得到相同的预测,但得分较低(0.80而不是0.89)和不同的边界框,对象根本没有居中。
(TL;DR)
是否有不同的库实现(tfjs和tfjs -节点),以不同的方式使用同一模型?我认为这不可能是输入问题,因为经过长时间的搜索和斗争,我想出了两种方法将图像交给Node中的tf.browser.getPixel (我仍然想知道为什么要在tfjs内使用“浏览器”方法)。有人比较过吗?
所以..。这是我使用的代码,供您参考:
model_web正在加载tf.loadGraphModel("file://path/to/model_web/model.json");
转换JPG并使其与tf.browser.getPixel()一起工作的两种不同方法
const inkjet = require('inkjet');
const {createCanvas, loadImage} = require('canvas');
const decodeJPGInkjet = (file) => {
return new Promise((rs, rj) => {
fs.readFile(file).then((buffer) => {
inkjet.decode(buffer, (err, decoded) => {
if (err) {
rj(err);
} else {
rs(decoded);
}
});
});
});
};
const decodeJPGCanvas = (file) => {
return loadImage(file).then((image) => {
const canvas = createCanvas(image.width, image.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0, image.width, image.height);
const data = ctx.getImageData(0, 0, image.width, image.height);
return {data: new Uint8Array(data.data), width: data.width, height: data.height};
});
};
这就是使用加载模型进行预测的代码--在https://github.com/cloud-annotations/javascript-sdk/blob/master/src/index.js中找到的用于节点和浏览器的相同代码--在节点上不起作用,我用require("@tensorflow/tfjs-node");
更改了require("@tensorflow/tfjs");
,用fs.read
替换了fetch
const runObjectDetectionPrediction = async (graph, labels, input) => {
const batched = tf.tidy(() => {
const img = tf.browser.fromPixels(input);
// Reshape to a single-element batch so we can pass it to executeAsync.
return img.expandDims(0);
});
const height = batched.shape[1];
const width = batched.shape[2];
const result = await graph.executeAsync(batched);
const scores = result[0].dataSync();
const boxes = result[1].dataSync();
// clean the webgl tensors
batched.dispose();
tf.dispose(result);
const [maxScores, classes] = calculateMaxScores(
scores,
result[0].shape[1],
result[0].shape[2]
);
const prevBackend = tf.getBackend();
// run post process in cpu
tf.setBackend("cpu");
const indexTensor = tf.tidy(() => {
const boxes2 = tf.tensor2d(boxes, [result[1].shape[1], result[1].shape[3]]);
return tf.image.nonMaxSuppression(
boxes2,
maxScores,
20, // maxNumBoxes
0.5, // iou_threshold
0.5 // score_threshold
);
});
const indexes = indexTensor.dataSync();
indexTensor.dispose();
// restore previous backend
tf.setBackend(prevBackend);
return buildDetectedObjects(
width,
height,
boxes,
maxScores,
indexes,
classes,
labels
);
};
发布于 2020-02-19 05:01:57
对不同使用相同模型的库(tfjs和tfjs-节点)执行不同的实现。
如果在浏览器和nodejs中都部署了相同的模型,则预测将是相同的。
如果预测值不同,则可能与用于预测的张量有关。从图像到张量的处理可能不同,从而导致不同的张量用于预测,从而导致输出不同。
-我想出了两种方法在节点中将图像交给tf.browser.getPixel (我仍然想知道为什么要在tfjs-节点内使用“浏览器”方法)。
画布包使用系统图形创建可以由nodejs使用的浏览器(如画布环境)。这使得使用tf.browser命名空间成为可能,特别是在处理图像转换时。但是,仍然可以直接使用nodejs缓冲区来创建张量。
https://stackoverflow.com/questions/60221268
复制