HDFql 保存和加载图像

Posted

技术标签:

【中文标题】HDFql 保存和加载图像【英文标题】:HDFql Saving and Loading Images 【发布时间】:2020-01-07 01:44:11 【问题描述】:

我正在尝试使用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,您可以随时将 image.data 替换为 uchar 数组,例如:uchar image_data[10] = 1,2,3,4,5,6,7,8,9,10;

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

【问题讨论】:

【参考方案1】:

您的代码 sn-p 中的 HDFql SELECT 操作包含两个问题:1) 您不能在此处指定 AS INT 和 2) 数据集 image 位于组 test 中。此外,将数据写入数据集的脚本永远不会被调用(即执行)。

另外,sn-p的代码可以做一些优化,即:

    删除关键字“CONTIGUOUS”,因为在创建数据集时它是 默认情况下是连续的。 把数据集的数据类型改成OPAQUE - 相信你想存储图片的原始数据所以这个数据类型比较合适。 以临时方式注册变量,以便在使用后(由 HDFql)自动取消注册 - 这样可以减轻您的负担。

这里是代码 sn-p 更正/重构:

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

int main() 
    char script[1024];

    HDFql::execute("CREATE AND 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 DATASET test/image AS OPAQUE(%d) VALUES FROM MEMORY %d", size.width*size.height*3, HDFql::variableTransientRegister(img.data));
    HDFql::execute(script);
    HDFql::execute("CLOSE FILE");

    cv::Mat img_loaded = cv::Mat::zeros(cv::Size(size.width, size.height), CV_8UC3);
    sprintf(script, "SELECT FROM /tmp/test.h5 test/image INTO MEMORY %d", HDFql::variableTransientRegister(img_loaded.data));
    HDFql::execute(script);

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

    return 0;

【讨论】:

【参考方案2】:

这是基于@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 的彻底回答几乎抓住了我的代码无法正常工作的原因。

【讨论】:

以上是关于HDFql 保存和加载图像的主要内容,如果未能解决你的问题,请参考以下文章

保存和加载图像生成器 (Tensorflow Keras)

javascript从客户端保存/加载图像+文本数据

imgaug:加载和保存图像

如何使用 WebGL 异步加载图像、创建纹理、渲染和保存图像?

尝试在应用程序错误 NSInvalidArgumentException 中保存/加载图像

Xcode 在 Xcode iOS 中保存和加载图像