Saving Armadillo matrix/cube into HDF5 file - c++

I'm trying to save a struct with multiple arma::vec, arma:mat and arma::cube.
struct rdb_struct{
string info;
vec rng_vec;
vec azvec;
cube TSAP;
cube CONV;
cube TVSAP;
mat rd_maxbeam;
mat rd_maxbeam2;
mat rd_maxbeam3;
umat rd_maxbeam_index;
umat rd_maxbeam2_index;
umat rd_maxbeam3_index;
mat rd_maxbeam_azdeg;
mat rd_maxbeam2_azdeg;
mat rd_maxbeam3_azdeg;
};
For the string and vectors, it was somewhat simple to save:
#define ARMA_DONT_USE_WRAPPER
#include <armadillo>
#include <string>
#include <iostream>
#include "H5Cpp.h"
#define ARMA_ALLOW_FAKE_GCC //allows the use of GCC compiled armadillo with ICC compiler
using namespace std;
using namespace arma;
struct rdb_struct{
string info;
//params_struct params;
vec rng_vec;
vec azvec;
cube TSAP;
cube CONV;
cube TVSAP;
mat rd_maxbeam;
mat rd_maxbeam2;
mat rd_maxbeam3;
umat rd_maxbeam_index;
umat rd_maxbeam2_index;
umat rd_maxbeam3_index;
mat rd_maxbeam_azdeg;
mat rd_maxbeam2_azdeg;
mat rd_maxbeam3_azdeg;
};
struct rdb_struct_hdf5{
string info;
// params_struct params;
hvl_t rng_vec;
hvl_t azvec;
hid_t mem_TSAP;
};
int main(void)
{
rdb_struct rdb_data;
rdb_struct_hdf5 rdb_hdf5;
long long unsigned int NR=256;
long long unsigned int ND=450;
long long unsigned int NE=64;
hid_t vlen_double = H5Tvlen_create(H5T_NATIVE_DOUBLE);
rdb_data.info="testing woohoo";
rdb_data.rng_vec=2*ones<vec>(32);
rdb_data.azvec=3*ones<vec>(32);
rdb_data.TSAP=4*ones<cube>(NR,ND,NE);
rdb_data.CONV=5*ones<cube>(NR,ND,NE);
rdb_data.TVSAP=6*ones<cube>(NR,ND,NE);
rdb_data.rd_maxbeam=7*ones<mat>(NR,ND);
rdb_data.rd_maxbeam2=8*ones<mat>(NR,ND);
rdb_data.rd_maxbeam3=9*ones<mat>(NR,ND);
rdb_data.rd_maxbeam_index=10*ones<umat>(NR,ND);
rdb_data.rd_maxbeam2_index=11*ones<umat>(NR,ND);
rdb_data.rd_maxbeam3_index=12*ones<umat>(NR,ND);
rdb_data.rd_maxbeam_azdeg=13*ones<mat>(NR,ND);
rdb_data.rd_maxbeam2_azdeg=14*ones<mat>(NR,ND);
rdb_data.rd_maxbeam3_azdeg=15*ones<mat>(NR,ND);
rdb_hdf5.info=rdb_data.info;
rdb_hdf5.rng_vec.p=rdb_data.rng_vec.memptr();
rdb_hdf5.rng_vec.len=rdb_data.rng_vec.size();
rdb_hdf5.azvec.p=rdb_data.azvec.memptr();
rdb_hdf5.azvec.len=rdb_data.azvec.size();
// the array of each length of multidimentional data.
hsize_t dim_rdb[1];
dim_rdb[0] = sizeof(rdb_hdf5) / sizeof(rdb_struct_hdf5);
// the length of dim
int rank_rdb = sizeof(dim_rdb) / sizeof(hsize_t);
// defining the datatype to pass HDF55
H5::CompType h5_rdb(sizeof(rdb_struct_hdf5));
h5_rdb.insertMember("info", HOFFSET(rdb_struct_hdf5, info), H5::StrType(H5::PredType::C_S1, H5T_VARIABLE));
h5_rdb.insertMember("rng_vec", HOFFSET(rdb_struct_hdf5, rng_vec), vlen_double);
h5_rdb.insertMember("azvec", HOFFSET(rdb_struct_hdf5, azvec), vlen_double);
h5_rdb.insertMember("TSAP", HOFFSET(rdb_struct_hdf5, mem_TSAP), cube_double);
// preparation of a dataset and a file.
H5::DataSpace space_rdb(rank_rdb, dim_rdb);
H5::H5File *file = new H5::H5File("data_test.h5", H5F_ACC_TRUNC);
H5::DataSet *dataset_rdb = new H5::DataSet(file->createDataSet("rdb_data", h5_rdb, space_rdb));
// Write
dataset_rdb->write(&rdb_hdf5, h5_rdb);
delete dataset_rdb;
delete file;
return 0;
}
But the mat and cubes have been giving me trouble, mainly because I have no idea what I'm doing with HDF5. It looks like to do what I want, I need to create a H5Tarray_create and insert it into the 'cpmp_type h5_rdb' but everything I have tried has failed to run (it does compile) with the following message:
HDF5-DIAG: Error detected in HDF5 (1.10.4) thread 139735682275136:
#000: ../../../src/H5Tcompound.c line 354 in H5Tinsert(): unable to insert member
major: Datatype
minor: Unable to insert object
#001: ../../../src/H5Tcompound.c line 446 in H5T__insert(): member extends past end of compound type
major: Datatype
minor: Unable to insert object
terminate called after throwing an instance of 'H5::DataTypeIException'
Aborted (core dumped)
This code seems to work but when I try to merge it with my original code it doesn't work, mainly from me not understanding how/why hid_t is used for everything...
#include <armadillo>
#include <string>
#include <iostream>
#include "H5Cpp.h"
#define ARMA_ALLOW_FAKE_GCC //allows the use of GCC compiled armadillo with ICC compiler
using namespace std;
using namespace arma;
int
main (void)
{
long long unsigned int NR=64;
long long unsigned int ND=64;
long long unsigned int NE=64;
hsize_t dims_of_int_array[] = {NR,ND,NE};
hsize_t dims_of_int_dataspace[] = {1};
// int *data = (int *)malloc(4*4*4*sizeof(int));
// int i;
// for (i=0; i<(4*4*4); i++) data[i] = i;
cube data = 4*ones<cube>(NR,ND,NE);
hid_t file = H5Fcreate("multset.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
hid_t mem_h5t = H5Tarray_create(H5T_NATIVE_DOUBLE, 2, dims_of_int_array);
hid_t dataspace = H5Screate_simple(2, dims_of_int_dataspace, NULL);
hid_t dataset = H5Dcreate(file, "data_data", mem_h5t, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
H5Dwrite(dataset, mem_h5t, H5S_ALL, H5S_ALL, H5P_DEFAULT, data.memptr());
H5Dclose(dataset);
H5Sclose(dataspace);
H5Tclose(mem_h5t);
// free(data);
return 0;
}
I did notice the code that is work only works until the cube size becomes too large and starts spitting out errors about contiguous write failed but I think that's a problem for another day. I'm mainly looking for help on how to insert a array datatype into a composite datatype. Any help would be greatly appreciated.

Related

Is this a memory issue with DNN_BACKEND_CUDA and DNN_FRONTEND_CUDA?

I have the following code:
#include <iostream>
#include <opencv2/dnn_superres.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <filesystem>
#include <thread>
#include <future>
#include <opencv2/dnn/dnn.hpp>
#include <opencv2/core/cuda.hpp>
#include <iostream>
using namespace std;
using namespace cv;
using namespace cuda;
using namespace dnn;
using namespace dnn_superres;
int upsample_and_save(DnnSuperResImpl sr,
std::filesystem::path file_path,
std::filesystem::path save_dir) {
std::cout<<"We are inside of upsample_and_save!" ;
Mat img = cv::imread(file_path.string()); //Read image
std::cout<<"We are inside of upsample_and_save and read the image" ;
Mat img_new ; //Container to store upsampled image
std::cout<<"We are inside of upsample_and_save and created img_new" ;
sr.upsample(img, img_new); //Upsample
std::cout<<"We upsampled" ;
cv::imwrite((save_dir / file_path.filename()).string(), img_new); //Save upscaled image
std::cout<<"We wrote the image!" ;
std::cout<< (save_dir / file_path.filename()).string();
return 0;
}
int main() {
// Parameters
string original_path = "C:/Users/Administrator/Desktop/Upscale/original"; //Path to folder containing original files
std::filesystem::path upscaled_path = "C:/Users/Administrator/Desktop/Upscale/upscaled"; //Folder to save upscaled images
std::vector<std::string> models {"lapsrn", "fsrcnn"};
std::vector<std::string> model_weights {"LapSRN_x8.pb", "FSRCNN_x2.pb"};
std::vector<int> scale_factors {8,2};
string model_dir = "C:/Users/Administrator/Desktop/Upscale/models/";
int model_choice = 1; //CHOOSE MODEL HERE (index in vector starting from 0)
std::vector<std::string> allowed {".jpg",".png"}; //Allowed image types
string model = models[model_choice]; //Model for dnn_superres
int scale_factor = scale_factors[model_choice]; //Scale factor
string model_path = model_dir + model_weights[model_choice]; //Model weights
DnnSuperResImpl sr; //Module instance
sr.readModel(model_path); //Read model weights
sr.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
sr.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
sr.setModel(model, scale_factor); //Set model and scale
std::cout<<"We set up OK!";
for (const auto &file : std::filesystem::directory_iterator(original_path)) {
std::cout<<"We are inside of the for loop!";
if (std::count(allowed.begin(), allowed.end(), file.path().extension())) {
upsample_and_save(sr, file.path(), upscaled_path);
std::cout<< "We hit upsample in the for loop!";
} else {
std::cout<<"The if statement has failed!";
}
std::cout<< "out of the loop";
return 0;
}
}
The issue I am having:
If I set the model to FSRCNN_x2.pb by adjusting model_choice to 1, the code works great! This model upscales an image by 2x. However, if I select LapSRN_x8.pb, the code will produce the following output:
PS C:\Users\Administrator\Desktop\Upscale\build\Release> ."C:/Users/Administrator/Desktop/Upscale/build/Release/upscale.exe"
We set up OK! We are inside of the for loop! We hit upsample in the for loop! We are inside of upsample_and_save! We are inside of upsample_and_save and read the image! We are inside of upsample_and_save and created img_new
PS C:\Users\Administrator\Desktop\Upscale\build\Release>
The code seems to hit the sr.upsample(img,img_new) and then completely crash!
I have attempted to fix this by commenting out
sr.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
sr.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
And after doing so, it appears that the code works fine. Does anyone know why this is happening?

when i use itk to read '.nii.gz' file ,reader->update give me a microsoft c++ error

when my program run reader->update(); i will be given a microsoft c++ error
Microsoft C++ 异常: itk::ImageFileReaderException,位于内存位置 0x00000000002CF0F8 处。
here is my entire code:
#include "itkImage.h"
#include <iostream>
#include<itkAndImageFilter.h>
#include <itkImageFileReader.h>
#include "itkImageFileWriter.h"
#include<string>
int main()
{
using PixelType = float;
constexpr unsigned int Dimension = 3;
const char* im_path = "C:/Users/Administrator/Desktop/test.nii.gz";
using ImageType = itk::Image<PixelType, Dimension>;
using ReaderType = itk::ImageFileReader<ImageType>;
ReaderType::Pointer reader = ReaderType::New();
reader->SetFileName(im_path);
std::string s = reader->GetFileName();
std::cout << s << std::endl;
ImageType::Pointer image = reader->GetOutput();
reader->Update();
return 0;
}
There is probably something wrong with how you compiled ITK, or how you link your program to ITK. Your program works on my computer without issue. I only changed the path to the file. Make sure the file is not damaged, by opening it in another program such as ITK-SNAP or 3D Slicer.

Convert C-Source image dump into original image

I have created with GIMP a C-Source image dump like the following:
/* GIMP RGBA C-Source image dump (example.c) */
static const struct {
guint width;
guint height;
guint bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
guint8 pixel_data[304 * 98 * 2 + 1];
} example= {
304, 98, 2,
"\206\061\206\061..... }
Is there a way to read this in GIMP again in order to get back the original image? because it doesn't seem possible.
Or does it exist a tool that can do this back-conversion?
EDITED
Following some suggestion I tried to write a simple C programme to make the reverse coversion ending up with something very similar to another code found on internet but both dont work:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "imgs_press.h"
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
using namespace std;
int main(int argc, char** argv) {
int fd;
char *name = "orignal_img.pnm";
fd = open(name, O_WRONLY | O_CREAT, 0644);
if (fd == -1) {
perror("open failed");
exit(1);
}
if (dup2(fd, 1) == -1) {
perror("dup2 failed");
exit(1);
}
// file descriptor 1, i.e. stdout, now points to the file
// "helloworld" which is open for writing
// You can now use printf which writes specifically to stdout
printf("P2\n");
printf("%d %d\n", press_high.width, press_high.height);
for(int x=0; x<press_high.width * press_high.height * 2; x++) {
printf("%d ", press_high.pixel_data[x]);
}
}
As suggested by n-1-8e9-wheres-my-share-m, maybe I need to manipulate the pixels usign the correct decode, but I have no idea how to do that, does anybody have other suggestions?
The image I got is indeed distorted:
Updated Answer
If you want to decode the RGB565 and write a NetPBM format PNM file without using ImageMagick, you can do this:
#include <stdint.h> /* for uint8_t */
#include <stdio.h> /* for printf */
/* tell compiler what those GIMP types are */
typedef int guint;
typedef uint8_t guint8;
#include <YOURGIMPIMAGE>
int main(){
int w = gimp_image.width;
int h = gimp_image.height;
int i;
uint16_t* RGB565p = (uint16_t*)&(gimp_image.pixel_data);
/* Print P3 PNM header on stdout */
printf("P3\n%d %d\n255\n",w, h);
/* Print RGB pixels, ASCII, one RGB pixel per line */
for(i=0;i<w*h;i++){
uint16_t RGB565 = *RGB565p++;
uint8_t r = (RGB565 & 0xf800) >> 8;
uint8_t g = (RGB565 & 0x07e0) >> 3;
uint8_t b = (RGB565 & 0x001f) << 3;
printf("%d %d %d\n", r, g ,b);
}
}
Compile with:
clang example.c
And run with:
./a.out > result.pnm
I have not tested it too extensively beyond your sample image, so you may want to make a test image with some reds, greens, blues and shades of grey to ensure that all my bit-twiddling is correct.
Original Answer
The easiest way to get your image back would be... to let ImageMagick do it.
So, take your C file and add a main() to it that simply writes the 304x98x2 bytes starting at &(example.pixel_data) to stdout:
Compile it with something like:
clang example.c -o program # or with GCC
gcc example.c -o program
Then run it, writing to a file for ImageMagick with:
./program > image.bin
And tell ImageMagick its size, type and where it is and what you want as a result:
magick -size 304x98 RGB565:image.bin result.png
I did a quick, not-too-thorough test of the following code and it worked fine for an image I generated with GIMP. Note it doesn't handle alpha/transparency but that could be added if necessary. Save it as program.c:
#include <unistd.h> /* for write() */
#include <stdint.h> /* for uint8_t */
/* tell compiler what those GIMP types are */
typedef int guint;
typedef uint8_t guint8;
<PASTE YOUR GIMP FILE HERE>
int main(){
/* Work out how many bytes to write */
int nbytes = example.width * example.height * 2;
/* Write on stdout for redirection to a file - may need to reopen in binary mode if on Windows */
write(1, &(example.pixel_data), nbytes);
}
If I run this with the file you provided via Google Drive I get:

Too few arguments to function 'int fclose(FILE*)'

Hello I am a beginner of C language for microprocessors. I want to read a ''.bmp'' file in order to apply line detection on it. I have declared a function to read the image. This error occurs when compile button is pushed:
#include "esp_camera.h"
#include "Arduino.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
#include "driver/rtc_io.h"
#include <EEPROM.h> // read and write from flash memory
#include <SPI.h>
void imageReader(const char *imgName,
int *height,
int *width,
int *bitdepth,
unsigned char *header,
unsigned char *_colortable,
unsigned char *buf
) // READ AN IMAGE
{
int i;
fs::FS &fs = SD_MMC; //
FILE *file;
file = fopen(imgName,"rb"); // read imgName file ( it is a picture in .bmp format )
if(!file){
Serial.printf("Unable to read image");
}
for(i=0 ; i<54 ; i++){
header[i]=getc(file);
}
*width = *(int * )& header[18]; // width information of the image
*height = *(int * )& header[22]; // height information of image
*bitdepth = *(int *)& header[28];
if(*bitdepth<=8){
fread(_colortable,sizeof(unsigned char),1024,file);
}
fread(buf,sizeof(unsigned char),( 1600 * 1200 ) ,file);
fclose();
}
It gives this error. too few arguments to function 'int fclose(FILE*)'
The fclose() function needs to know which file to close. You need to tell it that by supplying "file" as an argument. You want to use fclose(file).

error: no matching function for call to 'FaceDetector::FaceDetector(std::__cxx11::string)'

I am new to C++ and i am getting error like
error: no matching function for call to 'FaceDetector::FaceDetector(std::__cxx11::string)'
FaceDetector fd(string(DEFAULT_CASCADE_PATH));
and i am attaching my code and error log how to fix this please guide me
#define DEFAULT_CASCADE_PATH "cascades/haarcascade_frontalface_default.xml"
#define ORIGINALS_LIST "obama_raw/list"
#define OUTPUT_DIR "obama_faces"
#define OUTPUT_LIST "list"
#define FACE_SIZE Size(150,150)
#include <cstdlib>
#include <fstream>
#include "cv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "FaceDetector.h"
using namespace std;
using namespace cv;
void read_input_list(const string &list_path, vector<Mat> &images) {
ifstream file(list_path.c_str());
string path;
while (getline(file, path)) {
images.push_back(imread(path));
}
}
int main(int argc, char** argv) {
FaceDetector fd(string(DEFAULT_CASCADE_PATH));
vector<Mat> raw_faces;
ofstream out_list(format("%s/%s", OUTPUT_DIR, OUTPUT_LIST).c_str());
read_input_list(string(ORIGINALS_LIST), raw_faces);
int img_c = 0; //images counter
//now detect the faces in each of the raw images:
for (vector<Mat>::const_iterator raw_img = raw_faces.begin() ; raw_img != raw_faces.end() ; raw_img++){
vector<Rect> faces;
//detect faces in the image (there should be only one):
fd.findFacesInImage(*raw_img, faces);
//cut each face and write to disk:
for (vector<Rect>::const_iterator face = faces.begin() ; face != faces.end() ; face++){
int edge_size = max(face->width, face->height);
Rect square(face->x, face->y, edge_size, edge_size);
Mat face_img = (*raw_img)(square);
//resize:
resize(face_img, face_img, FACE_SIZE);
//write to disk:
string face_path = format("%s/%d.jpg", OUTPUT_DIR, img_c++);
imwrite(face_path,face_img);
out_list << face_path << endl;
}
}
out_list.close();
return 0;
}
and i am attaching my error log.Please can any one help.
Thanks in advance
Error : https://i.stack.imgur.com/RZXXK.jpg
From GCC 5, A new ABI is enabled by default. In that new ABI, std::__cxx11 namesapce was introduced.
According to your error message, It seems that your program and OpenCV library you want to link with were build with different GCC version, which made incompatible binary.
For more information, you can read the following page:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html