【问题标题】:Why am I getting strange triplication of video using Webcam and Tensorflow.js?为什么我使用 Webcam 和 Tensorflow.js 得到奇怪的三重视频?
【发布时间】:2019-01-21 03:15:15
【问题描述】:

我已经训练了一个 keras 模型,现在我想在网络上运行它。我认为这可能是尝试测试 Tensorflow.js 的好方法。我下载了 Tesnroflow.js “Webcam-transfer-learning”教程,然后对其进行了修改以获得我目前拥有的内容。工作中的 keras 模型在将图像尺寸减小到 48x48 后执行情感分类。现在在 keras 模型中,我拍摄网络摄像头的快照,复制它,然后绘制我的框和标签。我试图在 tf.js 中做同样的事情,所以我设置了一个画布,获取了对它的引用,并在转换为灰度后尝试在画布上绘图。

我看到一个奇怪的行为,它正确显示了灰度图像,但它显示了 3 次,并且不确定我做错了什么。我已经包括了我认为问题可能存在于下面的区域。如果需要更多信息,我可以分享更多。我希望已经尝试过执行类似操作的人可以立即看到我明显做错了什么。任何信息都会有帮助。谢谢!

修改webcam.js,增加函数

preProc() {
return tf.tidy(() => {
  // Reads the image as a Tensor from the webcam <video> element.
  const webcamImage = tf.fromPixels(this.webcamElement);

  //Resize to our image and get back single channel for greyscale
  const croppedImage = this.cropImage(webcamImage, 1);

  // Expand the outer most dimension so we have a batch size of 1.
  const batchedImage = croppedImage.expandDims(0);

  // Normalize the image between -1 and 1. The image comes in between 0-255,
  // so we divide by 127 and subtract 1.
  return batchedImage.toFloat().div(tf.scalar(127)).sub(tf.scalar(1));
});
}

/**
* Crops an image tensor so we get a square image with no white space.
* @param {Tensor4D} img An input image Tensor to crop.
*/
cropImage(img, dim=3) {
  const size = Math.min(img.shape[0], img.shape[1]);
  const centerHeight = img.shape[0] / 2;
  const beginHeight = centerHeight - (size / 2);
  const centerWidth = img.shape[1] / 2;
  const beginWidth = centerWidth - (size / 2);
  return img.slice([beginHeight, beginWidth, 0], [size, size, dim]);
}

来自 ui.js 我正在使用 drawFrame

export function drawFrame(image, canvas) {
  const [width, height] = [300, 165];
  const ctx = canvas.getContext('2d');
  const imageData = new ImageData(width, height);
  const data = image.dataSync();
  for (let i = 0; i < height * width; ++i) {
    const j = i * 4;
    imageData.data[j + 0] = (data[i * 3 + 0] + 1) * 127;
    imageData.data[j + 1] = (data[i * 3 + 1] + 1) * 127;
    imageData.data[j + 2] = (data[i * 3 + 2] + 1) * 127;
    imageData.data[j + 3] = 255;
  }
  ctx.putImageData(imageData, 0, 0);
}

最后在 index.js 中,当按下预测按钮时,会执行下面的处理程序

async function predict() {
while (isPredicting) {
  const predictedClass = tf.tidy(() => {
    // Capture the frame from the webcam.
    const imgmod = webcam.preProc();
    ui.drawFrame(imgmod, grayframe);


    // Returns the index with the maximum probability. This number corresponds
    // to the class the model thinks is the most probable given the input.
    //return predictions.as1D().argMax();
    return imgmod;
  });

  const classId = (await predictedClass.data())[0];
  predictedClass.dispose();

  //ui.predictClass(classId);
  await tf.nextFrame();
  }
  ui.donePredicting();
}

【问题讨论】:

    标签: python-3.x tensorflow keras tensorflow.js


    【解决方案1】:

    drawframe 正在绘制图像三遍。 它与输入图像的形状以及使用heightwidth 裁剪图像的方式有关。如果输入图像的形状为 [298, 160],则不会渲染画布,因为在尝试访问不在 data 中的索引时会出错。例如data 的大小是298 * 160,而循环的最后一个元素将尝试访问元素3 * 300 * 160。由于代码没有错误,说明data的大小大于[298, 160]。无论如何,数据维度存在不匹配。由于三个通道,图像被绘制了 3 次,可能是因为它之前没有被移除。

    您可以考虑使用tf.toPixel方法,而不是自己实现绘制图像数据的方式

    【讨论】:

    • 谢谢edkeveked。我最初尝试使用 tf.toPixel,但我收到一条消息,指出 tf 已被销毁,我认为这是由于逻辑位于 tf.tidy 中。所以后来我更多地查看了 tf.js 示例,发现他们正在使用这个 ui 类来执行绘图,所以我也照做了。想我会采用这种方法,直到我更好地理解 tensorflow.js。感谢您的帮助...我会更多地研究并条机为什么会这样做。
    • 要在上面添加更多细节,我在使用 tf.toPixel 而不是 ui.drawframe 时收到的错误消息是:“未捕获(承诺)错误:张量已释放。”。如果我遇到解决方案,将在此处发布答案。
    • 这是因为 tf.tidy。考虑在绘制图像后使用它来处理张量
    • 再次感谢edkeveked。这帮助很大。我使用 tidy 分配了预处理的图像,然后执行了对 tf.toPixel 的调用,现在我的画布上有一个正常的绘图。谢谢!!
    • 很高兴它有帮助。至于并条机的问题,我认为这与张量的形状以及您使用高度和宽度的方式有关。你能说出最初的形状是什么吗?
    猜你喜欢
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 2015-04-28
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    • 1970-01-01
    • 2020-09-21
    相关资源
    最近更新 更多