【问题标题】:How to load 16 bits grayscale png in OpenCV.js?如何在 OpenCV.js 中加载 16 位灰度 png?
【发布时间】:2021-07-16 04:10:50
【问题描述】:

我想在 Javascript 中加载一个 16 位灰度 PNG(其中每个像素代表一个数字/深度值。This is file format is used by TUM to store depth information

但是,opencv.js 读取的图像是 RGBA 8bits (mat.type() == 24 == cv.CV_8UC4 - 我想得到cv.CV_16UC1),这似乎是因为图像是由浏览器本身解码的,Because canvas only support 8-bit RGBA image with continuous storage, the cv.Mat type is cv.CV_8UC4 作为documentation 表示它。因此,我们没有得到一个像素,而是得到一个介于 0 和 65535 (2^8-1) 之间的值,而是得到一个介于 0 和 255 (2^8-1) 之间的数字,其中 R=G=B 和 A=255

[编辑] 为了重新制定它,画布将我的 16 位灰度转换为 8 位 RGBA。画布处理 2^24 种颜色,但在转换过程中 R=G=B 并且每个通道是 2^8,因此它只处理 2^8 灰度而不是 2^16 灰度。

没有做任何特别的事情: https://jsfiddle.net/remmel/rmntq4yb/74/

摘录:

var img = await loadImage("https://raw.githubusercontent.com/remmel/rgbd-dataset/main/rgbd_dataset_freiburg1_desk/depth/1305031468.188327.png");
var canvasOriginal = document.getElementById('canvas0')
var ctxOriginal = canvasOriginal.getContext('2d')
canvasOriginal.width = img.width
canvasOriginal.height = img.height
ctxOriginal.drawImage(img, 0, 0)
var mat = cv.imread('canvas0')
console.log(mat.channels(), mat.type() === cv.CV_8UC4) //4, true

图像魔术:

$ identify 1305031468.188327.png
1305031468.188327.png PNG 640x480 640x480+0+0 16-bit Grayscale Gray 131604B 0.000u 0:00.000

我尝试使用 jimp-browser 解码图像,但仍然得到 RGBA 图像。调试它,我看到它在 16 位中读取了正确的灰度值,但在将其转换为 8 位后,R=G=B=gray 8bit 和 A=255。一个解决方案可能是自定义 (fix?) 该库

我也尝试使用 OpenCV.js 直接加载图像,但仍然是相同的 4 通道图像:

<img src='https://i.stack.imgur.com/8am9t.png' id='dpng' />

  var depthMat2 = cv.imread('dpng')
  console.log(depthMat2.channels(), depthMat2.type() === cv.CV_8UC4) //4 true

图像(imgur 似乎没有压缩图像):

【问题讨论】:

  • 我不明白这个问题。画布支持 16,777,216 种颜色。你的实际目标是什么?
  • 是的,画布支持 2^24 颜色。但它似乎只支持 256 个灰度。 Canvas 将 16 位灰度图像转换为 8 位 RGBA
  • 实际有 256 种灰色,因为灰色是指 RGB 光谱的所有颜色都相同。 R = 0,G = 0,B = 0; R = 1,G = 1,B = 1;一直到 R = 255,G = 255,B = 255。
  • 是的,但我的原始图像的灰度介于 0 和 65535 之间。并且 Canvas 无法处理 R=65535、G=65535、B=65535(如果有帮助,我进行了编辑)跨度>
  • Canvas ctx.drawImage(imageElement) 应该会自动工作,只要该 imageElement 已加载并且是 .png。我还是不明白你的目的。这是什么?

标签: javascript opencv


【解决方案1】:

我改用 fast-png lib 来读取我的 16 位灰度 PNG:https://www.npmjs.com/package/fast-png

import { decode } from 'fast-png'
...
var arrayBuffer = await((await fetch(urlDepth)).arrayBuffer())
var depthData = (await decode(arrayBuffer)).data

【讨论】:

    【解决方案2】:

    我想你只想做比率数学:

    function rgbAlter(rgb){
      return 65535/255*rgb;
    }
    for(let i=0,l=256; i<l; i++){
      console.log(rgbAlter(i));
    }

    【讨论】:

    • 给你一个具体的例子,在那个 png 中,第 3 个像素是灰色(8213),但是浏览器给了我第 3 个像素 rgba(32,32,32,255)和 8213/256=32.08(另一个示例第 4 个像素:gray(8841) rgba(34,34,34,255), 8841>>8=34)。如您所见,如果丢失信息,则无法找回: 32*256 = 8192 != 8213
    猜你喜欢
    • 2012-02-07
    • 2017-02-13
    • 2019-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 2011-09-19
    相关资源
    最近更新 更多