p5.js |从相机馈送捕获的图像质量低于实际相机馈送?

p5.js | Quality of image captured from camera feed, lower than actual camera feed?

使用下面的代码,来自我的 Mac 相机并在 <video> 中显示的视频质量非常好。

然而,我在 p5 canvas 中捕获和显示的帧的质量非常低、暗且有颗粒感。为什么会这样,我可以解决它吗?

function setup() {
  let canvas = createCanvas(canvasSize, canvasSize)
  canvas.elt.width = canvasSize
  canvas.elt.height = canvasSize
  video = createCapture(VIDEO)
}

let PAUSE = false

async function draw() {

  if (video && video.loadedmetadata) {

    if (!PAUSE) {
      // the quality of this image is much lower than what is shown inside p5's <video>
      image(video.get(), 0, 0, canvasSize, canvasSize, x, y, canvasSize, canvasSize)

      PAUSE = true

    }

  }

}

你不应该这样设置 width/height。这会弄乱高 DPI 显示器的大小,并导致您的图像显得拉伸和模糊。

const canvasSize = 500;

function setup() {
  let canvas = createCanvas(canvasSize, canvasSize)
  // Don't do this, it will mess up the sizing on high DPI displays:
  // canvas.elt.width = canvasSize
  // canvas.elt.height = canvasSize
  video = createCapture(VIDEO)
}

let PAUSE = false;

function draw() {
  if (video && video.loadedmetadata) {
    if (!PAUSE) {
      // the quality of this image is much lower than what is shown inside p5's <video>
      image(video.get(), 0, 0, canvasSize, canvasSize, 0, 0, canvasSize, canvasSize)
    }
  }
}

function keyPressed() {
  if (key === 'p') {
    PAUSE = !PAUSE;
  }
}

使用此代码,我暂停了正在呈现给 p5.js 的视频,然后截取了屏幕截图。 p5.js canvas 上显示的视频版本与实时视频没有区别。

我找到问题所在了。

不是因为我设置了canvas.elt.widthcanvas.elt.height,尽管设置它们确实是多余的。

这是因为在 OP 中显示的代码中,我捕获了 第一帧 而这 太快了 所以第一帧框架仍然是黑暗和模糊的。显然从相机传来的前几帧是这样的。

如果我给我的代码延迟例如5 秒后,它捕获的帧与来自视频源的帧质量完全相同。

let video
let canvasWidth = 400

// set this to 10 on https://editor.p5js.org/ and you'll see the problem
const DELAY = 5000

function setup() {
  let canvas = createCanvas(canvasWidth, canvasWidth)
  canvas.elt.width = canvasWidth // redundant
  canvas.elt.height = canvasWidth // redundant
  video = createCapture(VIDEO)
}

let PAUSE = false
let start = Date.now()

async function draw() {
  let delay = Date.now() - start

  if (video && video.loadedmetadata) {

    if (delay > DELAY && !PAUSE) {
      PAUSE = true
      
      let x = Math.round((video.width / 2) - (canvasWidth / 2))
      let y = Math.round((video.height / 2) - (canvasWidth / 2))

      // the quality of this image is now perfect
      image(video.get(), 0, 0, canvasWidth, canvasWidth, x, y, canvasWidth, canvasWidth)
    }

  }

}