使用 jpeg_js 解码图像

issue decoding an image using jpeg_js

我的环境:

ubuntu 18.04
rtx 2080ti
cuda 10.1
node v12.16.3 
tfjs 1.7.4

saved_model 是 efficientdet-d0,
推理步骤在 inference step

为了用js解析图片数据,我把img.png转成了img.jpg,saved_model和saved_model result
的结果是一样的 将 saved_model 转换为 tfjs_graph_model 的命令是

tensorflowjs_converter --input_format=tf_saved_model /tmp/saved_model ~/DATA/http_models/specDetection/

我的测试代码是

var tfc = require("@tensorflow/tfjs-converter");
var tf  = require("@tensorflow/tfjs-core");
var jpeg_js = require("jpeg-js");
var fs = require("fs");


async function loadModel() {
    var modelUrl = "http://localhost:8000/model.json"
    var model = await tfc.loadGraphModel(modelUrl);
    return model;
}

async function detect() {
    var model = await loadModel();
    var img = fs.readFileSync("~/SRC/automl_test/efficientdet/img.jpg");
    const input = jpeg_js.decode(img,{useTArray:true,formatAsRGBA:false});

    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 result = await model.executeAsync({'image_arrays:0':batched},['detections:0']);
    console.log(result);
}

detect();

当用我的测试代码检测 img.jpg 中的对象时,没有检测到任何东西---结果的大小是 0
我该怎么做才能解决这个问题?
感谢任何线索

编辑:
代码 1:

 var img = fs.readFileSync("~/DATA/http_models/specDetection/test.jpg");

    var dataJpegJs = jpeg_js.decode(img,{useTArray:true,formatAsRGBA:false})
    var batched = tf.browser.fromPixels({data:dataJpegJs.data, width: dataJpegJs.width, height:dataJpegJs.height},3);
    batched = batched.slice([0,0,0],[-1,-1,3]);
    var result = await model.executeAsync({'image_arrays:0':batched.expandDims(0)},['detections:0']);
    result = tf.slice(result,[0,0,1],[1,-1,4]);

代码 2:

var img = fs.readFileSync("~/DATA/http_models/specDetection/test.jpg");

    var dataJpegJs = jpeg_js.decode(img,{useTArray:true,formatAsRGBA:true})
    var batched = tf.browser.fromPixels({data:dataJpegJs.data, width: dataJpegJs.width, height:dataJpegJs.height},4);
    batched = batched.slice([0,0,0],[-1,-1,3]);
    var result = await model.executeAsync({'image_arrays:0':batched.expandDims(0)},['detections:0']);
    result = tf.slice(result,[0,0,1],[1,-1,4]);

代码 1 得到了错误的结果,代码 2 得到了正确的结果。 代码 2 使用 formatAsRGBA:true 解码 jpg,并在 tf.browser.fromPixels 中设置 numChannels=4。 jpeg-js 必须将 jpg 解码为 RGBA 才能正常工作。 我认为这是 jpeg 的一个错误-js.or 我对 jpg 编码不熟悉?

张量生成不好。 fromPixels 主要用于从 htmlImageElement 中获取张量。打印张量的摘要并将其与为 python 生成的张量进行比较就足以说​​明这一点。

jpeg-js 有问题吗?

首先我们需要知道imageData是如何工作的。图像数据像素是 4 个数值 R、G、B、A。当使用 jpeg_js.decode 解码的数据作为具有 3 个通道(formatAsRGBA:false)的 tf.browser.fromPixel 的参数时,它被认为是一个图像数据。让我们考虑数据 [a, b, c, d, e, f] = jpeg_js.decode("path", {formatAsRGBA:false}) 和从中创建的张量 t t = tf.browser.fromPixels({data, width: 2, height: 1})。它是如何解释的? tf.browser.fromPixels,将创建一个高度为 1 且宽度为 2 的 ImageDate。因此,imageData 的大小为 1 * 2 * 4(而不是 1 * 2 * 3)并将其所有值设置为 0 .然后它将解码后的数据复制到imageData中。所以imageData = [a, b, c, d, e, f, 0, 0]。 结果,切片 (t.slice([0, 0, 0], [-1, -1, 3]) 将是 [a, b, c, e, f, 0]jpeg_jstf.browser.fromPixels 都不是问题。这就是 imageData 的工作原理

可以做什么?

  • 保持解码图像的alpha通道formatAsRGBA:true
  • 不使用tf.browser.fromPixel,而是直接使用tf.tensor创建张量
const img = tf.tensor(input.data, [input.height, input.width, 3])

另一种选择是使用tensorflow-nodetf.node.decodeImage 可以从张量解码图像。

const img = fs.readFileSync("path/of/image");
const tensor = tf.node.decodeImage(img)
// use the tensor for prediction

不同于jpeg-js仅适用于jpeg编码格式的图像,它可以解码更广泛的图像