【问题标题】:How to convert JSON descriptors to cv.Mat format in opencv4nodejs?如何在 opencv4nodejs 中将 JSON 描述符转换为 cv.Mat 格式?
【发布时间】:2020-02-03 21:57:07
【问题描述】:

我正在尝试使用存储在匹配功能函数内的 JSON 文件中的数据,使用 opencv4nodejs。存储的数据是来自先前计算的图像的描述符。当数据被计算然后在代码中使用时一切正常,但从 JSON 文件中获取时却不行。 数据类型为cv.Mat,然后使用fs.writeFileSync() 方法存储在JSON 文件中。问题是使用这些描述符的下一个函数需要cv.Mat 类型的变量,JSON 数据不被视为这样。如何使用存储在 JSON 文件中的这些数据?

这个过程在 c++ 中完美运行,使用cv::FileStorage 方法。 JSON 文件如下所示:

{
    "first": {
        "type_id": "opencv-matrix",
        "rows": 69,
        "cols": 128,
        "dt": "f",
        "data": [ 2.76096805e-04, 7.95492728e-04, 4.21693228e-04, (...)
},
    "second": {
        "type_id": "opencv-matrix",
        "rows": 45,
        "cols": 128,
        "dt": "f",
        "data": [ 3.94702045e-04, 1.63780281e-03, -2.23156996e-03, (...)
    }
}

JSON 文件显示存储的数据,可用于存储带有>> 运算符的cv::Mat 变量。

我无法使用 opencv4nodejs 5.5.0 版在 node.js 中重现此过程。 我使用cv.Mat 变量上的JSON.stringify() 方法保存了JSON 文件,然后使用fs 包中的fs.writeFileSync() 方法来存储描述符(不幸的是,在opencv4nodejs 中似乎没有与cv::FileStorage 等效的方法)。 首先,我无法在创建的 JSON 文件中看到任何数据:

{"first":{"step":512,"elemSize":4,"sizes":[69,128],"empty":0,"depth":5,"dims":2,"channels":1,"type":5,"cols":128,"rows":69},
"second":{"step":512,"elemSize":4,"sizes":[45,128],"empty":0,"depth":5,"dims":2,"channels":1,"type":5,"cols":128,"rows":45}}

我尝试通过first.sizes方法访问sizes元素,但它只返回数组的大小,而不是里面的数据。我徒劳地搜索了一种访问 JSON 文件中不可见数据的方法。对此有所了解会很棒。 更重要的是,我不能在下一个函数中使用这些描述符,因为它需要 cv.Mat 类型。

MSERDetector::MatchKnn - Error: expected argument 0 to be of type Mat

我已经探索了两种解决方案,到目前为止都没有成功:

  • 格式化 JSON 文件。我尝试创建一个 JSON 数组,但没有效果:
["first":{"step":512,"elemSize":4,"sizes":[69,128],"empty":0,"depth":5,"dims":2,"channels":1,"type":5,"cols":128,"rows":69},
"second":{"step":512,"elemSize":4,"sizes":[45,128],"empty":0,"depth":5,"dims":2,"channels":1,"type":5,"cols":128,"rows":45}]

我还尝试添加一个名为 mat 的密钥(我知道这是一个愚蠢的密钥,不知道如何格式化我的 JSON 文件,因为我在网上找不到任何文档):

{"mat":{"first":{"step":512,"elemSize":4,"sizes":[69,128],"empty":0,"depth":5,"dims":2,"channels":1,"type":5,"cols":128,"rows":69}},
"second":{"step":512,"elemSize":4,"sizes":[45,128],"empty":0,"depth":5,"dims":2,"channels":1,"type":5,"cols":128,"rows":45}}
  • 将 JSON 数据转换为 cv.Mat。我首先使用fs.readFileSync()读取文件,然后使用JSON.parse()方法解析文件。当试图用new cv.Mat() 转换这个变量时,它返回一个空矩阵。我还尝试手动填充它:
const descriptors_first = new cv.Mat(descriptors.first.rows, descriptors.first.cols, descriptors.first.type, descriptors.first.channels, descriptors.first.depth, descriptors.first.dims, descriptors.first.empty, descriptors.first.step, descriptors.first.elemSize, descriptors.first.sizes);

这一次,它返回一个 cv.Mat 变量,显示与刚刚计算的 {keys:values} 完全相同的变量,但给出了错误的结果。就像里面根本没有存储任何数据一样。

也许我的问题可以更准确:有没有办法表明 JSON 文件的类型为cv.Mat,如果是,如何在 opencv4nodejs 中这样做?我们看到cv::FileStorage 在创建文件时指定了一个类型"type_id": "opencv-matrix"。但我找不到任何有关 opencv4nodejs 的文档或示例。第二个问题,如何将 JSON 数据转换为 cv.Mat,以实际使用假定存储在 JSON 文件中的数据填充几乎创建的变量?问题可能是文件不包含数据,因为我没有发现任何查看它们的可能性。奇怪的是,我什至看不到console.log() 的数据。在描述符cv.Mat 变量上,它显示:

Mat {
  step: 512,
  elemSize: 4,
  sizes: [ 69, 128 ],
  empty: 0,
  depth: 5,
  dims: 2,
  channels: 1,
  type: 5,
  cols: 128,
  rows: 69
}

在解析后的 JSON 文件上:

{
  first: {
    step: 512,
    elemSize: 4,
    sizes: [ 69, 128 ],
    empty: 0,
    depth: 5,
    dims: 2,
    channels: 1,
    type: 5,
    cols: 128,
    rows: 69
  }
}

欢迎任何帮助,无论如何感谢您阅读我的问题。

【问题讨论】:

  • 将您的输出放入一个变量中并作为字典访问它们。例如,output = {"first":{"step":512,"elemSize":4,"sizes":[69,128],"empty":0,"depth":5,"dims":2,"channels":1,"type":5,"cols":128,"rows":69}, "second":{"step":512,"elemSize":4,"sizes":[45,128],"empty":0,"depth":5,"dims":2,"channels":1,"type":5,"cols":128,"rows":45}} 你会得到 [69, 128] 的东西 output["first"]["sizes"]
  • 您可以使用 OpenCV 的文件系统在本地以 YAML 格式存储和检索来自 OpenCV 浮点矩阵的浮点数据,完全无需外部 JSON 解析器。如果可能的话,我建议采用前一种方法,因为它更容易、更快捷!
  • 谢谢@testuser。实际上,console.log(output["first"]["sizes"]) 返回 [69, 128]。但我仍然无法访问任何数据,也无法使用此输出,因为它未被识别为 cv.Mat 类型。
  • 谢谢@eldesgraciado。我为 node.js 安装了js-yaml 模块。我用yaml.load(fs.writeFileSync("./uploads/descriptors.yml", descriptors_first)); 创建了 yml 文件。这次文件只包含[object Mat],由于不是cv.Mat类型,所以还是不能使用。

标签: node.js json opencv opencv4nodejs


【解决方案1】:

好的,我写这篇文章是为了回答,因为太长了,无法发表评论。这就是您打开YAML 文件并将其数据存储在OpenCV 矩阵中的方式。 YAML 文件中的数据根据​​“标签”存储。我们可以在一个文件中定义多个矩阵的多个标签。

因此,例如,包含矩阵数据的文件可能如下所示:

myInputFile.yml:

myMatrix: !!opencv-matrix
   rows: 2
   cols: 2
   dt: f
   data: [ 5.8485,  12.6626,
           6.6515,  11.0982 ]

该文件定义了一个 2 x 2 矩阵。数据类型由dt 标签定义,在本例中为float。检索此数据的方法是请求myMatrix 标签,并使用空矩阵作为接收器。我不知道 OpenCV java 的语法;在 C++ 中,你就是这样做的:

//let's read the external YAML file:
std::string fileStoragePath = "myInputFile.yml";

//use OpenCv's file system to open the file:
cv::FileStorage inputFile( fileStoragePath, cv::FileStorage::READ );

//let's check if the file can be actually opened…
if ( !inputFile.isOpened() ){
   std::cout << "Encountered an error while opening the file!" <<std::endl;
}

//parse the data in the input file to a matrix:
cv::Mat dataMatrix;

//Now, give me a label, and I will give you the data of that label:
std::string fieldName = "myMatrix";
inputFile [ fieldName ] >> dataMatrix;

你的浮动数据应该在dataMatrix,你可以正常寻址。

【讨论】:

  • 正如我在最初的问题中提到的,这与cv.FileStorage() 完美配合。数据出现在文件中,并且可以轻松检索。我的问题是它在 node.js 中不起作用。数据不出现在文件中(没有“data”键),并且不能被使用,因为文件未被识别为opencv矩阵。在opencv4nodejs中必须有一种特定的方式来表明一个数据集是cv.Mat类型的,但是我找不到关于这个主题的任何文档。
猜你喜欢
  • 2020-11-21
  • 2021-10-29
  • 1970-01-01
  • 2021-10-19
  • 2011-03-25
  • 2012-08-20
  • 1970-01-01
  • 2021-09-26
  • 1970-01-01
相关资源
最近更新 更多