HDFql保存和加载图像

时间:2019-09-04 07:46:59

标签: c++ opencv hdf5 hdfql

我正在尝试使用HDFql将图像从OpenCV保存到HDF5。这是我要实现的目标的一个最小示例(假设您在/tmp/lena.jpg处有一个图片):

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <HDFql.hpp>

int main() {
    char script[1024];

    HDFql::execute("CREATE FILE /tmp/test.h5");
    HDFql::execute("USE FILE /tmp/test.h5");
    HDFql::execute("CREATE GROUP image");
    cv::Mat img = cv::imread("/tmp/lena.jpg", CV_8UC3);
    cv::Size size(img.size());
    std::cout << "Size = " << size.width << ", " << size.height;

    for(int i=0; i<100; i++)
    {
        // Show a few pixel values - cast is necessary, since values are unsigned char
        std::cout << i << ": " << (int)img.data[i] << std::endl;
    }

    sprintf(script, "CREATE CONTIGUOUS DATASET test/image AS UNSIGNED TINYINT(%d)", size.width*size.height*3);
    HDFql::execute(script);
    sprintf(script, "INSERT INTO test/image VALUES FROM MEMORY %d", HDFql::variableRegister(img.data));
    HDFql::execute("CLOSE FILE");

    HDFql::execute("USE FILE /tmp/test.h5");
    cv::Mat img_loaded = cv::Mat::zeros(cv::Size(size.width, size.height), CV_8UC3);
    HDFql::variableRegister(img_loaded.data);
    HDFql::execute("SELECT AS INT FROM image VALUES INTO MEMORY " + HDFql::variableGetNumber(img_loaded.data));
    HDFql::variableUnregister(img_loaded.data);
    HDFql::execute("CLOSE FILE");

    cv::imshow("loaded image", img_loaded);
    cv::waitKey();

    return 0;
}

此代码基本上创建了一个新的HDF5文件,然后使用OpenCV打开图像并将该图像保存到HDF5文件中。然后从HDF5文件加载相同的图像并显示它。

如果您没有OpenCV,则始终可以用uchar数组替换image.data,例如:uchar image_data[10] = {1,2,3,4,5,6,7,8,9,10};

长话短说,这不起作用,并且在检查HDF5文件时,在保存步骤中它已经失败了。任何对我做错事的帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

您的代码段中的HDFql SELECT操作包含两个问题:1)您不能在那里指定AS INT,2)数据集image位于组{{1}中}。另外,永远不会调用(即执行)将数据写入数据集中的脚本。

此外,可以对代码段进行一些优化,即:

  1. 删除关键字“ CONTIGUOUS”,因为创建数据集时 默认情况下是连续的。
  2. 将数据集的数据类型更改为test-我相信您想存储图像的原始数据,以便此数据类型更合适。
  3. 以临时方式注册变量,以便在使用它们(由HDFql使用)后,它们将自动取消注册-这会减轻您的负担。

以下是经过纠正/重构的代码段:

OPAQUE

答案 1 :(得分:1)

这是基于@SOG给出的答案-谢谢!

#include <iostream.h>
#include <HDFql.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

int main (int argc, const char * argv[]) {
    char script[1024];

    //Create HDF5 file and group "test"
    HDFql::execute("CREATE TRUNCATE FILE /tmp/test.h5");
    HDFql::execute("USE FILE /tmp/test.h5");
    HDFql::execute("CREATE GROUP test");

    //==== Load Image, save it to test.h5/test/image ====
    //Choose color or grayscale
    //cv::ImreadModes read_mode = cv::IMREAD_GRAYSCALE;
    cv::ImreadModes read_mode = cv::IMREAD_COLOR;
    cv::Mat img = cv::imread("/tmp/lena.jpg", read_mode);
    cv::Size size(img.size());
    int num_pixels = size.width*size.height*img.channels();

    cv::imshow("image", img);
    cv::waitKey();

    sprintf(script, "CREATE DATASET test/image AS UNSIGNED TINYINT(%d) "
        "VALUES FROM MEMORY %d", num_pixels,
            HDFql::variableTransientRegister(img.data));
    HDFql::execute(script);
    HDFql::execute("CLOSE FILE");

    //==== Load HDF5, and load saved image data to a new cv::Mat image ====
    HDFql::execute("USE FILE /tmp/test.h5");
    cv::Mat img_loaded;
    if(read_mode == cv::IMREAD_COLOR)
    {
        img_loaded = cv::Mat::zeros(size, CV_8UC3);
    } else
    {
        img_loaded = cv::Mat::zeros(size, CV_8UC1);
    }
    std::cout << "size = " << img_loaded.size() << ", type = " << img_loaded.type() 
        << ", channels = " << img_loaded.channels() <<std::endl;

    sprintf(script, "SELECT FROM test/image INTO MEMORY %d",
        HDFql::variableTransientRegister(img_loaded.data));
    HDFql::execute(script);
    HDFql::execute("CLOSE FILE");

    cv::imshow("loaded image", img_loaded);
    cv::waitKey();
}

此代码对于灰度图像和彩色图像均适用。 @SOG的答案仍然存在一些问题,除了一些小问题,我无法使用它处理数据类型OPAQUE,因此我回到了使用UNSIGNED TINYINT的位置。我不知道为什么会这样。

除此之外,@ SOG的详尽答案几乎可以捕捉到我的代码无法正常工作的原因。