C++读取FY卫星遥感图像(HDF格式)

发布时间 2023-12-15 17:22:44作者: zxl260

转一下我自己的博客

网上找了大概2周,艰难的实现了C++读取HDF图像,CSDN吃相真难看,好多文章都要会员。。。

#include <cstdint>
#include <hdf5.h>
#include <iostream>
#include <matplotlibcpp.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
namespace plt = matplotlibcpp;
using namespace std;
//该函数用于读取hdf文件中group、data等信息
herr_t op_func(hid_t loc_id, const char* name, const H5O_info_t* info,void*operator_data)
{
    printf("/");               /* Print root group in object path */

    /*
     * Check if the current object is the root group, and if not print
     * the full path name and type.
     */
    if (name[0] == '.')         /* Root group, do not print '.' */
        printf("  (Group)\n");
    else
        switch (info->type) {
            case H5O_TYPE_GROUP:
                printf("%s  (Group)\n", name);
                break;
            case H5O_TYPE_DATASET:
                printf("%s  (Dataset)\n", name);
                break;
            case H5O_TYPE_NAMED_DATATYPE:
                printf("%s  (Datatype)\n", name);
                break;
            default:
                printf("%s  (Unknown)\n", name);
        }

    return 0;
}
void hdf5_test1(){
    // 打开HDF5文件
    char file_path[] = "test.HDF";
    hid_t file_id=H5Fopen(file_path, H5F_ACC_RDONLY,H5P_DEFAULT );
    herr_t status;
    //这里读取hdf信息,找到数据保存位置
    status = H5Ovisit(file_id, H5_INDEX_NAME, H5_ITER_NATIVE, op_func, nullptr, H5O_INFO_ALL);
    hid_t dataset_id;
    //"/Data/NOMChannel03"就是需要事先读取的数据保存位置
    dataset_id = H5Dopen1(file_id, "/Data/NOMChannel03");

    hid_t dataspace_id = H5Dget_space(dataset_id);
    int ndims;
    //获取数据维度
    ndims = H5Sget_simple_extent_ndims(dataspace_id);
    auto dims = new hsize_t[ndims];
    //获取数据大小
    H5Sget_simple_extent_dims(dataspace_id, dims, nullptr);
    auto x = dims[0];
    auto y = dims[1];
    size_t nn = x*y;
    hid_t datatype_id;
    H5T_class_t dataclass;
    size_t size;
    datatype_id = H5Dget_type(dataset_id);
    dataclass= H5Tget_class(datatype_id);
    size = H5Tget_size(datatype_id);
    cv::Mat img = cv::Mat(int(x), int(y), CV_16S);//CV_16S是为了读取short类型数据
    if(dataclass == H5T_INTEGER){
        if (size == sizeof(short)) {
            auto* buffer = (short*) calloc(nn, sizeof(short));
            //H5T_NATIVE_SHORT表示short类型
            H5Dread(dataset_id, H5T_NATIVE_SHORT, H5S_ALL,H5S_ALL, H5P_DEFAULT, buffer);
            int n = 0;
            short *ptmp = NULL;
            for(int i=0; i<x; i++)
            {
                ptmp = img.ptr<short>(i);//指针指向img的第i行
                for(int j=0;j<y;j++) {
                    ptmp[j] = buffer[n++];
                }
            }
            cv::imwrite("../output.png", img);
            cv::namedWindow("新图", cv::WINDOW_KEEPRATIO);
            cv::imshow("新图", img);
            // 等待100000 ms后窗口自动关闭
            cv::waitKey(0);
            free(buffer);
            H5Fclose(file_id);
            H5Dclose(dataset_id);
        }
        else {
            printf("2dData::readHDF5: unknown integer type, size=%i\n",(int) size);
        }
    }
    else {
        printf("2dData::readHDF5: unknown HDF5 data type\n");
    }
}



int main() {
    hdf5_test1();
}