vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
@@ -0,0 +1,35 @@
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
if(WIN32)
|
||||
# windows cmake internal lookups are broken for now
|
||||
# will lookup for headers and shared libs given HDF_DIR env
|
||||
find_path(HDF5_INCLUDE_DIRS hdf5.h HINTS "$ENV{HDF5_DIR}\\..\\include")
|
||||
find_library(HDF5_C_LIBRARY NAMES hdf5 HINTS "$ENV{HDF5_DIR}\\..\\lib")
|
||||
if(HDF5_INCLUDE_DIRS AND HDF5_C_LIBRARY)
|
||||
set(HDF5_FOUND "YES")
|
||||
set(HDF5_LIBRARIES ${HDF5_C_LIBRARY})
|
||||
mark_as_advanced(HDF5_LIBRARIES)
|
||||
mark_as_advanced(HDF5_C_LIBRARY)
|
||||
mark_as_advanced(HDF5_INCLUDE_DIRS)
|
||||
add_definitions(-DH5_BUILT_AS_DYNAMIC_LIB -D_HDF5USEDLL_)
|
||||
else()
|
||||
set(HDF5_FOUND "NO")
|
||||
endif()
|
||||
else()
|
||||
if(NOT CMAKE_CROSSCOMPILING) # iOS build should not reuse OSX package
|
||||
find_package(HDF5)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT HDF5_FOUND)
|
||||
ocv_module_disable(hdf) # no return
|
||||
endif()
|
||||
|
||||
set(HAVE_HDF5 1)
|
||||
|
||||
ocv_warnings_disable(CMAKE_CXX_FLAGS -Winvalid-offsetof)
|
||||
|
||||
set(the_description "Hierarchical Data Format I/O")
|
||||
ocv_define_module(hdf opencv_core WRAP python)
|
||||
ocv_target_link_libraries(${the_module} ${HDF5_LIBRARIES})
|
||||
ocv_include_directories(${HDF5_INCLUDE_DIRS})
|
||||
@@ -0,0 +1,4 @@
|
||||
Hierarchical Data Format (hdf) I/O
|
||||
==================================
|
||||
|
||||
The module contains I/O routines for Hierarchical Data Format: https://en.m.wikipedia.org/wiki/Hierarchical_Data_Format meant to store large amounts of data. This module does not implement the specs from scratch, it's a wrapper on top of libhdf5, which should be pre-installed by the user.
|
||||
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,55 @@
|
||||
/*********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2015
|
||||
* Balint Cristian <cristian dot balint at gmail dot com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef __OPENCV_HDF_HPP__
|
||||
#define __OPENCV_HDF_HPP__
|
||||
|
||||
#include "opencv2/hdf/hdf5.hpp"
|
||||
|
||||
/** @defgroup hdf Hierarchical Data Format I/O routines
|
||||
|
||||
This module provides storage routines for Hierarchical Data Format objects.
|
||||
|
||||
@{
|
||||
@defgroup hdf5 Hierarchical Data Format version 5
|
||||
|
||||
Hierarchical Data Format version 5
|
||||
--------------------------------------------------------
|
||||
|
||||
In order to use it, the hdf5 library has to be installed, which
|
||||
means cmake should find it using `find_package(HDF5)`.
|
||||
@}
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,808 @@
|
||||
/*********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2015
|
||||
* Balint Cristian <cristian dot balint at gmail dot com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef __OPENCV_HDF5_HPP__
|
||||
#define __OPENCV_HDF5_HPP__
|
||||
|
||||
#include <vector>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
namespace cv
|
||||
{
|
||||
namespace hdf
|
||||
{
|
||||
using namespace std;
|
||||
|
||||
//! @addtogroup hdf5
|
||||
//! @{
|
||||
|
||||
|
||||
/** @brief Hierarchical Data Format version 5 interface.
|
||||
|
||||
Notice that this module is compiled only when hdf5 is correctly installed.
|
||||
|
||||
*/
|
||||
class CV_EXPORTS_W HDF5
|
||||
{
|
||||
public:
|
||||
|
||||
CV_WRAP enum
|
||||
{
|
||||
H5_UNLIMITED = -1, //!< The dimension size is unlimited, @sa dscreate()
|
||||
H5_NONE = -1, //!< No compression, @sa dscreate()
|
||||
H5_GETDIMS = 100, //!< Get the dimension information of a dataset. @sa dsgetsize()
|
||||
H5_GETMAXDIMS = 101, //!< Get the maximum dimension information of a dataset. @sa dsgetsize()
|
||||
H5_GETCHUNKDIMS = 102, //!< Get the chunk sizes of a dataset. @sa dsgetsize()
|
||||
};
|
||||
|
||||
virtual ~HDF5() {}
|
||||
|
||||
/** @brief Close and release hdf5 object.
|
||||
*/
|
||||
CV_WRAP virtual void close( ) = 0;
|
||||
|
||||
/** @brief Create a group.
|
||||
@param grlabel specify the hdf5 group label.
|
||||
|
||||
Create a hdf5 group with default properties. The group is closed automatically after creation.
|
||||
|
||||
@note Groups are useful for better organising multiple datasets. It is possible to create subgroups within any group.
|
||||
Existence of a particular group can be checked using hlexists(). In case of subgroups, a label would be e.g: 'Group1/SubGroup1'
|
||||
where SubGroup1 is within the root group Group1. Before creating a subgroup, its parent group MUST be created.
|
||||
|
||||
- In this example, Group1 will have one subgroup called SubGroup1:
|
||||
|
||||
@snippet samples/create_groups.cpp create_group
|
||||
|
||||
The corresponding result visualized using the HDFView tool is
|
||||
|
||||

|
||||
|
||||
@note When a dataset is created with dscreate() or kpcreate(), it can be created within a group by specifying the
|
||||
full path within the label. In our example, it would be: 'Group1/SubGroup1/MyDataSet'. It is not thread safe.
|
||||
*/
|
||||
CV_WRAP virtual void grcreate( const String& grlabel ) = 0;
|
||||
|
||||
/** @brief Check if label exists or not.
|
||||
@param label specify the hdf5 dataset label.
|
||||
|
||||
Returns **true** if dataset exists, and **false** otherwise.
|
||||
|
||||
@note Checks if dataset, group or other object type (hdf5 link) exists under the label name. It is thread safe.
|
||||
*/
|
||||
CV_WRAP virtual bool hlexists( const String& label ) const = 0;
|
||||
|
||||
/**
|
||||
* Check whether a given attribute exits or not in the root group.
|
||||
*
|
||||
* @param atlabel the attribute name to be checked.
|
||||
* @return true if the attribute exists, false otherwise.
|
||||
*
|
||||
* @sa atdelete, atwrite, atread
|
||||
*/
|
||||
CV_WRAP virtual bool atexists(const String& atlabel) const = 0;
|
||||
|
||||
/**
|
||||
* Delete an attribute from the root group.
|
||||
*
|
||||
* @param atlabel the attribute to be deleted.
|
||||
*
|
||||
* @note CV_Error() is called if the given attribute does not exist. Use atexists()
|
||||
* to check whether it exists or not beforehand.
|
||||
*
|
||||
* @sa atexists, atwrite, atread
|
||||
*/
|
||||
CV_WRAP virtual void atdelete(const String& atlabel) = 0;
|
||||
|
||||
/**
|
||||
* Write an attribute inside the root group.
|
||||
*
|
||||
* @param value attribute value.
|
||||
* @param atlabel attribute name.
|
||||
*
|
||||
* The following example demonstrates how to write an attribute of type cv::String:
|
||||
*
|
||||
* @snippet samples/read_write_attributes.cpp snippets_write_str
|
||||
*
|
||||
* @note CV_Error() is called if the given attribute already exists. Use atexists()
|
||||
* to check whether it exists or not beforehand. And use atdelete() to delete
|
||||
* it if it already exists.
|
||||
*
|
||||
* @sa atexists, atdelete, atread
|
||||
*/
|
||||
CV_WRAP virtual void atwrite(const int value, const String& atlabel) = 0;
|
||||
|
||||
/**
|
||||
* Read an attribute from the root group.
|
||||
*
|
||||
* @param value address where the attribute is read into
|
||||
* @param atlabel attribute name
|
||||
*
|
||||
* The following example demonstrates how to read an attribute of type cv::String:
|
||||
*
|
||||
* @snippet samples/read_write_attributes.cpp snippets_read_str
|
||||
*
|
||||
* @note The attribute MUST exist, otherwise CV_Error() is called. Use atexists()
|
||||
* to check if it exists beforehand.
|
||||
*
|
||||
* @sa atexists, atdelete, atwrite
|
||||
*/
|
||||
CV_WRAP virtual void atread(int* value, const String& atlabel) = 0;
|
||||
|
||||
/** @overload */
|
||||
CV_WRAP virtual void atwrite(const double value, const String& atlabel) = 0;
|
||||
|
||||
/** @overload */
|
||||
CV_WRAP virtual void atread(double* value, const String& atlabel) = 0;
|
||||
|
||||
/** @overload */
|
||||
CV_WRAP virtual void atwrite(const String& value, const String& atlabel) = 0;
|
||||
|
||||
/** @overload */
|
||||
CV_WRAP virtual void atread(String* value, const String& atlabel) = 0;
|
||||
|
||||
/**
|
||||
* Write an attribute into the root group.
|
||||
*
|
||||
* @param value attribute value. Currently, only n-d continuous multi-channel arrays are supported.
|
||||
* @param atlabel attribute name.
|
||||
*
|
||||
* @note CV_Error() is called if the given attribute already exists. Use atexists()
|
||||
* to check whether it exists or not beforehand. And use atdelete() to delete
|
||||
* it if it already exists.
|
||||
*
|
||||
* @sa atexists, atdelete, atread.
|
||||
*/
|
||||
CV_WRAP virtual void atwrite(InputArray value, const String& atlabel) = 0;
|
||||
|
||||
/**
|
||||
* Read an attribute from the root group.
|
||||
*
|
||||
* @param value attribute value. Currently, only n-d continuous multi-channel arrays are supported.
|
||||
* @param atlabel attribute name.
|
||||
*
|
||||
* @note The attribute MUST exist, otherwise CV_Error() is called. Use atexists()
|
||||
* to check if it exists beforehand.
|
||||
*
|
||||
* @sa atexists, atdelete, atwrite
|
||||
*/
|
||||
CV_WRAP virtual void atread(OutputArray value, const String& atlabel) = 0;
|
||||
|
||||
/** @overload */
|
||||
CV_WRAP virtual void dscreate( const int rows, const int cols, const int type,
|
||||
const String& dslabel ) const = 0;
|
||||
/** @overload */
|
||||
CV_WRAP virtual void dscreate( const int rows, const int cols, const int type,
|
||||
const String& dslabel, const int compresslevel ) const = 0;
|
||||
/** @overload */
|
||||
CV_WRAP virtual void dscreate( const int rows, const int cols, const int type,
|
||||
const String& dslabel, const int compresslevel, const vector<int>& dims_chunks ) const = 0;
|
||||
/** @brief Create and allocate storage for two dimensional single or multi channel dataset.
|
||||
@param rows declare amount of rows
|
||||
@param cols declare amount of columns
|
||||
@param type type to be used, e.g, CV_8UC3, CV_32FC1 and etc.
|
||||
@param dslabel specify the hdf5 dataset label. Existing dataset label will cause an error.
|
||||
@param compresslevel specify the compression level 0-9 to be used, H5_NONE is the default value and means no compression.
|
||||
The value 0 also means no compression.
|
||||
A value 9 indicating the best compression ration. Note
|
||||
that a higher compression level indicates a higher computational cost. It relies
|
||||
on GNU gzip for compression.
|
||||
@param dims_chunks each array member specifies the chunking size to be used for block I/O,
|
||||
by default NULL means none at all.
|
||||
|
||||
@note If the dataset already exists, an exception will be thrown (CV_Error() is called).
|
||||
|
||||
- Existence of the dataset can be checked using hlexists(), see in this example:
|
||||
@code{.cpp}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// create space for 100x50 CV_64FC2 matrix
|
||||
if ( ! h5io->hlexists( "hilbert" ) )
|
||||
h5io->dscreate( 100, 50, CV_64FC2, "hilbert" );
|
||||
else
|
||||
printf("DS already created, skipping\n" );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
@note Activating compression requires internal chunking. Chunking can significantly improve access
|
||||
speed both at read and write time, especially for windowed access logic that shifts offset inside dataset.
|
||||
If no custom chunking is specified, the default one will be invoked by the size of the **whole** dataset
|
||||
as a single big chunk of data.
|
||||
|
||||
- See example of level 9 compression using internal default chunking:
|
||||
@code{.cpp}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// create level 9 compressed space for CV_64FC2 matrix
|
||||
if ( ! h5io->hlexists( "hilbert", 9 ) )
|
||||
h5io->dscreate( 100, 50, CV_64FC2, "hilbert", 9 );
|
||||
else
|
||||
printf("DS already created, skipping\n" );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
@note A value of H5_UNLIMITED for **rows** or **cols** or both means **unlimited** data on the specified dimension,
|
||||
thus, it is possible to expand anytime such a dataset on row, col or on both directions. Presence of H5_UNLIMITED on any
|
||||
dimension **requires** to define custom chunking. No default chunking will be defined in the unlimited scenario since
|
||||
default size on that dimension will be zero, and will grow once dataset is written. Writing into a dataset that has
|
||||
H5_UNLIMITED on some of its dimensions requires dsinsert() that allows growth on unlimited dimensions, instead of dswrite()
|
||||
that allows to write only in predefined data space.
|
||||
|
||||
- Example below shows no compression but unlimited dimension on cols using 100x100 internal chunking:
|
||||
@code{.cpp}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// create level 9 compressed space for CV_64FC2 matrix
|
||||
int chunks[2] = { 100, 100 };
|
||||
h5io->dscreate( 100, cv::hdf::HDF5::H5_UNLIMITED, CV_64FC2, "hilbert", cv::hdf::HDF5::H5_NONE, chunks );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
@note It is **not** thread safe, it must be called only once at dataset creation, otherwise an exception will occur.
|
||||
Multiple datasets inside a single hdf5 file are allowed.
|
||||
*/
|
||||
CV_WRAP virtual void dscreate( const int rows, const int cols, const int type,
|
||||
const String& dslabel, const int compresslevel, const int* dims_chunks ) const = 0;
|
||||
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dscreate( const int n_dims, const int* sizes, const int type,
|
||||
const String& dslabel ) const = 0;
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dscreate( const int n_dims, const int* sizes, const int type,
|
||||
const String& dslabel, const int compresslevel ) const = 0;
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dscreate( const vector<int>& sizes, const int type,
|
||||
const String& dslabel, const int compresslevel = HDF5::H5_NONE,
|
||||
const vector<int>& dims_chunks = vector<int>() ) const = 0;
|
||||
/** @brief Create and allocate storage for n-dimensional dataset, single or multichannel type.
|
||||
@param n_dims declare number of dimensions
|
||||
@param sizes array containing sizes for each dimensions
|
||||
@param type type to be used, e.g., CV_8UC3, CV_32FC1, etc.
|
||||
@param dslabel specify the hdf5 dataset label. Existing dataset label will cause an error.
|
||||
@param compresslevel specify the compression level 0-9 to be used, H5_NONE is the default value and means no compression.
|
||||
The value 0 also means no compression.
|
||||
A value 9 indicating the best compression ration. Note
|
||||
that a higher compression level indicates a higher computational cost. It relies
|
||||
on GNU gzip for compression.
|
||||
@param dims_chunks each array member specifies chunking sizes to be used for block I/O,
|
||||
by default NULL means none at all.
|
||||
@note If the dataset already exists, an exception will be thrown. Existence of the dataset can be checked
|
||||
using hlexists().
|
||||
|
||||
- See example below that creates a 6 dimensional storage space:
|
||||
@code{.cpp}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// create space for 6 dimensional CV_64FC2 matrix
|
||||
if ( ! h5io->hlexists( "nddata" ) )
|
||||
int n_dims = 5;
|
||||
int dsdims[n_dims] = { 100, 100, 20, 10, 5, 5 };
|
||||
h5io->dscreate( n_dims, sizes, CV_64FC2, "nddata" );
|
||||
else
|
||||
printf("DS already created, skipping\n" );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
@note Activating compression requires internal chunking. Chunking can significantly improve access
|
||||
speed both at read and write time, especially for windowed access logic that shifts offset inside dataset.
|
||||
If no custom chunking is specified, the default one will be invoked by the size of **whole** dataset
|
||||
as single big chunk of data.
|
||||
|
||||
- See example of level 0 compression (shallow) using chunking against the first
|
||||
dimension, thus storage will consists of 100 chunks of data:
|
||||
@code{.cpp}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// create space for 6 dimensional CV_64FC2 matrix
|
||||
if ( ! h5io->hlexists( "nddata" ) )
|
||||
int n_dims = 5;
|
||||
int dsdims[n_dims] = { 100, 100, 20, 10, 5, 5 };
|
||||
int chunks[n_dims] = { 1, 100, 20, 10, 5, 5 };
|
||||
h5io->dscreate( n_dims, dsdims, CV_64FC2, "nddata", 0, chunks );
|
||||
else
|
||||
printf("DS already created, skipping\n" );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
@note A value of H5_UNLIMITED inside the **sizes** array means **unlimited** data on that dimension, thus it is
|
||||
possible to expand anytime such dataset on those unlimited directions. Presence of H5_UNLIMITED on any dimension
|
||||
**requires** to define custom chunking. No default chunking will be defined in unlimited scenario since the default size
|
||||
on that dimension will be zero, and will grow once dataset is written. Writing into dataset that has H5_UNLIMITED on
|
||||
some of its dimension requires dsinsert() instead of dswrite() that allows growth on unlimited dimension instead of
|
||||
dswrite() that allows to write only in predefined data space.
|
||||
|
||||
- Example below shows a 3 dimensional dataset using no compression with all unlimited sizes and one unit chunking:
|
||||
@code{.cpp}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
int n_dims = 3;
|
||||
int chunks[n_dims] = { 1, 1, 1 };
|
||||
int dsdims[n_dims] = { cv::hdf::HDF5::H5_UNLIMITED, cv::hdf::HDF5::H5_UNLIMITED, cv::hdf::HDF5::H5_UNLIMITED };
|
||||
h5io->dscreate( n_dims, dsdims, CV_64FC2, "nddata", cv::hdf::HDF5::H5_NONE, chunks );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
*/
|
||||
CV_WRAP virtual void dscreate( const int n_dims, const int* sizes, const int type,
|
||||
const String& dslabel, const int compresslevel, const int* dims_chunks ) const = 0;
|
||||
|
||||
/** @brief Fetch dataset sizes
|
||||
@param dslabel specify the hdf5 dataset label to be measured.
|
||||
@param dims_flag will fetch dataset dimensions on H5_GETDIMS, dataset maximum dimensions on H5_GETMAXDIMS,
|
||||
and chunk sizes on H5_GETCHUNKDIMS.
|
||||
|
||||
Returns vector object containing sizes of dataset on each dimensions.
|
||||
|
||||
@note Resulting vector size will match the amount of dataset dimensions. By default H5_GETDIMS will return
|
||||
actual dataset dimensions. Using H5_GETMAXDIM flag will get maximum allowed dimension which normally match
|
||||
actual dataset dimension but can hold H5_UNLIMITED value if dataset was prepared in **unlimited** mode on
|
||||
some of its dimension. It can be useful to check existing dataset dimensions before overwrite it as whole or subset.
|
||||
Trying to write with oversized source data into dataset target will thrown exception. The H5_GETCHUNKDIMS will
|
||||
return the dimension of chunk if dataset was created with chunking options otherwise returned vector size
|
||||
will be zero.
|
||||
*/
|
||||
CV_WRAP virtual vector<int> dsgetsize( const String& dslabel, int dims_flag = HDF5::H5_GETDIMS ) const = 0;
|
||||
|
||||
/** @brief Fetch dataset type
|
||||
@param dslabel specify the hdf5 dataset label to be checked.
|
||||
|
||||
Returns the stored matrix type. This is an identifier compatible with the CvMat type system,
|
||||
like e.g. CV_16SC5 (16-bit signed 5-channel array), and so on.
|
||||
|
||||
@note Result can be parsed with CV_MAT_CN() to obtain amount of channels and CV_MAT_DEPTH() to obtain native cvdata type.
|
||||
It is thread safe.
|
||||
*/
|
||||
CV_WRAP virtual int dsgettype( const String& dslabel ) const = 0;
|
||||
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dswrite( InputArray Array, const String& dslabel ) const = 0;
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dswrite( InputArray Array, const String& dslabel,
|
||||
const int* dims_offset ) const = 0;
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dswrite( InputArray Array, const String& dslabel,
|
||||
const vector<int>& dims_offset,
|
||||
const vector<int>& dims_counts = vector<int>() ) const = 0;
|
||||
/** @brief Write or overwrite a Mat object into specified dataset of hdf5 file.
|
||||
@param Array specify Mat data array to be written.
|
||||
@param dslabel specify the target hdf5 dataset label.
|
||||
@param dims_offset each array member specify the offset location
|
||||
over dataset's each dimensions from where InputArray will be (over)written into dataset.
|
||||
@param dims_counts each array member specifies the amount of data over dataset's
|
||||
each dimensions from InputArray that will be written into dataset.
|
||||
|
||||
Writes Mat object into targeted dataset.
|
||||
|
||||
@note If dataset is not created and does not exist it will be created **automatically**. Only Mat is supported and
|
||||
it must be **continuous**. It is thread safe but it is recommended that writes to happen over separate non-overlapping
|
||||
regions. Multiple datasets can be written inside a single hdf5 file.
|
||||
|
||||
- Example below writes a 100x100 CV_64FC2 matrix into a dataset. No dataset pre-creation required. If routine
|
||||
is called multiple times dataset will be just overwritten:
|
||||
@code{.cpp}
|
||||
// dual channel hilbert matrix
|
||||
cv::Mat H(100, 100, CV_64FC2);
|
||||
for(int i = 0; i < H.rows; i++)
|
||||
for(int j = 0; j < H.cols; j++)
|
||||
{
|
||||
H.at<cv::Vec2d>(i,j)[0] = 1./(i+j+1);
|
||||
H.at<cv::Vec2d>(i,j)[1] = -1./(i+j+1);
|
||||
count++;
|
||||
}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// write / overwrite dataset
|
||||
h5io->dswrite( H, "hilbert" );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
- Example below writes a smaller 50x100 matrix into 100x100 compressed space optimised by two 50x100 chunks.
|
||||
Matrix is written twice into first half (0->50) and second half (50->100) of data space using offset.
|
||||
@code{.cpp}
|
||||
// dual channel hilbert matrix
|
||||
cv::Mat H(50, 100, CV_64FC2);
|
||||
for(int i = 0; i < H.rows; i++)
|
||||
for(int j = 0; j < H.cols; j++)
|
||||
{
|
||||
H.at<cv::Vec2d>(i,j)[0] = 1./(i+j+1);
|
||||
H.at<cv::Vec2d>(i,j)[1] = -1./(i+j+1);
|
||||
count++;
|
||||
}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// optimise dataset by two chunks
|
||||
int chunks[2] = { 50, 100 };
|
||||
// create 100x100 CV_64FC2 compressed space
|
||||
h5io->dscreate( 100, 100, CV_64FC2, "hilbert", 9, chunks );
|
||||
// write into first half
|
||||
int offset1[2] = { 0, 0 };
|
||||
h5io->dswrite( H, "hilbert", offset1 );
|
||||
// write into second half
|
||||
int offset2[2] = { 50, 0 };
|
||||
h5io->dswrite( H, "hilbert", offset2 );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
*/
|
||||
CV_WRAP virtual void dswrite( InputArray Array, const String& dslabel,
|
||||
const int* dims_offset, const int* dims_counts ) const = 0;
|
||||
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dsinsert( InputArray Array, const String& dslabel ) const = 0;
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dsinsert( InputArray Array,
|
||||
const String& dslabel, const int* dims_offset ) const = 0;
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dsinsert( InputArray Array,
|
||||
const String& dslabel, const vector<int>& dims_offset,
|
||||
const vector<int>& dims_counts = vector<int>() ) const = 0;
|
||||
/** @brief Insert or overwrite a Mat object into specified dataset and auto expand dataset size if **unlimited** property allows.
|
||||
@param Array specify Mat data array to be written.
|
||||
@param dslabel specify the target hdf5 dataset label.
|
||||
@param dims_offset each array member specify the offset location
|
||||
over dataset's each dimensions from where InputArray will be (over)written into dataset.
|
||||
@param dims_counts each array member specify the amount of data over dataset's
|
||||
each dimensions from InputArray that will be written into dataset.
|
||||
|
||||
Writes Mat object into targeted dataset and **autoexpand** dataset dimension if allowed.
|
||||
|
||||
@note Unlike dswrite(), datasets are **not** created **automatically**. Only Mat is supported and it must be **continuous**.
|
||||
If dsinsert() happens over outer regions of dataset dimensions and on that dimension of dataset is in **unlimited** mode then
|
||||
dataset is expanded, otherwise exception is thrown. To create datasets with **unlimited** property on specific or more
|
||||
dimensions see dscreate() and the optional H5_UNLIMITED flag at creation time. It is not thread safe over same dataset
|
||||
but multiple datasets can be merged inside a single hdf5 file.
|
||||
|
||||
- Example below creates **unlimited** rows x 100 cols and expands rows 5 times with dsinsert() using single 100x100 CV_64FC2
|
||||
over the dataset. Final size will have 5x100 rows and 100 cols, reflecting H matrix five times over row's span. Chunks size is
|
||||
100x100 just optimized against the H matrix size having compression disabled. If routine is called multiple times dataset will be
|
||||
just overwritten:
|
||||
@code{.cpp}
|
||||
// dual channel hilbert matrix
|
||||
cv::Mat H(50, 100, CV_64FC2);
|
||||
for(int i = 0; i < H.rows; i++)
|
||||
for(int j = 0; j < H.cols; j++)
|
||||
{
|
||||
H.at<cv::Vec2d>(i,j)[0] = 1./(i+j+1);
|
||||
H.at<cv::Vec2d>(i,j)[1] = -1./(i+j+1);
|
||||
count++;
|
||||
}
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// optimise dataset by chunks
|
||||
int chunks[2] = { 100, 100 };
|
||||
// create Unlimited x 100 CV_64FC2 space
|
||||
h5io->dscreate( cv::hdf::HDF5::H5_UNLIMITED, 100, CV_64FC2, "hilbert", cv::hdf::HDF5::H5_NONE, chunks );
|
||||
// write into first half
|
||||
int offset[2] = { 0, 0 };
|
||||
for ( int t = 0; t < 5; t++ )
|
||||
{
|
||||
offset[0] += 100 * t;
|
||||
h5io->dsinsert( H, "hilbert", offset );
|
||||
}
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
*/
|
||||
CV_WRAP virtual void dsinsert( InputArray Array, const String& dslabel,
|
||||
const int* dims_offset, const int* dims_counts ) const = 0;
|
||||
|
||||
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dsread( OutputArray Array, const String& dslabel ) const = 0;
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dsread( OutputArray Array,
|
||||
const String& dslabel, const int* dims_offset ) const = 0;
|
||||
/* @overload */
|
||||
CV_WRAP virtual void dsread( OutputArray Array, const String& dslabel,
|
||||
const vector<int>& dims_offset,
|
||||
const vector<int>& dims_counts = vector<int>() ) const = 0;
|
||||
/** @brief Read specific dataset from hdf5 file into Mat object.
|
||||
@param Array Mat container where data reads will be returned.
|
||||
@param dslabel specify the source hdf5 dataset label.
|
||||
@param dims_offset each array member specify the offset location over
|
||||
each dimensions from where dataset starts to read into OutputArray.
|
||||
@param dims_counts each array member specify the amount over dataset's each
|
||||
dimensions of dataset to read into OutputArray.
|
||||
|
||||
Reads out Mat object reflecting the stored dataset.
|
||||
|
||||
@note If hdf5 file does not exist an exception will be thrown. Use hlexists() to check dataset presence.
|
||||
It is thread safe.
|
||||
|
||||
- Example below reads a dataset:
|
||||
@code{.cpp}
|
||||
// open hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// blank Mat container
|
||||
cv::Mat H;
|
||||
// read hibert dataset
|
||||
h5io->read( H, "hilbert" );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
- Example below perform read of 3x5 submatrix from second row and third element.
|
||||
@code{.cpp}
|
||||
// open hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// blank Mat container
|
||||
cv::Mat H;
|
||||
int offset[2] = { 1, 2 };
|
||||
int counts[2] = { 3, 5 };
|
||||
// read hibert dataset
|
||||
h5io->read( H, "hilbert", offset, counts );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
*/
|
||||
CV_WRAP virtual void dsread( OutputArray Array, const String& dslabel,
|
||||
const int* dims_offset, const int* dims_counts ) const = 0;
|
||||
|
||||
/** @brief Fetch keypoint dataset size
|
||||
@param kplabel specify the hdf5 dataset label to be measured.
|
||||
@param dims_flag will fetch dataset dimensions on H5_GETDIMS, and dataset maximum dimensions on H5_GETMAXDIMS.
|
||||
|
||||
Returns size of keypoints dataset.
|
||||
|
||||
@note Resulting size will match the amount of keypoints. By default H5_GETDIMS will return actual dataset dimension.
|
||||
Using H5_GETMAXDIM flag will get maximum allowed dimension which normally match actual dataset dimension but can hold
|
||||
H5_UNLIMITED value if dataset was prepared in **unlimited** mode. It can be useful to check existing dataset dimension
|
||||
before overwrite it as whole or subset. Trying to write with oversized source data into dataset target will thrown
|
||||
exception. The H5_GETCHUNKDIMS will return the dimension of chunk if dataset was created with chunking options otherwise
|
||||
returned vector size will be zero.
|
||||
*/
|
||||
CV_WRAP virtual int kpgetsize( const String& kplabel, int dims_flag = HDF5::H5_GETDIMS ) const = 0;
|
||||
|
||||
/** @brief Create and allocate special storage for cv::KeyPoint dataset.
|
||||
@param size declare fixed number of KeyPoints
|
||||
@param kplabel specify the hdf5 dataset label, any existing dataset with the same label will be overwritten.
|
||||
@param compresslevel specify the compression level 0-9 to be used, H5_NONE is default and means no compression.
|
||||
@param chunks each array member specifies chunking sizes to be used for block I/O,
|
||||
H5_NONE is default and means no compression.
|
||||
@note If the dataset already exists an exception will be thrown. Existence of the dataset can be checked
|
||||
using hlexists().
|
||||
|
||||
- See example below that creates space for 100 keypoints in the dataset:
|
||||
@code{.cpp}
|
||||
// open hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
if ( ! h5io->hlexists( "keypoints" ) )
|
||||
h5io->kpcreate( 100, "keypoints" );
|
||||
else
|
||||
printf("DS already created, skipping\n" );
|
||||
@endcode
|
||||
|
||||
@note A value of H5_UNLIMITED for **size** means **unlimited** keypoints, thus is possible to expand anytime such
|
||||
dataset by adding or inserting. Presence of H5_UNLIMITED **require** to define custom chunking. No default chunking
|
||||
will be defined in unlimited scenario since default size on that dimension will be zero, and will grow once dataset
|
||||
is written. Writing into dataset that have H5_UNLIMITED on some of its dimension requires kpinsert() that allow
|
||||
growth on unlimited dimension instead of kpwrite() that allows to write only in predefined data space.
|
||||
|
||||
- See example below that creates unlimited space for keypoints chunking size of 100 but no compression:
|
||||
@code{.cpp}
|
||||
// open hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
if ( ! h5io->hlexists( "keypoints" ) )
|
||||
h5io->kpcreate( cv::hdf::HDF5::H5_UNLIMITED, "keypoints", cv::hdf::HDF5::H5_NONE, 100 );
|
||||
else
|
||||
printf("DS already created, skipping\n" );
|
||||
@endcode
|
||||
*/
|
||||
virtual void kpcreate( const int size, const String& kplabel,
|
||||
const int compresslevel = H5_NONE, const int chunks = H5_NONE ) const = 0;
|
||||
|
||||
/** @brief Write or overwrite list of KeyPoint into specified dataset of hdf5 file.
|
||||
@param keypoints specify keypoints data list to be written.
|
||||
@param kplabel specify the target hdf5 dataset label.
|
||||
@param offset specify the offset location on dataset from where keypoints will be (over)written into dataset.
|
||||
@param counts specify the amount of keypoints that will be written into dataset.
|
||||
|
||||
Writes vector<KeyPoint> object into targeted dataset.
|
||||
|
||||
@note If dataset is not created and does not exist it will be created **automatically**. It is thread safe but
|
||||
it is recommended that writes to happen over separate non overlapping regions. Multiple datasets can be written
|
||||
inside single hdf5 file.
|
||||
|
||||
- Example below writes a 100 keypoints into a dataset. No dataset precreation required. If routine is called multiple
|
||||
times dataset will be just overwritten:
|
||||
@code{.cpp}
|
||||
// generate 100 dummy keypoints
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
for(int i = 0; i < 100; i++)
|
||||
keypoints.push_back( cv::KeyPoint(i, -i, 1, -1, 0, 0, -1) );
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// write / overwrite dataset
|
||||
h5io->kpwrite( keypoints, "keypoints" );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
- Example below uses smaller set of 50 keypoints and writes into compressed space of 100 keypoints optimised by 10 chunks.
|
||||
Same keypoint set is written three times, first into first half (0->50) and at second half (50->75) then into remaining slots
|
||||
(75->99) of data space using offset and count parameters to settle the window for write access.If routine is called multiple times
|
||||
dataset will be just overwritten:
|
||||
@code{.cpp}
|
||||
// generate 50 dummy keypoints
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
for(int i = 0; i < 50; i++)
|
||||
keypoints.push_back( cv::KeyPoint(i, -i, 1, -1, 0, 0, -1) );
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// create maximum compressed space of size 100 with chunk size 10
|
||||
h5io->kpcreate( 100, "keypoints", 9, 10 );
|
||||
// write into first half
|
||||
h5io->kpwrite( keypoints, "keypoints", 0 );
|
||||
// write first 25 keypoints into second half
|
||||
h5io->kpwrite( keypoints, "keypoints", 50, 25 );
|
||||
// write first 25 keypoints into remained space of second half
|
||||
h5io->kpwrite( keypoints, "keypoints", 75, 25 );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
*/
|
||||
virtual void kpwrite( const vector<KeyPoint> keypoints, const String& kplabel,
|
||||
const int offset = H5_NONE, const int counts = H5_NONE ) const = 0;
|
||||
|
||||
/** @brief Insert or overwrite list of KeyPoint into specified dataset and autoexpand dataset size if **unlimited** property allows.
|
||||
@param keypoints specify keypoints data list to be written.
|
||||
@param kplabel specify the target hdf5 dataset label.
|
||||
@param offset specify the offset location on dataset from where keypoints will be (over)written into dataset.
|
||||
@param counts specify the amount of keypoints that will be written into dataset.
|
||||
|
||||
Writes vector<KeyPoint> object into targeted dataset and **autoexpand** dataset dimension if allowed.
|
||||
|
||||
@note Unlike kpwrite(), datasets are **not** created **automatically**. If dsinsert() happen over outer region of dataset
|
||||
and dataset has been created in **unlimited** mode then dataset is expanded, otherwise exception is thrown. To create datasets
|
||||
with **unlimited** property see kpcreate() and the optional H5_UNLIMITED flag at creation time. It is not thread safe over same
|
||||
dataset but multiple datasets can be merged inside single hdf5 file.
|
||||
|
||||
- Example below creates **unlimited** space for keypoints storage, and inserts a list of 10 keypoints ten times into that space.
|
||||
Final dataset will have 100 keypoints. Chunks size is 10 just optimized against list of keypoints. If routine is called multiple
|
||||
times dataset will be just overwritten:
|
||||
@code{.cpp}
|
||||
// generate 10 dummy keypoints
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
for(int i = 0; i < 10; i++)
|
||||
keypoints.push_back( cv::KeyPoint(i, -i, 1, -1, 0, 0, -1) );
|
||||
// open / autocreate hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// create unlimited size space with chunk size of 10
|
||||
h5io->kpcreate( cv::hdf::HDF5::H5_UNLIMITED, "keypoints", -1, 10 );
|
||||
// insert 10 times same 10 keypoints
|
||||
for(int i = 0; i < 10; i++)
|
||||
h5io->kpinsert( keypoints, "keypoints", i * 10 );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
*/
|
||||
virtual void kpinsert( const vector<KeyPoint> keypoints, const String& kplabel,
|
||||
const int offset = H5_NONE, const int counts = H5_NONE ) const = 0;
|
||||
|
||||
/** @brief Read specific keypoint dataset from hdf5 file into vector<KeyPoint> object.
|
||||
@param keypoints vector<KeyPoint> container where data reads will be returned.
|
||||
@param kplabel specify the source hdf5 dataset label.
|
||||
@param offset specify the offset location over dataset from where read starts.
|
||||
@param counts specify the amount of keypoints from dataset to read.
|
||||
|
||||
Reads out vector<KeyPoint> object reflecting the stored dataset.
|
||||
|
||||
@note If hdf5 file does not exist an exception will be thrown. Use hlexists() to check dataset presence.
|
||||
It is thread safe.
|
||||
|
||||
- Example below reads a dataset containing keypoints starting with second entry:
|
||||
@code{.cpp}
|
||||
// open hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// blank KeyPoint container
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
// read keypoints starting second one
|
||||
h5io->kpread( keypoints, "keypoints", 1 );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||
- Example below perform read of 3 keypoints from second entry.
|
||||
@code{.cpp}
|
||||
// open hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// blank KeyPoint container
|
||||
std::vector<cv::KeyPoint> keypoints;
|
||||
// read three keypoints starting second one
|
||||
h5io->kpread( keypoints, "keypoints", 1, 3 );
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
*/
|
||||
virtual void kpread( vector<KeyPoint>& keypoints, const String& kplabel,
|
||||
const int offset = H5_NONE, const int counts = H5_NONE ) const = 0;
|
||||
|
||||
};
|
||||
|
||||
/** @brief Open or create hdf5 file
|
||||
@param HDF5Filename specify the HDF5 filename.
|
||||
|
||||
Returns a pointer to the hdf5 object class
|
||||
|
||||
@note If the specified file does not exist, it will be created using default properties.
|
||||
Otherwise, it is opened in read and write mode with default access properties.
|
||||
Any operations except dscreate() functions on object
|
||||
will be thread safe. Multiple datasets can be created inside a single hdf5 file, and can be accessed
|
||||
from the same hdf5 object from multiple instances as long read or write operations are done over
|
||||
non-overlapping regions of dataset. Single hdf5 file also can be opened by multiple instances,
|
||||
reads and writes can be instantiated at the same time as long as non-overlapping regions are involved. Object
|
||||
is released using close().
|
||||
|
||||
- Example below opens and then releases the file.
|
||||
@code{.cpp}
|
||||
// open / auto create hdf5 file
|
||||
cv::Ptr<cv::hdf::HDF5> h5io = cv::hdf::open( "mytest.h5" );
|
||||
// ...
|
||||
// release
|
||||
h5io->close();
|
||||
@endcode
|
||||
|
||||

|
||||
|
||||
- Text dump (3x3 Hilbert matrix) of hdf5 dataset using **h5dump** tool:
|
||||
@code{.txt}
|
||||
$ h5dump test.h5
|
||||
HDF5 "test.h5" {
|
||||
GROUP "/" {
|
||||
DATASET "hilbert" {
|
||||
DATATYPE H5T_ARRAY { [2] H5T_IEEE_F64LE }
|
||||
DATASPACE SIMPLE { ( 3, 3 ) / ( 3, 3 ) }
|
||||
DATA {
|
||||
(0,0): [ 1, -1 ], [ 0.5, -0.5 ], [ 0.333333, -0.333333 ],
|
||||
(1,0): [ 0.5, -0.5 ], [ 0.333333, -0.333333 ], [ 0.25, -0.25 ],
|
||||
(2,0): [ 0.333333, -0.333333 ], [ 0.25, -0.25 ], [ 0.2, -0.2 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
*/
|
||||
CV_EXPORTS_W Ptr<HDF5> open( const String& HDF5Filename );
|
||||
|
||||
//! @}
|
||||
|
||||
} // end namespace hdf
|
||||
} // end namespace cv
|
||||
#endif // _OPENCV_HDF5_HPP_
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @file create_groups.cpp
|
||||
* @author Fangjun Kuang <csukuangfj dot at gmail dot com>
|
||||
* @date December 2017
|
||||
*
|
||||
* @brief It demonstrates how to create HDF5 groups and subgroups.
|
||||
*
|
||||
* Basic steps:
|
||||
* 1. Use hdf::open to create a HDF5 file
|
||||
* 2. Use HDF5::hlexists to check if a group exists or not
|
||||
* 3. Use HDF5::grcreate to create a group by specifying its name
|
||||
* 4. Use hdf::close to close a HDF5 file after modifying it
|
||||
*
|
||||
*/
|
||||
|
||||
//! [tutorial]
|
||||
#include <iostream>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/hdf.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
int main()
|
||||
{
|
||||
//! [create_group]
|
||||
|
||||
//! [tutorial_create_file]
|
||||
Ptr<hdf::HDF5> h5io = hdf::open("mytest.h5");
|
||||
//! [tutorial_create_file]
|
||||
|
||||
//! [tutorial_create_group]
|
||||
// "/" means the root group, which is always present
|
||||
if (!h5io->hlexists("/Group1"))
|
||||
h5io->grcreate("/Group1");
|
||||
else
|
||||
std::cout << "/Group1 has already been created, skip it.\n";
|
||||
//! [tutorial_create_group]
|
||||
|
||||
//! [tutorial_create_subgroup]
|
||||
// Note that Group1 has been created above, otherwise exception will occur
|
||||
if (!h5io->hlexists("/Group1/SubGroup1"))
|
||||
h5io->grcreate("/Group1/SubGroup1");
|
||||
else
|
||||
std::cout << "/Group1/SubGroup1 has already been created, skip it.\n";
|
||||
//! [tutorial_create_subgroup]
|
||||
|
||||
//! [tutorial_close_file]
|
||||
h5io->close();
|
||||
//! [tutorial_close_file]
|
||||
|
||||
//! [create_group]
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [tutorial]
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* @file create_read_write_datasets.cpp
|
||||
* @author Fangjun Kuang <csukuangfj dot at gmail dot com>
|
||||
* @date December 2017
|
||||
*
|
||||
* @brief It demonstrates how to create a dataset, how
|
||||
* to write a cv::Mat to the dataset and how to
|
||||
* read a cv::Mat from it.
|
||||
*
|
||||
*/
|
||||
|
||||
//! [tutorial]
|
||||
#include <iostream>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/hdf.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
static void write_root_group_single_channel()
|
||||
{
|
||||
String filename = "root_group_single_channel.h5";
|
||||
String dataset_name = "/single"; // Note that it is a child of the root group /
|
||||
|
||||
// prepare data
|
||||
Mat data;
|
||||
data = (cv::Mat_<float>(2, 3) << 0, 1, 2, 3, 4, 5, 6);
|
||||
|
||||
//! [tutorial_open_file]
|
||||
Ptr<hdf::HDF5> h5io = hdf::open(filename);
|
||||
//! [tutorial_open_file]
|
||||
|
||||
//! [tutorial_write_root_single_channel]
|
||||
// write data to the given dataset
|
||||
// the dataset "/single" is created automatically, since it is a child of the root
|
||||
h5io->dswrite(data, dataset_name);
|
||||
//! [tutorial_write_root_single_channel]
|
||||
|
||||
//! [tutorial_read_dataset]
|
||||
Mat expected;
|
||||
h5io->dsread(expected, dataset_name);
|
||||
//! [tutorial_read_dataset]
|
||||
|
||||
//! [tutorial_check_result]
|
||||
double diff = norm(data - expected);
|
||||
CV_Assert(abs(diff) < 1e-10);
|
||||
//! [tutorial_check_result]
|
||||
|
||||
h5io->close();
|
||||
}
|
||||
|
||||
static void write_single_channel()
|
||||
{
|
||||
String filename = "single_channel.h5";
|
||||
String parent_name = "/data";
|
||||
String dataset_name = parent_name + "/single";
|
||||
|
||||
// prepare data
|
||||
Mat data;
|
||||
data = (cv::Mat_<float>(2, 3) << 0, 1, 2, 3, 4, 5);
|
||||
|
||||
Ptr<hdf::HDF5> h5io = hdf::open(filename);
|
||||
|
||||
//! [tutorial_create_dataset]
|
||||
// first we need to create the parent group
|
||||
if (!h5io->hlexists(parent_name)) h5io->grcreate(parent_name);
|
||||
|
||||
// create the dataset if it not exists
|
||||
if (!h5io->hlexists(dataset_name)) h5io->dscreate(data.rows, data.cols, data.type(), dataset_name);
|
||||
//! [tutorial_create_dataset]
|
||||
|
||||
// the following is the same with the above function write_root_group_single_channel()
|
||||
|
||||
h5io->dswrite(data, dataset_name);
|
||||
|
||||
Mat expected;
|
||||
h5io->dsread(expected, dataset_name);
|
||||
|
||||
double diff = norm(data - expected);
|
||||
CV_Assert(abs(diff) < 1e-10);
|
||||
|
||||
h5io->close();
|
||||
}
|
||||
|
||||
/*
|
||||
* creating, reading and writing multiple-channel matrices
|
||||
* are the same with single channel matrices
|
||||
*/
|
||||
static void write_multiple_channels()
|
||||
{
|
||||
String filename = "two_channels.h5";
|
||||
String parent_name = "/data";
|
||||
String dataset_name = parent_name + "/two_channels";
|
||||
|
||||
// prepare data
|
||||
Mat data(2, 3, CV_32SC2);
|
||||
for (size_t i = 0; i < data.total()*data.channels(); i++)
|
||||
((int*) data.data)[i] = (int)i;
|
||||
|
||||
Ptr<hdf::HDF5> h5io = hdf::open(filename);
|
||||
|
||||
// first we need to create the parent group
|
||||
if (!h5io->hlexists(parent_name)) h5io->grcreate(parent_name);
|
||||
|
||||
// create the dataset if it not exists
|
||||
if (!h5io->hlexists(dataset_name)) h5io->dscreate(data.rows, data.cols, data.type(), dataset_name);
|
||||
|
||||
// the following is the same with the above function write_root_group_single_channel()
|
||||
|
||||
h5io->dswrite(data, dataset_name);
|
||||
|
||||
Mat expected;
|
||||
h5io->dsread(expected, dataset_name);
|
||||
|
||||
double diff = norm(data - expected);
|
||||
CV_Assert(abs(diff) < 1e-10);
|
||||
|
||||
h5io->close();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
write_root_group_single_channel();
|
||||
|
||||
write_single_channel();
|
||||
|
||||
write_multiple_channels();
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [tutorial]
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @file read_write_attributes.cpp
|
||||
* @author Fangjun Kuang <csukuangfj dot at gmail dot com>
|
||||
* @date December 2017
|
||||
*
|
||||
* @brief It demonstrates how to read and write attributes inside the
|
||||
* root group.
|
||||
*
|
||||
* Currently, only the following datatypes can be used as attributes:
|
||||
* - cv::String
|
||||
* - int
|
||||
* - double
|
||||
* - cv::InputArray (n-d continuous multichannel arrays)
|
||||
*
|
||||
* Although HDF supports associating attributes with both datasets and groups,
|
||||
* only support for the root group is implemented by OpenCV at present.
|
||||
*/
|
||||
|
||||
//! [tutorial]
|
||||
#include <iostream>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/hdf.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
static void read_write_attributes()
|
||||
{
|
||||
String filename = "attributes.h5";
|
||||
|
||||
//! [tutorial_open_file]
|
||||
Ptr<hdf::HDF5> h5io = hdf::open(filename);
|
||||
//! [tutorial_open_file]
|
||||
|
||||
//! [tutorial_write_mat]
|
||||
String attr_mat_name = "array attribute";
|
||||
Mat attr_mat;
|
||||
attr_mat = (cv::Mat_<float>(2, 3) << 0, 1, 2, 3, 4, 5, 6);
|
||||
if (!h5io->atexists(attr_mat_name))
|
||||
h5io->atwrite(attr_mat, attr_mat_name);
|
||||
//! [tutorial_write_mat]
|
||||
|
||||
//! [snippets_write_str]
|
||||
String attr_str_name = "string attribute";
|
||||
String attr_str = "Hello HDF5 from OpenCV!";
|
||||
if (!h5io->atexists(attr_str_name))
|
||||
h5io->atwrite(attr_str, attr_str_name);
|
||||
//! [snippets_write_str]
|
||||
|
||||
String attr_int_name = "int attribute";
|
||||
int attr_int = 123456;
|
||||
if (!h5io->atexists(attr_int_name))
|
||||
h5io->atwrite(attr_int, attr_int_name);
|
||||
|
||||
String attr_double_name = "double attribute";
|
||||
double attr_double = 45678.123;
|
||||
if (!h5io->atexists(attr_double_name))
|
||||
h5io->atwrite(attr_double, attr_double_name);
|
||||
|
||||
// read attributes
|
||||
Mat expected_attr_mat;
|
||||
int expected_attr_int;
|
||||
double expected_attr_double;
|
||||
|
||||
//! [snippets_read_str]
|
||||
String expected_attr_str;
|
||||
h5io->atread(&expected_attr_str, attr_str_name);
|
||||
//! [snippets_read_str]
|
||||
|
||||
//! [tutorial_read_mat]
|
||||
h5io->atread(expected_attr_mat, attr_mat_name);
|
||||
//! [tutorial_read_mat]
|
||||
h5io->atread(&expected_attr_int, attr_int_name);
|
||||
h5io->atread(&expected_attr_double, attr_double_name);
|
||||
|
||||
// check results
|
||||
CV_Assert(norm(attr_mat - expected_attr_mat) < 1e-10);
|
||||
CV_Assert(attr_str.compare(expected_attr_str) == 0);
|
||||
CV_Assert(attr_int == expected_attr_int);
|
||||
CV_Assert(fabs(attr_double - expected_attr_double) < 1e-10);
|
||||
|
||||
//! [tutorial_close_file]
|
||||
h5io->close();
|
||||
//! [tutorial_close_file]
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
read_write_attributes();
|
||||
|
||||
return 0;
|
||||
}
|
||||
//! [tutorial]
|
||||
@@ -0,0 +1,43 @@
|
||||
/*********************************************************************
|
||||
* Software License Agreement (BSD License)
|
||||
*
|
||||
* Copyright (c) 2015
|
||||
* Balint Cristian <cristian dot balint at gmail dot com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*********************************************************************/
|
||||
|
||||
#ifndef __OPENCV_HDF_PRECOMP_H__
|
||||
#define __OPENCV_HDF_PRECOMP_H__
|
||||
|
||||
#include "opencv2/core.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "opencv2/hdf.hpp"
|
||||
#endif
|
||||
@@ -0,0 +1,374 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
/**
|
||||
* @file test_hdf5.cpp
|
||||
* @author Fangjun Kuang <csukuangfj dot at gmail dot com>
|
||||
* @date December 2017
|
||||
*/
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
namespace opencv_test { namespace {
|
||||
|
||||
struct HDF5_Test : public testing::Test
|
||||
{
|
||||
virtual void SetUp()
|
||||
{
|
||||
m_filename = "test.h5";
|
||||
|
||||
// 0 1 2
|
||||
// 3 4 5
|
||||
m_single_channel.create(2, 3, CV_32F);
|
||||
for (size_t i = 0; i < m_single_channel.total(); i++)
|
||||
{
|
||||
((float*)m_single_channel.data)[i] = i;
|
||||
}
|
||||
|
||||
// 0 1 2 3 4 5
|
||||
// 6 7 8 9 10 11
|
||||
m_two_channels.create(2, 3, CV_32SC2);
|
||||
for (size_t i = 0; i < m_two_channels.total()*m_two_channels.channels(); i++)
|
||||
{
|
||||
((int*)m_two_channels.data)[i] = (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
//! Remove the hdf5 file
|
||||
void reset()
|
||||
{
|
||||
remove(m_filename.c_str());
|
||||
}
|
||||
|
||||
String m_filename; //!< filename for testing
|
||||
Ptr<hdf::HDF5> m_hdf_io; //!< HDF5 file pointer
|
||||
Mat m_single_channel; //!< single channel matrix for test
|
||||
Mat m_two_channels; //!< two-channel matrix for test
|
||||
};
|
||||
|
||||
TEST_F(HDF5_Test, create_a_single_group)
|
||||
{
|
||||
reset();
|
||||
|
||||
String group_name = "parent";
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
m_hdf_io->grcreate(group_name);
|
||||
|
||||
EXPECT_EQ(m_hdf_io->hlexists(group_name), true);
|
||||
EXPECT_EQ(m_hdf_io->hlexists("child"), false);
|
||||
|
||||
// It should fail since it creates a group with an existing name
|
||||
EXPECT_ANY_THROW(m_hdf_io->grcreate(group_name));
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
|
||||
TEST_F(HDF5_Test, create_a_child_group)
|
||||
{
|
||||
reset();
|
||||
|
||||
String parent = "parent";
|
||||
String child = parent + "/child";
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
m_hdf_io->grcreate(parent);
|
||||
m_hdf_io->grcreate(child);
|
||||
|
||||
EXPECT_EQ(m_hdf_io->hlexists(parent), true);
|
||||
EXPECT_EQ(m_hdf_io->hlexists(child), true);
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
TEST_F(HDF5_Test, create_dataset)
|
||||
{
|
||||
reset();
|
||||
|
||||
String dataset_single_channel = "/single";
|
||||
String dataset_two_channels = "/dual";
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
|
||||
m_hdf_io->dscreate(m_single_channel.rows,
|
||||
m_single_channel.cols,
|
||||
m_single_channel.type(),
|
||||
dataset_single_channel);
|
||||
|
||||
m_hdf_io->dscreate(m_two_channels.rows,
|
||||
m_two_channels.cols,
|
||||
m_two_channels.type(),
|
||||
dataset_two_channels);
|
||||
|
||||
EXPECT_EQ(m_hdf_io->hlexists(dataset_single_channel), true);
|
||||
EXPECT_EQ(m_hdf_io->hlexists(dataset_two_channels), true);
|
||||
|
||||
std::vector<int> dims;
|
||||
|
||||
dims = m_hdf_io->dsgetsize(dataset_single_channel, hdf::HDF5::H5_GETDIMS);
|
||||
EXPECT_EQ(dims.size(), (size_t)2);
|
||||
EXPECT_EQ(dims[0], m_single_channel.rows);
|
||||
EXPECT_EQ(dims[1], m_single_channel.cols);
|
||||
|
||||
dims = m_hdf_io->dsgetsize(dataset_two_channels, hdf::HDF5::H5_GETDIMS);
|
||||
EXPECT_EQ(dims.size(), (size_t)2);
|
||||
EXPECT_EQ(dims[0], m_two_channels.rows);
|
||||
EXPECT_EQ(dims[1], m_two_channels.cols);
|
||||
|
||||
int type;
|
||||
type = m_hdf_io->dsgettype(dataset_single_channel);
|
||||
EXPECT_EQ(type, m_single_channel.type());
|
||||
|
||||
type = m_hdf_io->dsgettype(dataset_two_channels);
|
||||
EXPECT_EQ(type, m_two_channels.type());
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
|
||||
TEST_F(HDF5_Test, write_read_dataset_1)
|
||||
{
|
||||
reset();
|
||||
|
||||
String dataset_single_channel = "/single";
|
||||
String dataset_two_channels = "/dual";
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
|
||||
// since the dataset is under the root group, it is created by dswrite() automatically.
|
||||
m_hdf_io->dswrite(m_single_channel, dataset_single_channel);
|
||||
m_hdf_io->dswrite(m_two_channels, dataset_two_channels);
|
||||
|
||||
EXPECT_EQ(m_hdf_io->hlexists(dataset_single_channel), true);
|
||||
EXPECT_EQ(m_hdf_io->hlexists(dataset_two_channels), true);
|
||||
|
||||
// read single channel matrix
|
||||
Mat single;
|
||||
m_hdf_io->dsread(single, dataset_single_channel);
|
||||
EXPECT_EQ(single.type(), m_single_channel.type());
|
||||
EXPECT_EQ(single.size(), m_single_channel.size());
|
||||
EXPECT_LE(cvtest::norm(single, m_single_channel, NORM_L2), 1e-10);
|
||||
|
||||
// read dual channel matrix
|
||||
Mat dual;
|
||||
m_hdf_io->dsread(dual, dataset_two_channels);
|
||||
EXPECT_EQ(dual.type(), m_two_channels.type());
|
||||
EXPECT_EQ(dual.size(), m_two_channels.size());
|
||||
EXPECT_LE(cvtest::norm(dual, m_two_channels, NORM_L2), 1e-10);
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
TEST_F(HDF5_Test, write_read_dataset_2)
|
||||
{
|
||||
reset();
|
||||
// create the dataset manually if it is not inside
|
||||
// the root group
|
||||
|
||||
String parent = "/parent";
|
||||
|
||||
String dataset_single_channel = parent + "/single";
|
||||
String dataset_two_channels = parent + "/dual";
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
|
||||
m_hdf_io->grcreate(parent);
|
||||
EXPECT_EQ(m_hdf_io->hlexists(parent), true);
|
||||
|
||||
m_hdf_io->dscreate(m_single_channel.rows,
|
||||
m_single_channel.cols,
|
||||
m_single_channel.type(),
|
||||
dataset_single_channel);
|
||||
|
||||
m_hdf_io->dscreate(m_two_channels.rows,
|
||||
m_two_channels.cols,
|
||||
m_two_channels.type(),
|
||||
dataset_two_channels);
|
||||
|
||||
EXPECT_EQ(m_hdf_io->hlexists(dataset_single_channel), true);
|
||||
EXPECT_EQ(m_hdf_io->hlexists(dataset_two_channels), true);
|
||||
|
||||
m_hdf_io->dswrite(m_single_channel, dataset_single_channel);
|
||||
m_hdf_io->dswrite(m_two_channels, dataset_two_channels);
|
||||
|
||||
EXPECT_EQ(m_hdf_io->hlexists(dataset_single_channel), true);
|
||||
EXPECT_EQ(m_hdf_io->hlexists(dataset_two_channels), true);
|
||||
|
||||
// read single channel matrix
|
||||
Mat single;
|
||||
m_hdf_io->dsread(single, dataset_single_channel);
|
||||
EXPECT_EQ(single.type(), m_single_channel.type());
|
||||
EXPECT_EQ(single.size(), m_single_channel.size());
|
||||
EXPECT_LE(cvtest::norm(single, m_single_channel, NORM_L2), 1e-10);
|
||||
|
||||
// read dual channel matrix
|
||||
Mat dual;
|
||||
m_hdf_io->dsread(dual, dataset_two_channels);
|
||||
EXPECT_EQ(dual.type(), m_two_channels.type());
|
||||
EXPECT_EQ(dual.size(), m_two_channels.size());
|
||||
EXPECT_LE(cvtest::norm(dual, m_two_channels, NORM_L2), 1e-10);
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
TEST_F(HDF5_Test, test_attribute)
|
||||
{
|
||||
reset();
|
||||
|
||||
String attr_name = "test attribute name";
|
||||
int attr_value = 0x12345678;
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
EXPECT_EQ(m_hdf_io->atexists(attr_name), false);
|
||||
|
||||
m_hdf_io->atwrite(attr_value, attr_name);
|
||||
EXPECT_ANY_THROW(m_hdf_io->atwrite(attr_value, attr_name)); // error! it already exists
|
||||
|
||||
EXPECT_EQ(m_hdf_io->atexists(attr_name), true);
|
||||
|
||||
int expected_attr_value;
|
||||
m_hdf_io->atread(&expected_attr_value, attr_name);
|
||||
EXPECT_EQ(attr_value, expected_attr_value);
|
||||
|
||||
m_hdf_io->atdelete(attr_name);
|
||||
EXPECT_ANY_THROW(m_hdf_io->atdelete(attr_name)); // error! Delete non-existed attribute
|
||||
|
||||
EXPECT_EQ(m_hdf_io->atexists(attr_name), false);
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
TEST_F(HDF5_Test, test_attribute_int)
|
||||
{
|
||||
reset();
|
||||
|
||||
String attr_name = "test int";
|
||||
int attr_value = 0x12345678;
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
|
||||
m_hdf_io->atwrite(attr_value, attr_name);
|
||||
|
||||
int expected_attr_value;
|
||||
m_hdf_io->atread(&expected_attr_value, attr_name);
|
||||
EXPECT_EQ(attr_value, expected_attr_value);
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
TEST_F(HDF5_Test, test_attribute_double)
|
||||
{
|
||||
reset();
|
||||
|
||||
String attr_name = "test double";
|
||||
double attr_value = 123.456789;
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
|
||||
m_hdf_io->atwrite(attr_value, attr_name);
|
||||
|
||||
double expected_attr_value;
|
||||
m_hdf_io->atread(&expected_attr_value, attr_name);
|
||||
EXPECT_NEAR(attr_value, expected_attr_value, 1e-9);
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
TEST_F(HDF5_Test, test_attribute_String)
|
||||
{
|
||||
reset();
|
||||
|
||||
String attr_name = "test-String";
|
||||
String attr_value = "----_______----Hello HDF5----_______----\n";
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
|
||||
m_hdf_io->atwrite(attr_value, attr_name);
|
||||
|
||||
String got_attr_value;
|
||||
m_hdf_io->atread(&got_attr_value, attr_name);
|
||||
EXPECT_EQ(attr_value, got_attr_value);
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
TEST_F(HDF5_Test, test_attribute_String_empty)
|
||||
{
|
||||
reset();
|
||||
|
||||
String attr_name = "test-empty-string";
|
||||
String attr_value;
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
|
||||
m_hdf_io->atwrite(attr_value, attr_name);
|
||||
|
||||
String got_attr_value;
|
||||
m_hdf_io->atread(&got_attr_value, attr_name);
|
||||
EXPECT_EQ(attr_value, got_attr_value);
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
TEST_F(HDF5_Test, test_attribute_InutArray_OutputArray_2d)
|
||||
{
|
||||
reset();
|
||||
|
||||
String attr_name = "test-InputArray-OutputArray-2d";
|
||||
cv::Mat attr_value;
|
||||
|
||||
std::vector<int> depth_vec;
|
||||
depth_vec.push_back(CV_8U); depth_vec.push_back(CV_8S);
|
||||
depth_vec.push_back(CV_16U); depth_vec.push_back(CV_16S);
|
||||
depth_vec.push_back(CV_32S); depth_vec.push_back(CV_32F);
|
||||
depth_vec.push_back(CV_64F);
|
||||
|
||||
std::vector<int> channel_vec;
|
||||
channel_vec.push_back(1); channel_vec.push_back(2);
|
||||
channel_vec.push_back(3); channel_vec.push_back(4);
|
||||
channel_vec.push_back(5); channel_vec.push_back(6);
|
||||
channel_vec.push_back(7); channel_vec.push_back(8);
|
||||
channel_vec.push_back(9); channel_vec.push_back(10);
|
||||
|
||||
std::vector<std::vector<int> > dim_vec;
|
||||
std::vector<int> dim_2d;
|
||||
dim_2d.push_back(2); dim_2d.push_back(3);
|
||||
dim_vec.push_back(dim_2d);
|
||||
|
||||
std::vector<int> dim_3d;
|
||||
dim_3d.push_back(2);
|
||||
dim_3d.push_back(3);
|
||||
dim_3d.push_back(4);
|
||||
dim_vec.push_back(dim_3d);
|
||||
|
||||
std::vector<int> dim_4d;
|
||||
dim_4d.push_back(2); dim_4d.push_back(3);
|
||||
dim_4d.push_back(4); dim_4d.push_back(5);
|
||||
dim_vec.push_back(dim_4d);
|
||||
|
||||
Mat expected_attr_value;
|
||||
|
||||
m_hdf_io = hdf::open(m_filename);
|
||||
for (size_t i = 0; i < depth_vec.size(); i++)
|
||||
for (size_t j = 0; j < channel_vec.size(); j++)
|
||||
for (size_t k = 0; k < dim_vec.size(); k++)
|
||||
{
|
||||
if (m_hdf_io->atexists(attr_name))
|
||||
m_hdf_io->atdelete(attr_name);
|
||||
|
||||
attr_value.create(dim_vec[k], CV_MAKETYPE(depth_vec[i], channel_vec[j]));
|
||||
randu(attr_value, 0, 255);
|
||||
|
||||
m_hdf_io->atwrite(attr_value, attr_name);
|
||||
m_hdf_io->atread(expected_attr_value, attr_name);
|
||||
|
||||
double diff = cvtest::norm(attr_value, expected_attr_value, NORM_L2);
|
||||
EXPECT_LE(diff, 1e-6);
|
||||
|
||||
EXPECT_EQ(attr_value.size, expected_attr_value.size);
|
||||
EXPECT_EQ(attr_value.type(), expected_attr_value.type());
|
||||
}
|
||||
|
||||
m_hdf_io->close();
|
||||
}
|
||||
|
||||
}} // namespace
|
||||
@@ -0,0 +1,7 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
|
||||
#include "test_precomp.hpp"
|
||||
|
||||
CV_TEST_MAIN("cv")
|
||||
@@ -0,0 +1,11 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html.
|
||||
#ifndef __OPENCV_TEST_PRECOMP_HPP__
|
||||
#define __OPENCV_TEST_PRECOMP_HPP__
|
||||
|
||||
#include "opencv2/ts.hpp"
|
||||
#include "opencv2/core.hpp"
|
||||
#include "opencv2/hdf.hpp"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
Creating Groups {#tutorial_hdf_create_groups}
|
||||
===============================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
This tutorial will show you:
|
||||
- How to create a HDF5 file?
|
||||
- How to create a group?
|
||||
- How to check whether a given group exists or not?
|
||||
- How to create a subgroup?
|
||||
|
||||
Source Code
|
||||
----
|
||||
|
||||
The following code creates two groups: `Group1` and `SubGroup1`, where
|
||||
`SubGroup1` is a child of `Group1`.
|
||||
|
||||
You can download the code from [here][1] or find it in the file
|
||||
`modules/hdf/samples/create_groups.cpp` of the opencv_contrib source code library.
|
||||
|
||||
@snippet samples/create_groups.cpp tutorial
|
||||
|
||||
Explanation
|
||||
----
|
||||
|
||||
First, we create a HDF5 file
|
||||
|
||||
@snippet samples/create_groups.cpp tutorial_create_file
|
||||
|
||||
If the given file does not exist, it will be created. Otherwise, it is open for read and write.
|
||||
|
||||
Next, we create the group `Group1`
|
||||
|
||||
@snippet samples/create_groups.cpp tutorial_create_group
|
||||
|
||||
Note that we have to check whether `/Group1` exists or not using
|
||||
the function cv::hdf::HDF5::hlexists() before creating it. You can not create
|
||||
a group with an existing name. Otherwise, an error will occur.
|
||||
|
||||
Then, we create the subgroup named `Subgroup1`. In order to
|
||||
indicate that it is a sub group of `Group1`, we have to
|
||||
use the group name `/Group1/SubGroup1`:
|
||||
|
||||
@snippet samples/create_groups.cpp tutorial_create_subgroup
|
||||
|
||||
Note that before creating a subgroup, we have to make sure
|
||||
that its parent group exists. Otherwise, an error will occur.
|
||||
|
||||
In the end, we have to close the file
|
||||
|
||||
@snippet samples/create_groups.cpp tutorial_close_file
|
||||
|
||||
Result
|
||||
----
|
||||
|
||||
There are many tools that can be used to inspect a given HDF file, such
|
||||
as HDFView and h5dump. If you are using Ubuntu, you can install
|
||||
them with the following commands:
|
||||
|
||||
@code
|
||||
sudo apt-get install hdf5-tools hdfview
|
||||
@endcode
|
||||
|
||||
There are also binaries available from the The HDF Group official website <https://support.hdfgroup.org/HDF5/Tutor/tools.html>.
|
||||
|
||||
The following figure shows the result visualized with the tool HDFView:
|
||||
|
||||

|
||||
|
||||
The output for `h5dump` is:
|
||||
|
||||
@code
|
||||
$ h5dump mytest.h5
|
||||
HDF5 "mytest.h5" {
|
||||
GROUP "/" {
|
||||
GROUP "Group1" {
|
||||
GROUP "SubGroup1" {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@endcode
|
||||
|
||||
[1]: https://github.com/opencv/opencv_contrib/tree/master/modules/hdf/samples/create_groups.cpp
|
||||
@@ -0,0 +1,74 @@
|
||||
Creating, Writing and Reading Datasets {#tutorial_hdf_create_read_write_datasets}
|
||||
===============================
|
||||
|
||||
Goal
|
||||
----
|
||||
|
||||
This tutorial shows you:
|
||||
- How to create a dataset?
|
||||
- How to write a `cv::Mat` to a dataset?
|
||||
- How to read a `cv::Mat` from a dataset?
|
||||
|
||||
@note Currently, it supports only reading and writing cv::Mat and the matrix should be continuous
|
||||
in memory. Supports for other data types have not been implemented yet.
|
||||
|
||||
Source Code
|
||||
----
|
||||
|
||||
The following code demonstrates writing a single channel
|
||||
matrix and a two-channel matrix to datasets and then reading them
|
||||
back.
|
||||
|
||||
You can download the code from [here][1] or find it in the file
|
||||
`modules/hdf/samples/create_read_write_datasets.cpp` of the opencv_contrib source code library.
|
||||
|
||||
@snippet samples/create_read_write_datasets.cpp tutorial
|
||||
|
||||
Explanation
|
||||
----
|
||||
|
||||
The first step for creating a dataset is to open the file
|
||||
|
||||
@snippet samples/create_read_write_datasets.cpp tutorial_open_file
|
||||
|
||||
For the function `write_root_group_single_channel()`, since
|
||||
the dataset name is `/single`, which is inside the root group, we can use
|
||||
|
||||
@snippet samples/create_read_write_datasets.cpp tutorial_write_root_single_channel
|
||||
|
||||
to write the data directly to the dataset without the need of creating
|
||||
it beforehand. Because it is created inside cv::hdf::HDF5::dswrite()
|
||||
automatically.
|
||||
|
||||
@warning This applies only to datasets that reside inside the root group.
|
||||
|
||||
Of course, we can create the dataset by ourselves:
|
||||
|
||||
@snippet samples/create_read_write_datasets.cpp tutorial_create_dataset
|
||||
|
||||
To read data from a dataset, we use
|
||||
|
||||
@snippet samples/create_read_write_datasets.cpp tutorial_read_dataset
|
||||
|
||||
by specifying the name of the dataset.
|
||||
|
||||
We can check that the data read out is exactly the data written before by using
|
||||
|
||||
@snippet samples/create_read_write_datasets.cpp tutorial_check_result
|
||||
|
||||
Results
|
||||
----
|
||||
|
||||
Figure 1 shows the result visualized using the tool HDFView for the file
|
||||
`root_group_single_channel`. The results
|
||||
of matrices for datasets that are not the direct children of the root group
|
||||
are given in Figure 2 and Figure 3, respectively.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
[1]: https://github.com/opencv/opencv_contrib/tree/master/modules/hdf/samples/create_read_write_datasets.cpp
|
||||
@@ -0,0 +1,57 @@
|
||||
Reading and Writing Attributes{#tutorial_hdf_read_write_attributes}
|
||||
===============================
|
||||
|
||||
Goal
|
||||
----
|
||||
This tutorial shows you:
|
||||
- How to write attributes?
|
||||
- How to read attributes?
|
||||
|
||||
@note Although attributes can be associated with groups and datasets, only attributes
|
||||
with the root group are implemented in OpenCV. Supported attribute types are
|
||||
`int`, `double`, `cv::String` and `cv::InputArray` (only for continuous arrays).
|
||||
|
||||
Source Code
|
||||
----
|
||||
|
||||
The following code demonstrates reading and writing attributes
|
||||
inside the root group with data types `cv::Mat`, `cv::String`, `int`
|
||||
and `double`.
|
||||
|
||||
You can download the code from [here][1] or find it in the file
|
||||
`modules/hdf/samples/read_write_attributes.cpp` of the opencv_contrib source code library.
|
||||
|
||||
@snippet samples/read_write_attributes.cpp tutorial
|
||||
|
||||
Explanation
|
||||
----
|
||||
|
||||
The first step is to open the HDF5 file:
|
||||
|
||||
@snippet samples/read_write_attributes.cpp tutorial_open_file
|
||||
|
||||
Then we use cv::hdf::HDF5::atwrite() to write attributes by specifying its value and name:
|
||||
|
||||
@snippet samples/read_write_attributes.cpp tutorial_write_mat
|
||||
|
||||
@warning Before writing an attribute, we have to make sure that
|
||||
the attribute does not exist using cv::hdf::HDF5::atexists().
|
||||
|
||||
To read an attribute, we use cv::hdf::HDF5::atread() by specifying the attribute name
|
||||
|
||||
@snippet samples/read_write_attributes.cpp tutorial_read_mat
|
||||
|
||||
In the end, we have to close the HDF file
|
||||
|
||||
@snippet samples/read_write_attributes.cpp tutorial_close_file
|
||||
|
||||
Results
|
||||
----
|
||||
|
||||
Figure 1 and Figure 2 give the results visualized using the tool HDFView.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
[1]: https://github.com/opencv/opencv_contrib/tree/master/modules/hdf/samples/read_write_attributes.cpp
|
||||
@@ -0,0 +1,32 @@
|
||||
The Hierarchical Data Format (hdf) I/O {#tutorial_table_of_content_hdf}
|
||||
=====================================
|
||||
|
||||
Here you will know how to read and write a HDF5 file using OpenCV.
|
||||
Specifically, it shows you how to read/write groups, datasets and attributes.
|
||||
|
||||
@note The HDF5 library has to be installed in your system
|
||||
to use this module.
|
||||
|
||||
- @subpage tutorial_hdf_create_groups
|
||||
|
||||
*Compatibility:* \> OpenCV 3.0
|
||||
|
||||
*Author:* Fangjun Kuang
|
||||
|
||||
You will learn how to create groups and subgroups.
|
||||
|
||||
- @subpage tutorial_hdf_create_read_write_datasets
|
||||
|
||||
*Compatibility:* \> OpenCV 3.0
|
||||
|
||||
*Author:* Fangjun Kuang
|
||||
|
||||
You will learn how to create, read and write datasets.
|
||||
|
||||
- @subpage tutorial_hdf_read_write_attributes
|
||||
|
||||
*Compatibility:* \> OpenCV 3.4
|
||||
|
||||
*Author:* Fangjun Kuang
|
||||
|
||||
You will learn how to read and write attributes.
|
||||