1 /*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2015
5 * Balint Cristian <cristian dot balint at gmail dot com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of the copyright holders nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35 #include "precomp.hpp"
36
37 #include <hdf5.h>
38
39 using namespace std;
40
41 namespace cv
42 {
43 namespace hdf
44 {
45
46 class HDF5Impl CV_FINAL : public HDF5
47 {
48 public:
49
50 HDF5Impl( const String& HDF5Filename );
51
~HDF5Impl()52 virtual ~HDF5Impl() CV_OVERRIDE { close(); };
53
54 // close and release
55 virtual void close( ) CV_OVERRIDE;
56
57 /*
58 * h5 generic
59 */
60
61 // check if object / link exists
62 virtual bool hlexists( const String& label ) const CV_OVERRIDE;
63
64 virtual bool atexists(const String& atlabel) const CV_OVERRIDE;
65 virtual void atdelete(const String& atlabel) CV_OVERRIDE;
66
67 virtual void atwrite(const int value, const String& atlabel) CV_OVERRIDE;
68 virtual void atread(int* value, const String& atlabel) CV_OVERRIDE;
69
70 virtual void atwrite(const double value, const String& atlabel) CV_OVERRIDE;
71 virtual void atread(double* value, const String& atlabel) CV_OVERRIDE;
72
73 virtual void atwrite(const String& value, const String& atlabel) CV_OVERRIDE;
74 virtual void atread(String* value, const String& atlabel) CV_OVERRIDE;
75
76 virtual void atwrite(InputArray value, const String& atlabel) CV_OVERRIDE;
77 virtual void atread(OutputArray value, const String& atlabel) CV_OVERRIDE;
78
79 /*
80 * h5 group
81 */
82
83 // create a group
84 virtual void grcreate( const String& grlabel ) CV_OVERRIDE;
85
86 /*
87 * cv::Mat
88 */
89
90 // get sizes of dataset
91 virtual vector<int> dsgetsize( const String& dslabel, int dims_flag = H5_GETDIMS ) const CV_OVERRIDE;
92
93 /* get data type of dataset */
94 virtual int dsgettype( const String& dslabel ) const CV_OVERRIDE;
95
96 // overload dscreate() #1
97 virtual void dscreate( const int rows, const int cols, const int type, const String& dslabel ) const CV_OVERRIDE;
98
99 // overload dscreate() #2
100 virtual void dscreate( const int rows, const int cols, const int type, const String& dslabel,
101 const int compresslevel ) const CV_OVERRIDE;
102
103 // overload dscreate() #3
104 virtual void dscreate( const int rows, const int cols, const int type, const String& dslabel,
105 const int compresslevel, const vector<int>& dims_chunks ) const CV_OVERRIDE;
106
107 /* create two dimensional single or mutichannel dataset */
108 virtual void dscreate( const int rows, const int cols, const int type, const String& dslabel,
109 const int compresslevel, const int* dims_chunks ) const CV_OVERRIDE;
110
111 // overload dscreate() #1
112 virtual void dscreate( const int n_dims, const int* sizes, const int type,
113 const String& dslabel ) const CV_OVERRIDE;
114
115 // overload dscreate() #2
116 virtual void dscreate( const int n_dims, const int* sizes, const int type,
117 const String& dslabel, const int compresslevel ) const CV_OVERRIDE;
118
119 // overload dscreate() #3
120 virtual void dscreate( const vector<int>& sizes, const int type, const String& dslabel,
121 const int compresslevel = H5_NONE, const vector<int>& dims_chunks = vector<int>() ) const CV_OVERRIDE;
122
123 /* create n-dimensional single or mutichannel dataset */
124 virtual void dscreate( const int n_dims, const int* sizes, const int type,
125 const String& dslabel, const int compresslevel, const int* dims_chunks ) const CV_OVERRIDE;
126
127 // overload dswrite() #1
128 virtual void dswrite( InputArray Array, const String& dslabel ) const CV_OVERRIDE;
129
130 // overload dswrite() #2
131 virtual void dswrite( InputArray Array, const String& dslabel, const int* dims_offset ) const CV_OVERRIDE;
132
133 // overload dswrite() #3
134 virtual void dswrite( InputArray Array, const String& dslabel, const vector<int>& dims_offset,
135 const vector<int>& dims_counts = vector<int>() ) const CV_OVERRIDE;
136
137 /* write into dataset */
138 virtual void dswrite( InputArray Array, const String& dslabel,
139 const int* dims_offset, const int* dims_counts ) const CV_OVERRIDE;
140
141 // overload dsinsert() #1
142 virtual void dsinsert( InputArray Array, const String& dslabel ) const CV_OVERRIDE;
143
144 // overload dsinsert() #2
145 virtual void dsinsert( InputArray Array, const String& dslabel, const int* dims_offset ) const CV_OVERRIDE;
146
147 // overload dsinsert() #3
148 virtual void dsinsert( InputArray Array, const String& dslabel,
149 const vector<int>& dims_offset, const vector<int>& dims_counts = vector<int>() ) const CV_OVERRIDE;
150
151 /* append / merge into dataset */
152 virtual void dsinsert( InputArray Array, const String& dslabel,
153 const int* dims_offset = NULL, const int* dims_counts = NULL ) const CV_OVERRIDE;
154
155 // overload dsread() #1
156 virtual void dsread( OutputArray Array, const String& dslabel ) const CV_OVERRIDE;
157
158 // overload dsread() #2
159 virtual void dsread( OutputArray Array, const String& dslabel, const int* dims_offset ) const CV_OVERRIDE;
160
161 // overload dsread() #3
162 virtual void dsread( OutputArray Array, const String& dslabel,
163 const vector<int>& dims_offset, const vector<int>& dims_counts = vector<int>() ) const CV_OVERRIDE;
164
165 // read from dataset
166 virtual void dsread( OutputArray Array, const String& dslabel,
167 const int* dims_offset, const int* dims_counts ) const CV_OVERRIDE;
168
169 /*
170 * std::vector<cv::KeyPoint>
171 */
172
173 // get size of keypoints dataset
174 virtual int kpgetsize( const String& kplabel, int dims_flag = H5_GETDIMS ) const CV_OVERRIDE;
175
176 // create KeyPoint structure
177 virtual void kpcreate( const int size, const String& kplabel,
178 const int compresslevel = H5_NONE, const int chunks = H5_NONE ) const CV_OVERRIDE;
179
180 // write KeyPoint structures
181 virtual void kpwrite( const vector<KeyPoint> keypoints, const String& kplabel,
182 const int offset = H5_NONE, const int counts = H5_NONE ) const CV_OVERRIDE;
183
184 // append / merge KeyPoint structures
185 virtual void kpinsert( const vector<KeyPoint> keypoints, const String& kplabel,
186 const int offset = H5_NONE, const int counts = H5_NONE ) const CV_OVERRIDE;
187
188 // read KeyPoint structure
189 virtual void kpread( vector<KeyPoint>& keypoints, const String& kplabel,
190 const int offset = H5_NONE, const int counts = H5_NONE ) const CV_OVERRIDE;
191
192 private:
193
194 //! store filename
195 String m_hdf5_filename;
196
197 //! hdf5 file handler
198 hid_t m_h5_file_id;
199
200 //! translate cvType -> h5Type
201 inline hid_t GetH5type( int cvType ) const;
202
203 //! translate h5Type -> cvType
204 inline int GetCVtype( hid_t h5Type ) const;
205
206 };
207
GetH5type(int cvType) const208 inline hid_t HDF5Impl::GetH5type( int cvType ) const
209 {
210 hid_t h5Type = -1;
211
212 switch ( CV_MAT_DEPTH( cvType ) )
213 {
214 case CV_64F:
215 h5Type = H5T_NATIVE_DOUBLE;
216 break;
217 case CV_32F:
218 h5Type = H5T_NATIVE_FLOAT;
219 break;
220 case CV_8U:
221 h5Type = H5T_NATIVE_UCHAR;
222 break;
223 case CV_8S:
224 h5Type = H5T_NATIVE_CHAR;
225 break;
226 case CV_16U:
227 h5Type = H5T_NATIVE_USHORT;
228 break;
229 case CV_16S:
230 h5Type = H5T_NATIVE_SHORT;
231 break;
232 case CV_32S:
233 h5Type = H5T_NATIVE_INT;
234 break;
235 default:
236 CV_Error_(Error::StsInternal, ("Unknown cvType: %d.", cvType));
237 }
238 return h5Type;
239 }
240
GetCVtype(hid_t h5Type) const241 inline int HDF5Impl::GetCVtype( hid_t h5Type ) const
242 {
243 int cvType = -1;
244
245 if ( H5Tequal( h5Type, H5T_NATIVE_DOUBLE ) )
246 cvType = CV_64F;
247 else if ( H5Tequal( h5Type, H5T_NATIVE_FLOAT ) )
248 cvType = CV_32F;
249 else if ( H5Tequal( h5Type, H5T_NATIVE_UCHAR ) )
250 cvType = CV_8U;
251 else if ( H5Tequal( h5Type, H5T_NATIVE_CHAR ) )
252 cvType = CV_8S;
253 else if ( H5Tequal( h5Type, H5T_NATIVE_USHORT ) )
254 cvType = CV_16U;
255 else if ( H5Tequal( h5Type, H5T_NATIVE_SHORT ) )
256 cvType = CV_16S;
257 else if ( H5Tequal( h5Type, H5T_NATIVE_INT ) )
258 cvType = CV_32S;
259 else
260 CV_Error_(Error::StsInternal, ("Unknown H5Type: %lld.", (long long)h5Type));
261
262 return cvType;
263 }
264
HDF5Impl(const String & _hdf5_filename)265 HDF5Impl::HDF5Impl( const String& _hdf5_filename )
266 : m_hdf5_filename( _hdf5_filename )
267 {
268 // save old
269 // error handler
270 void *errdata;
271 H5E_auto2_t errfunc;
272 hid_t stackid = H5E_DEFAULT;
273 H5Eget_auto( stackid, &errfunc, &errdata );
274
275 // turn off error handling
276 H5Eset_auto( stackid, NULL, NULL );
277
278 // check HDF5 file presence (err suppressed)
279 htri_t check = H5Fis_hdf5( m_hdf5_filename.c_str() );
280
281 // restore previous error handler
282 H5Eset_auto( stackid, errfunc, errdata );
283
284 if ( check == 1 || check == 0 )
285 // open the HDF5 file
286 m_h5_file_id = H5Fopen( m_hdf5_filename.c_str(),
287 H5F_ACC_RDWR, H5P_DEFAULT );
288 else if ( check == -1 )
289 // file does not exist
290 m_h5_file_id = H5Fcreate( m_hdf5_filename.c_str(),
291 H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT );
292 else
293 CV_Error( Error::StsInternal, "Unknown file state." );
294 }
295
close()296 void HDF5Impl::close()
297 {
298 if ( m_h5_file_id != -1 )
299 H5Fclose( m_h5_file_id );
300 // mark closed
301 m_h5_file_id = -1;
302 }
303
304 /*
305 * h5 generic
306 */
307
hlexists(const String & label) const308 bool HDF5Impl::hlexists( const String& label ) const
309 {
310 bool exists = false;
311
312 hid_t lid = H5Pcreate( H5P_LINK_ACCESS );
313 if ( H5Lexists(m_h5_file_id, label.c_str(), lid) == 1 )
314 exists = true;
315
316 H5Pclose(lid);
317 return exists;
318 }
319
atexists(const String & atlabel) const320 bool HDF5Impl::atexists(const String& atlabel) const
321 {
322 bool res = false;
323
324 // save old error handler
325 void *errdata;
326 H5E_auto2_t errfunc;
327 hid_t stackid = H5E_DEFAULT;
328 H5Eget_auto(stackid, &errfunc, &errdata);
329
330 // turn off error handling
331 H5Eset_auto(stackid, NULL, NULL);
332
333 hid_t attr = H5Aopen_name(m_h5_file_id, atlabel.c_str());
334 if (attr >= 0)
335 {
336 res = true;
337 H5Aclose(attr);
338 }
339
340 // restore previous error handler
341 H5Eset_auto(stackid, errfunc, errdata);
342
343 return res;
344 }
345
atdelete(const String & atlabel)346 void HDF5Impl::atdelete(const String& atlabel)
347 {
348 if (!atexists(atlabel))
349 CV_Error_(Error::StsInternal,("The attribute '%s' does not exist!", atlabel.c_str()));
350
351 H5Adelete(m_h5_file_id, atlabel.c_str());
352 }
353
atwrite(const int value,const String & atlabel)354 void HDF5Impl::atwrite(const int value, const String& atlabel)
355 {
356 if (atexists(atlabel))
357 CV_Error_(Error::StsInternal,("The attribute '%s' already exists!", atlabel.c_str()));
358
359 hid_t aid = H5Screate(H5S_SCALAR);;
360 hid_t attr = H5Acreate2(m_h5_file_id, atlabel.c_str(), H5T_NATIVE_INT, aid,
361 H5P_DEFAULT, H5P_DEFAULT);
362 H5Awrite(attr, H5T_NATIVE_INT, &value);
363
364 H5Sclose(aid);
365 H5Aclose(attr);
366 }
367
atread(int * value,const String & atlabel)368 void HDF5Impl::atread(int* value, const String& atlabel)
369 {
370 if (!value)
371 CV_Error(Error::StsBadArg, "NULL pointer");
372
373 if (!atexists(atlabel))
374 CV_Error_(Error::StsInternal, ("Attribute '%s' does not exist!", atlabel.c_str()));
375
376 hid_t attr = H5Aopen(m_h5_file_id, atlabel.c_str(), H5P_DEFAULT);
377 H5Aread(attr, H5T_NATIVE_INT, value);
378 H5Aclose(attr);
379 }
380
atwrite(const double value,const String & atlabel)381 void HDF5Impl::atwrite(const double value, const String& atlabel)
382 {
383 if (atexists(atlabel))
384 CV_Error_(Error::StsInternal,("The attribute '%s' already exists!", atlabel.c_str()));
385
386 hid_t aid = H5Screate(H5S_SCALAR);;
387 hid_t attr = H5Acreate2(m_h5_file_id, atlabel.c_str(), H5T_NATIVE_DOUBLE, aid,
388 H5P_DEFAULT, H5P_DEFAULT);
389 H5Awrite(attr, H5T_NATIVE_DOUBLE, &value);
390
391 H5Sclose(aid);
392 H5Aclose(attr);
393 }
394
atread(double * value,const String & atlabel)395 void HDF5Impl::atread(double* value, const String& atlabel)
396 {
397 if (!value)
398 CV_Error(Error::StsBadArg, "NULL pointer");
399
400 if (!atexists(atlabel))
401 CV_Error_(Error::StsInternal, ("Attribute '%s' does not exist!", atlabel.c_str()));
402
403 hid_t attr = H5Aopen(m_h5_file_id, atlabel.c_str(), H5P_DEFAULT);
404 H5Aread(attr, H5T_NATIVE_DOUBLE, value);
405 H5Aclose(attr);
406 }
407
atwrite(const String & value,const String & atlabel)408 void HDF5Impl::atwrite(const String& value, const String& atlabel)
409 {
410 if (atexists(atlabel))
411 CV_Error_(Error::StsInternal,("The attribute '%s' already exists!", atlabel.c_str()));
412
413 hid_t aid = H5Screate(H5S_SCALAR);
414 hid_t atype = H5Tcopy(H5T_C_S1);
415 H5Tset_size(atype, value.size()+1);
416 H5Tset_strpad(atype, H5T_STR_NULLTERM);
417
418 hid_t attr = H5Acreate2(m_h5_file_id, atlabel.c_str(), atype, aid, H5P_DEFAULT, H5P_DEFAULT);
419 H5Awrite(attr, atype, value.c_str());
420
421 H5Sclose(aid);
422 H5Tclose(atype);
423 H5Aclose(attr);
424 }
425
atread(String * value,const String & atlabel)426 void HDF5Impl::atread(String* value, const String& atlabel)
427 {
428 if (!value)
429 CV_Error(Error::StsBadArg, "NULL pointer");
430
431 if (!atexists(atlabel))
432 CV_Error_(Error::StsInternal, ("Attribute '%s' does not exist!", atlabel.c_str()));
433
434 hid_t attr = H5Aopen(m_h5_file_id, atlabel.c_str(), H5P_DEFAULT);
435 hid_t atype = H5Aget_type(attr);
436 H5T_class_t type_class = H5Tget_class(atype);
437 if (type_class != H5T_STRING)
438 {
439 H5Tclose(atype);
440 H5Aclose(attr);
441 CV_Error_(Error::StsInternal, ("Attribute '%s' is not of string type!", atlabel.c_str()));
442 }
443 size_t size = H5Tget_size(atype);
444 AutoBuffer<char> buf(size);
445
446 hid_t atype_mem = H5Tget_native_type(atype, H5T_DIR_ASCEND);
447 H5Aread(attr, atype_mem, buf.data());
448 if (size > 0 && buf[size - 1] == '\0')
449 size--;
450 value->assign(buf.data(), size);
451
452 H5Tclose(atype_mem);
453 H5Tclose(atype);
454 H5Aclose(attr);
455 }
456
atwrite(InputArray value,const String & atlabel)457 void HDF5Impl::atwrite(InputArray value, const String& atlabel)
458 {
459 if (atexists(atlabel))
460 CV_Error_(Error::StsInternal,("The attribute '%s' already exists!", atlabel.c_str()));
461
462 Mat value_ = value.getMat();
463
464 if (!value_.isContinuous())
465 CV_Error(Error::StsInternal, "Only continuous array are implemented. Current array is not continuous!");
466
467 int ndims = value_.dims;
468
469 vector<hsize_t> dim_vec(ndims);
470 for (int i = 0; i < ndims; i++)
471 dim_vec[i] = value_.size[i];
472
473 hid_t dtype = GetH5type(value_.type());
474 if (value_.channels() > 1)
475 {
476 hsize_t dims[1] = { (hsize_t)value_.channels()};
477 dtype = H5Tarray_create(dtype, 1, dims);
478 }
479
480 hid_t aid = H5Screate(H5S_SIMPLE);
481 H5Sset_extent_simple(aid, ndims, dim_vec.data(), NULL);
482
483 hid_t attr = H5Acreate2(m_h5_file_id, atlabel.c_str(), dtype,
484 aid, H5P_DEFAULT, H5P_DEFAULT);
485
486 H5Awrite(attr, dtype, value_.data);
487
488 if (value_.channels() > 1)
489 H5Tclose(dtype);
490
491 H5Sclose(aid);
492 H5Aclose(attr);
493 }
494
atread(OutputArray value,const String & atlabel)495 void HDF5Impl::atread(OutputArray value, const String& atlabel)
496 {
497 if (!atexists(atlabel))
498 CV_Error_(Error::StsInternal, ("Attribute '%s' does not exist!", atlabel.c_str()));
499
500 hid_t attr = H5Aopen(m_h5_file_id, atlabel.c_str(), H5P_DEFAULT);
501 hid_t atype = H5Aget_type(attr);
502 hid_t aspace = H5Aget_space(attr);
503 int rank = H5Sget_simple_extent_ndims(aspace);
504
505 vector<hsize_t> dim_vec_(rank);
506 H5Sget_simple_extent_dims(aspace, dim_vec_.data(), NULL);
507 vector<int> dim_vec(dim_vec_.begin(), dim_vec_.end());
508
509 int nchannels = 1;
510 hid_t h5type;
511 if (H5Tget_class(atype) == H5T_ARRAY)
512 {
513 hsize_t dims;
514 H5Tget_array_dims(atype, &dims);
515 nchannels = (int) dims;
516
517 hid_t super_type = H5Tget_super(atype);
518 h5type = H5Tget_native_type(super_type, H5T_DIR_ASCEND);
519 H5Tclose(super_type);
520 }
521 else
522 h5type = H5Tget_native_type(atype, H5T_DIR_ASCEND);
523
524 int dtype = GetCVtype(h5type);
525
526 value.create(rank, dim_vec.data(), CV_MAKETYPE(dtype, nchannels));
527 H5Aread(attr, atype, value.getMat().data);
528
529 H5Sclose(aspace);
530 H5Tclose(atype);
531 H5Aclose(attr);
532 }
533
534 /*
535 * h5 group
536 */
537
grcreate(const String & grlabel)538 void HDF5Impl::grcreate( const String& grlabel )
539 {
540 if (hlexists(grlabel))
541 CV_Error_(Error::StsInternal, ("Requested group '%s' already exists.", grlabel.c_str()));
542
543 hid_t gid = H5Gcreate(m_h5_file_id, grlabel.c_str(),
544 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
545 H5Gclose(gid);
546 }
547
548 /*
549 * cv:Mat
550 */
551
dsgetsize(const String & dslabel,int dims_flag) const552 vector<int> HDF5Impl::dsgetsize( const String& dslabel, int dims_flag ) const
553 {
554 // open dataset
555 hid_t dsdata = H5Dopen( m_h5_file_id, dslabel.c_str(), H5P_DEFAULT );
556
557 // get file space
558 hid_t fspace = H5Dget_space( dsdata );
559
560 // fetch rank
561 int n_dims = H5Sget_simple_extent_ndims( fspace );
562
563 // dims storage
564 hsize_t *dims = new hsize_t[n_dims];
565
566 // output storage
567 vector<int> SizeVect(0);
568
569 // fetch dims
570 if ( dims_flag == H5_GETDIMS ||
571 dims_flag == H5_GETMAXDIMS )
572 {
573 if ( dims_flag == H5_GETDIMS )
574 H5Sget_simple_extent_dims( fspace, dims, NULL );
575 else
576 H5Sget_simple_extent_dims( fspace, NULL, dims );
577 SizeVect.resize( n_dims );
578 }
579 else if ( dims_flag == H5_GETCHUNKDIMS )
580 {
581 // rank size
582 int rank_chunk = -1;
583 // fetch chunk size
584 hid_t cparms = H5Dget_create_plist( dsdata );
585 if ( H5D_CHUNKED == H5Pget_layout ( cparms ) )
586 {
587 rank_chunk = H5Pget_chunk ( cparms, n_dims, dims );
588 }
589 if ( rank_chunk > 0 )
590 SizeVect.resize( n_dims );
591 }
592 else
593 CV_Error_(Error::StsInternal, ("Unknown dimension flag: %d", dims_flag));
594
595 // fill with size data
596 for ( size_t d = 0; d < SizeVect.size(); d++ )
597 SizeVect[d] = (int) dims[d];
598
599 H5Dclose( dsdata );
600 H5Sclose( fspace );
601
602 delete [] dims;
603
604 return SizeVect;
605 }
606
dsgettype(const String & dslabel) const607 int HDF5Impl::dsgettype( const String& dslabel ) const
608 {
609 hid_t h5type;
610
611 // open dataset
612 hid_t dsdata = H5Dopen( m_h5_file_id, dslabel.c_str(), H5P_DEFAULT );
613
614 // get data type
615 hid_t dstype = H5Dget_type( dsdata );
616
617 int channs = 1;
618 if ( H5Tget_class( dstype ) == H5T_ARRAY )
619 {
620 // fetch channs
621 hsize_t ardims[1];
622 H5Tget_array_dims( dstype, ardims );
623 channs = (int)ardims[0];
624 // fetch depth
625 hid_t tsuper = H5Tget_super( dstype );
626 h5type = H5Tget_native_type( tsuper, H5T_DIR_ASCEND );
627 H5Tclose( tsuper );
628 }
629 else
630 h5type = H5Tget_native_type( dstype, H5T_DIR_DESCEND );
631
632 // convert to CVType
633 int cvtype = GetCVtype( h5type );
634
635 H5Tclose( dstype );
636 H5Dclose( dsdata );
637
638 return CV_MAKETYPE( cvtype, channs );
639 }
640
641 // overload
dscreate(const int rows,const int cols,const int type,const String & dslabel) const642 void HDF5Impl::dscreate( const int rows, const int cols, const int type,
643 const String& dslabel ) const
644 {
645 // dataset dims
646 int dsizes[2] = { rows, cols };
647
648 // create the two dim array
649 dscreate( 2, dsizes, type, dslabel, HDF5::H5_NONE, NULL );
650 }
651
652 // overload
dscreate(const int rows,const int cols,const int type,const String & dslabel,const int compresslevel) const653 void HDF5Impl::dscreate( const int rows, const int cols, const int type,
654 const String& dslabel, const int compresslevel ) const
655 {
656 // dataset dims
657 int dsizes[2] = { rows, cols };
658
659 // create the two dim array
660 dscreate( 2, dsizes, type, dslabel, compresslevel, NULL );
661 }
662
663 // overload
dscreate(const int rows,const int cols,const int type,const String & dslabel,const int compresslevel,const vector<int> & dims_chunks) const664 void HDF5Impl::dscreate( const int rows, const int cols, const int type,
665 const String& dslabel, const int compresslevel,
666 const vector<int>& dims_chunks ) const
667 {
668 CV_Assert( dims_chunks.empty() || dims_chunks.size() == 2 );
669 dscreate( rows, cols, type, dslabel, compresslevel, dims_chunks.empty() ? NULL : &(dims_chunks[0]) );
670 }
671
dscreate(const int rows,const int cols,const int type,const String & dslabel,const int compresslevel,const int * dims_chunks) const672 void HDF5Impl::dscreate( const int rows, const int cols, const int type,
673 const String& dslabel, const int compresslevel, const int* dims_chunks ) const
674 {
675 // dataset dims
676 int dsizes[2] = { rows, cols };
677
678 // create the two dim array
679 dscreate( 2, dsizes, type, dslabel, compresslevel, dims_chunks );
680 }
681
682 // overload
dscreate(const int n_dims,const int * sizes,const int type,const String & dslabel) const683 void HDF5Impl::dscreate( const int n_dims, const int* sizes, const int type,
684 const String& dslabel ) const
685 {
686 dscreate( n_dims, sizes, type, dslabel, H5_NONE, NULL );
687 }
688
689 // overload
dscreate(const int n_dims,const int * sizes,const int type,const String & dslabel,const int compresslevel) const690 void HDF5Impl::dscreate( const int n_dims, const int* sizes, const int type,
691 const String& dslabel, const int compresslevel ) const
692 {
693 dscreate( n_dims, sizes, type, dslabel, compresslevel, NULL );
694 }
695
696 // overload
dscreate(const vector<int> & sizes,const int type,const String & dslabel,const int compresslevel,const vector<int> & dims_chunks) const697 void HDF5Impl::dscreate( const vector<int>& sizes, const int type,
698 const String& dslabel, const int compresslevel,
699 const vector<int>& dims_chunks ) const
700 {
701 CV_Assert( dims_chunks.empty() || dims_chunks.size() == sizes.size() );
702
703 const int n_dims = (int) sizes.size();
704 dscreate( n_dims, &sizes[0], type, dslabel, compresslevel, dims_chunks.empty() ? NULL : &(dims_chunks[0]) );
705 }
706
dscreate(const int n_dims,const int * sizes,const int type,const String & dslabel,const int compresslevel,const int * dims_chunks) const707 void HDF5Impl::dscreate( const int n_dims, const int* sizes, const int type,
708 const String& dslabel, const int compresslevel, const int* dims_chunks ) const
709 {
710 // compress valid H5_NONE, 0-9
711 CV_Assert( compresslevel >= H5_NONE && compresslevel <= 9 );
712
713 if ( hlexists( dslabel ) == true )
714 CV_Error_(Error::StsInternal, ("Requested dataset '%s' already exists.", dslabel.c_str()));
715
716 int channs = CV_MAT_CN( type );
717
718 hsize_t *chunks = new hsize_t[n_dims];
719 hsize_t *dsdims = new hsize_t[n_dims];
720 hsize_t *maxdim = new hsize_t[n_dims];
721
722 // dimension space
723 for ( int d = 0; d < n_dims; d++ )
724 {
725 CV_Assert( sizes[d] >= H5_UNLIMITED );
726
727 // dataset dimension
728 if ( sizes[d] == H5_UNLIMITED )
729 {
730 CV_Assert( dims_chunks != NULL );
731
732 dsdims[d] = 0;
733 maxdim[d] = H5S_UNLIMITED;
734 }
735 else
736 {
737 dsdims[d] = sizes[d];
738 maxdim[d] = sizes[d];
739 }
740 // default chunking
741 if ( dims_chunks == NULL )
742 chunks[d] = sizes[d];
743 else
744 chunks[d] = dims_chunks[d];
745 }
746
747 // create dataset space
748 hid_t dspace = H5Screate_simple( n_dims, dsdims, maxdim );
749
750 // create data property
751 hid_t dsdcpl = H5Pcreate( H5P_DATASET_CREATE );
752
753 // set properties
754 if ( compresslevel >= 0 )
755 H5Pset_deflate( dsdcpl, compresslevel );
756
757 if ( dims_chunks != NULL || compresslevel >= 0 )
758 H5Pset_chunk( dsdcpl, n_dims, chunks );
759
760 // convert to h5 type
761 hid_t dstype = GetH5type( type );
762
763 // expand channs
764 if ( channs > 1 )
765 {
766 hsize_t adims[1] = { (hsize_t)channs };
767 dstype = H5Tarray_create( dstype, 1, adims );
768 }
769
770 // create data
771 hid_t dsdata = H5Dcreate( m_h5_file_id, dslabel.c_str(), dstype,
772 dspace, H5P_DEFAULT, dsdcpl, H5P_DEFAULT );
773
774 if ( channs > 1 )
775 H5Tclose( dstype );
776
777 delete [] chunks;
778 delete [] dsdims;
779 delete [] maxdim;
780
781 H5Pclose( dsdcpl );
782 H5Sclose( dspace );
783 H5Dclose( dsdata );
784 }
785
786 // overload
dsread(OutputArray Array,const String & dslabel) const787 void HDF5Impl::dsread( OutputArray Array, const String& dslabel ) const
788 {
789 dsread( Array, dslabel, NULL, NULL );
790 }
791
792 // overload
dsread(OutputArray Array,const String & dslabel,const int * dims_offset) const793 void HDF5Impl::dsread( OutputArray Array, const String& dslabel,
794 const int* dims_offset ) const
795 {
796 dsread( Array, dslabel, dims_offset, NULL );
797 }
798
799 // overload
dsread(OutputArray Array,const String & dslabel,const vector<int> & dims_offset,const vector<int> & dims_counts) const800 void HDF5Impl::dsread( OutputArray Array, const String& dslabel,
801 const vector<int>& dims_offset,
802 const vector<int>& dims_counts ) const
803 {
804 dsread( Array, dslabel, &dims_offset[0], &dims_counts[0] );
805 }
806
dsread(OutputArray Array,const String & dslabel,const int * dims_offset,const int * dims_counts) const807 void HDF5Impl::dsread( OutputArray Array, const String& dslabel,
808 const int* dims_offset, const int* dims_counts ) const
809 {
810 // only Mat support
811 CV_Assert( Array.isMat() );
812
813 hid_t h5type;
814
815 // open the HDF5 dataset
816 hid_t dsdata = H5Dopen( m_h5_file_id, dslabel.c_str(), H5P_DEFAULT );
817
818 // get data type
819 hid_t dstype = H5Dget_type( dsdata );
820
821 int channs = 1;
822 if ( H5Tget_class( dstype ) == H5T_ARRAY )
823 {
824 // fetch channs
825 hsize_t ardims[1];
826 H5Tget_array_dims( dstype, ardims );
827 channs = (int) ardims[0];
828 // fetch depth
829 hid_t tsuper = H5Tget_super( dstype );
830 h5type = H5Tget_native_type( tsuper, H5T_DIR_ASCEND );
831 H5Tclose( tsuper );
832 } else
833 h5type = H5Tget_native_type( dstype, H5T_DIR_ASCEND );
834
835 int dType = GetCVtype( h5type );
836
837 // get file space
838 hid_t fspace = H5Dget_space( dsdata );
839
840 // fetch rank
841 int n_dims = H5Sget_simple_extent_ndims( fspace );
842
843 // fetch dims
844 hsize_t *dsdims = new hsize_t[n_dims];
845 H5Sget_simple_extent_dims( fspace, dsdims, NULL );
846
847 // set amount by custom offset
848 if ( dims_offset != NULL )
849 {
850 for ( int d = 0; d < n_dims; d++ )
851 dsdims[d] -= dims_offset[d];
852 }
853
854 // set custom amount of data
855 if ( dims_counts != NULL )
856 {
857 for ( int d = 0; d < n_dims; d++ )
858 dsdims[d] = dims_counts[d];
859 }
860
861 // get memory write window
862 int *mxdims = new int[n_dims];
863 hsize_t *foffset = new hsize_t[n_dims];
864 for ( int d = 0; d < n_dims; d++ )
865 {
866 foffset[d] = 0;
867 mxdims[d] = (int) dsdims[d];
868 }
869
870 // allocate persistent Mat
871 Array.create( n_dims, mxdims, CV_MAKETYPE(dType, channs) );
872
873 // get blank data space
874 hid_t dspace = H5Screate_simple( n_dims, dsdims, NULL );
875
876 // get matrix write window
877 H5Sselect_hyperslab( dspace, H5S_SELECT_SET,
878 foffset, NULL, dsdims, NULL );
879
880 // set custom offsets
881 if ( dims_offset != NULL )
882 {
883 for ( int d = 0; d < n_dims; d++ )
884 foffset[d] = dims_offset[d];
885 }
886
887 // get a file read window
888 H5Sselect_hyperslab( fspace, H5S_SELECT_SET,
889 foffset, NULL, dsdims, NULL );
890
891 // read from DS
892 Mat matrix = Array.getMat();
893 H5Dread( dsdata, dstype, dspace, fspace, H5P_DEFAULT, matrix.data );
894
895 delete [] dsdims;
896 delete [] mxdims;
897 delete [] foffset;
898
899 H5Tclose (h5type );
900 H5Tclose( dstype );
901 H5Sclose( dspace );
902 H5Sclose( fspace );
903 H5Dclose( dsdata );
904 }
905
906 // overload
dswrite(InputArray Array,const String & dslabel) const907 void HDF5Impl::dswrite( InputArray Array, const String& dslabel ) const
908 {
909 dswrite( Array, dslabel, NULL, NULL );
910 }
911 // overload
dswrite(InputArray Array,const String & dslabel,const int * dims_offset) const912 void HDF5Impl::dswrite( InputArray Array, const String& dslabel,
913 const int* dims_offset ) const
914 {
915 dswrite( Array, dslabel, dims_offset, NULL );
916 }
917 // overload
dswrite(InputArray Array,const String & dslabel,const vector<int> & dims_offset,const vector<int> & dims_counts) const918 void HDF5Impl::dswrite( InputArray Array, const String& dslabel,
919 const vector<int>& dims_offset,
920 const vector<int>& dims_counts ) const
921 {
922 dswrite( Array, dslabel, &dims_offset[0], &dims_counts[0] );
923 }
924
dswrite(InputArray Array,const String & dslabel,const int * dims_offset,const int * dims_counts) const925 void HDF5Impl::dswrite( InputArray Array, const String& dslabel,
926 const int* dims_offset, const int* dims_counts ) const
927 {
928 // only Mat support
929 CV_Assert( Array.isMat() );
930
931 Mat matrix = Array.getMat();
932
933 // memory array should be compact
934 CV_Assert( matrix.isContinuous() );
935
936 int n_dims = matrix.dims;
937 int channs = matrix.channels();
938
939 int *dsizes = new int[n_dims];
940 hsize_t *dsdims = new hsize_t[n_dims];
941 hsize_t *offset = new hsize_t[n_dims];
942 // replicate Mat dimensions
943 for ( int d = 0; d < n_dims; d++ )
944 {
945 offset[d] = 0;
946 dsizes[d] = matrix.size[d];
947 dsdims[d] = matrix.size[d];
948 }
949
950 // FixMe: If one of the groups the dataset belongs to does not exist,
951 // FixMe: dscreate() will fail!
952 // FixMe: It should be an error if the specified dataset has not been created instead of trying to create it
953 // pre-create dataset if needed
954 if ( hlexists( dslabel ) == false )
955 dscreate( n_dims, dsizes, matrix.type(), dslabel );
956
957 // set custom amount of data
958 if ( dims_counts != NULL )
959 {
960 for ( int d = 0; d < n_dims; d++ )
961 dsdims[d] = dims_counts[d];
962 }
963
964 // open dataset
965 hid_t dsdata = H5Dopen( m_h5_file_id, dslabel.c_str(), H5P_DEFAULT );
966
967 // create input data space
968 hid_t dspace = H5Screate_simple( n_dims, dsdims, NULL );
969
970 // set custom offsets
971 if ( dims_offset != NULL )
972 {
973 for ( int d = 0; d < n_dims; d++ )
974 offset[d] = dims_offset[d];
975 }
976
977 // create offset write window space
978 hid_t fspace = H5Dget_space( dsdata );
979 H5Sselect_hyperslab( fspace, H5S_SELECT_SET,
980 offset, NULL, dsdims, NULL );
981
982 // convert type
983 hid_t dstype = GetH5type( matrix.type() );
984
985 // expand channs
986 if ( matrix.channels() > 1 )
987 {
988 hsize_t adims[1] = { (hsize_t)channs };
989 dstype = H5Tarray_create( dstype, 1, adims );
990 }
991
992 // write into dataset
993 H5Dwrite( dsdata, dstype, dspace, fspace,
994 H5P_DEFAULT, matrix.data );
995
996 if ( matrix.channels() > 1 )
997 H5Tclose( dstype );
998
999 delete [] dsizes;
1000 delete [] dsdims;
1001 delete [] offset;
1002
1003 H5Sclose( dspace );
1004 H5Sclose( fspace );
1005 H5Dclose( dsdata );
1006 }
1007
1008 // overload
dsinsert(InputArray Array,const String & dslabel) const1009 void HDF5Impl::dsinsert( InputArray Array, const String& dslabel ) const
1010 {
1011 dsinsert( Array, dslabel, NULL, NULL );
1012 }
1013
1014 // overload
dsinsert(InputArray Array,const String & dslabel,const int * dims_offset) const1015 void HDF5Impl::dsinsert( InputArray Array, const String& dslabel,
1016 const int* dims_offset ) const
1017 {
1018 dsinsert( Array, dslabel, dims_offset, NULL );
1019 }
1020
1021 // overload
dsinsert(InputArray Array,const String & dslabel,const vector<int> & dims_offset,const vector<int> & dims_counts) const1022 void HDF5Impl::dsinsert( InputArray Array, const String& dslabel,
1023 const vector<int>& dims_offset,
1024 const vector<int>& dims_counts ) const
1025 {
1026 dsinsert( Array, dslabel, &dims_offset[0], &dims_counts[0] );
1027 }
1028
dsinsert(InputArray Array,const String & dslabel,const int * dims_offset,const int * dims_counts) const1029 void HDF5Impl::dsinsert( InputArray Array, const String& dslabel,
1030 const int* dims_offset, const int* dims_counts ) const
1031 {
1032 // only Mat support
1033 CV_Assert( Array.isMat() );
1034
1035 // check dataset exists
1036 if ( hlexists( dslabel ) == false )
1037 CV_Error_(Error::StsInternal, ("Dataset '%s' does not exist.", dslabel.c_str()));
1038
1039 Mat matrix = Array.getMat();
1040
1041 // memory array should be compact
1042 CV_Assert( matrix.isContinuous() );
1043
1044 int n_dims = matrix.dims;
1045 int channs = matrix.channels();
1046
1047 hsize_t *dsdims = new hsize_t[n_dims];
1048 hsize_t *offset = new hsize_t[n_dims];
1049 // replicate Mat dimensions
1050 for ( int d = 0; d < n_dims; d++ )
1051 {
1052 offset[d] = 0;
1053 dsdims[d] = matrix.size[d];
1054 }
1055
1056 // set custom amount of data
1057 if ( dims_counts != NULL )
1058 {
1059 for ( int d = 0; d < n_dims; d++ )
1060 {
1061 CV_Assert( dims_counts[d] <= matrix.size[d] );
1062 dsdims[d] = dims_counts[d];
1063 }
1064 }
1065
1066 // open dataset
1067 hid_t dsdata = H5Dopen( m_h5_file_id, dslabel.c_str(), H5P_DEFAULT );
1068
1069 // create input data space
1070 hid_t dspace = H5Screate_simple( n_dims, dsdims, NULL );
1071
1072 // set custom offsets
1073 if ( dims_offset != NULL )
1074 {
1075 for ( int d = 0; d < n_dims; d++ )
1076 offset[d] = dims_offset[d];
1077 }
1078
1079 // get actual file space and dims
1080 hid_t fspace = H5Dget_space( dsdata );
1081 int f_dims = H5Sget_simple_extent_ndims( fspace );
1082 hsize_t *fsdims = new hsize_t[f_dims];
1083 H5Sget_simple_extent_dims( fspace, fsdims, NULL );
1084 H5Sclose( fspace );
1085
1086 CV_Assert( f_dims == n_dims );
1087
1088 // compute new extents
1089 hsize_t *nwdims = new hsize_t[n_dims];
1090 for ( int d = 0; d < n_dims; d++ )
1091 {
1092 // init
1093 nwdims[d] = 0;
1094 // add offset
1095 if ( dims_offset != NULL )
1096 nwdims[d] += dims_offset[d];
1097 // add counts or matrix size
1098 if ( dims_counts != NULL )
1099 nwdims[d] += dims_counts[d];
1100 else
1101 nwdims[d] += matrix.size[d];
1102
1103 // clamp back if smaller
1104 if ( nwdims[d] < fsdims[d] )
1105 nwdims[d] = fsdims[d];
1106 }
1107
1108 // extend dataset
1109 H5Dextend( dsdata, nwdims );
1110
1111 // get the extended data space
1112 fspace = H5Dget_space( dsdata );
1113
1114 H5Sselect_hyperslab( fspace, H5S_SELECT_SET,
1115 offset, NULL, dsdims, NULL );
1116
1117 // convert type
1118 hid_t dstype = GetH5type( matrix.type() );
1119
1120 // expand channs
1121 if ( matrix.channels() > 1 )
1122 {
1123 hsize_t adims[1] = { (hsize_t)channs };
1124 dstype = H5Tarray_create( dstype, 1, adims );
1125 }
1126
1127 // write into dataset
1128 H5Dwrite( dsdata, dstype, dspace, fspace,
1129 H5P_DEFAULT, matrix.data );
1130
1131 if ( matrix.channels() > 1 )
1132 H5Tclose( dstype );
1133
1134 delete [] dsdims;
1135 delete [] offset;
1136 delete [] fsdims;
1137 delete [] nwdims;
1138
1139 H5Sclose( dspace );
1140 H5Sclose( fspace );
1141 H5Dclose( dsdata );
1142 }
1143
1144 /*
1145 * std::vector<cv::KeyPoint>
1146 */
1147
kpgetsize(const String & kplabel,int dims_flag) const1148 int HDF5Impl::kpgetsize( const String& kplabel, int dims_flag ) const
1149 {
1150 vector<int> sizes = dsgetsize( kplabel, dims_flag );
1151
1152 CV_Assert( sizes.size() == 1 );
1153
1154 return sizes[0];
1155 }
1156
kpcreate(const int size,const String & kplabel,const int compresslevel,const int chunks) const1157 void HDF5Impl::kpcreate( const int size, const String& kplabel,
1158 const int compresslevel, const int chunks ) const
1159 {
1160 // size valid
1161 CV_Assert( size >= H5_UNLIMITED );
1162
1163 // valid chunks
1164 CV_Assert( chunks == H5_NONE || chunks > 0 );
1165
1166 // compress valid -1, 0-9
1167 CV_Assert( compresslevel >= H5_NONE && compresslevel <= 9 );
1168
1169 if ( hlexists( kplabel ) == true )
1170 CV_Error_(Error::StsInternal, ("Requested dataset '%s' already exists.", kplabel.c_str()));
1171
1172 hsize_t dchunk[1];
1173 hsize_t dsdims[1];
1174 hsize_t maxdim[1];
1175
1176 // dataset dimension
1177 if ( size == H5_UNLIMITED )
1178 {
1179 dsdims[0] = 0;
1180 maxdim[0] = H5S_UNLIMITED;
1181 }
1182 else
1183 {
1184 dsdims[0] = size;
1185 maxdim[0] = size;
1186 }
1187
1188 // default chunking
1189 if ( chunks == H5_NONE )
1190 if ( size == H5_UNLIMITED )
1191 dchunk[0] = 1;
1192 else
1193 dchunk[0] = size;
1194 else
1195 dchunk[0] = chunks;
1196
1197 // dataset compound type
1198 hid_t dstype = H5Tcreate( H5T_COMPOUND, sizeof( KeyPoint ) );
1199 H5Tinsert( dstype, "xpos", HOFFSET( KeyPoint, pt.x ), H5T_NATIVE_FLOAT );
1200 H5Tinsert( dstype, "ypos", HOFFSET( KeyPoint, pt.y ), H5T_NATIVE_FLOAT );
1201 H5Tinsert( dstype, "size", HOFFSET( KeyPoint, size ), H5T_NATIVE_FLOAT );
1202 H5Tinsert( dstype, "angle", HOFFSET( KeyPoint, angle ), H5T_NATIVE_FLOAT );
1203 H5Tinsert( dstype, "response", HOFFSET( KeyPoint, response ), H5T_NATIVE_FLOAT );
1204 H5Tinsert( dstype, "octave", HOFFSET( KeyPoint, octave ), H5T_NATIVE_INT32 );
1205 H5Tinsert( dstype, "class_id", HOFFSET( KeyPoint, class_id ), H5T_NATIVE_INT32 );
1206
1207 // create dataset space
1208 hid_t dspace = H5Screate_simple( 1, dsdims, maxdim );
1209
1210 // create data property
1211 hid_t dsdcpl = H5Pcreate( H5P_DATASET_CREATE );
1212
1213 // set properties
1214 if ( compresslevel >= 0 )
1215 H5Pset_deflate( dsdcpl, compresslevel );
1216
1217 // if chunking or compression
1218 if ( dchunk[0] > 0 || compresslevel >= 0 )
1219 H5Pset_chunk( dsdcpl, 1, dchunk );
1220
1221 // create data
1222 H5Dcreate( m_h5_file_id, kplabel.c_str(), dstype,
1223 dspace, H5P_DEFAULT, dsdcpl, H5P_DEFAULT );
1224
1225 H5Tclose( dstype );
1226 H5Pclose( dsdcpl );
1227 H5Sclose( dspace );
1228 }
1229
kpwrite(const vector<KeyPoint> keypoints,const String & kplabel,const int offset,const int counts) const1230 void HDF5Impl::kpwrite( const vector<KeyPoint> keypoints, const String& kplabel,
1231 const int offset, const int counts ) const
1232 {
1233 CV_Assert( keypoints.size() > 0 );
1234
1235 int dskdims[1];
1236 hsize_t dsddims[1];
1237 hsize_t doffset[1];
1238
1239 // replicate vector dimension
1240 doffset[0] = 0;
1241 dsddims[0] = keypoints.size();
1242 dskdims[0] = (int)keypoints.size();
1243
1244 // pre-create dataset if needed
1245 if ( hlexists( kplabel ) == false )
1246 kpcreate( dskdims[0], kplabel );
1247
1248 // set custom amount of data
1249 if ( counts != H5_NONE )
1250 dsddims[0] = counts;
1251
1252 // open dataset
1253 hid_t dsdata = H5Dopen( m_h5_file_id, kplabel.c_str(), H5P_DEFAULT );
1254
1255 // create input data space
1256 hid_t dspace = H5Screate_simple( 1, dsddims, NULL );
1257
1258 // set custom offsets
1259 if ( offset != H5_NONE )
1260 doffset[0] = offset;
1261
1262 // create offset write window space
1263 hid_t fspace = H5Dget_space( dsdata );
1264 H5Sselect_hyperslab( fspace, H5S_SELECT_SET,
1265 doffset, NULL, dsddims, NULL );
1266
1267 // memory compound type
1268 hid_t mmtype = H5Tcreate( H5T_COMPOUND, sizeof( KeyPoint ) );
1269 H5Tinsert( mmtype, "xpos", HOFFSET( KeyPoint, pt.x ), H5T_NATIVE_FLOAT );
1270 H5Tinsert( mmtype, "ypos", HOFFSET( KeyPoint, pt.y ), H5T_NATIVE_FLOAT );
1271 H5Tinsert( mmtype, "size", HOFFSET( KeyPoint, size ), H5T_NATIVE_FLOAT );
1272 H5Tinsert( mmtype, "angle", HOFFSET( KeyPoint, angle ), H5T_NATIVE_FLOAT );
1273 H5Tinsert( mmtype, "response", HOFFSET( KeyPoint, response ), H5T_NATIVE_FLOAT );
1274 H5Tinsert( mmtype, "octave", HOFFSET( KeyPoint, octave ), H5T_NATIVE_INT32 );
1275 H5Tinsert( mmtype, "class_id", HOFFSET( KeyPoint, class_id ), H5T_NATIVE_INT32 );
1276
1277 // write into dataset
1278 H5Dwrite( dsdata, mmtype, dspace, fspace, H5P_DEFAULT, &keypoints[0] );
1279
1280 H5Tclose( mmtype );
1281 H5Sclose( dspace );
1282 H5Sclose( fspace );
1283 H5Dclose( dsdata );
1284 }
1285
kpinsert(const vector<KeyPoint> keypoints,const String & kplabel,const int offset,const int counts) const1286 void HDF5Impl::kpinsert( const vector<KeyPoint> keypoints, const String& kplabel,
1287 const int offset, const int counts ) const
1288 {
1289 CV_Assert( keypoints.size() > 0 );
1290
1291 // check dataset exists
1292 if ( hlexists( kplabel ) == false )
1293 CV_Error_(Error::StsInternal, ("Dataset '%s' does not exist.", kplabel.c_str()));
1294
1295 hsize_t dsddims[1];
1296 hsize_t doffset[1];
1297
1298 // replicate vector dimension
1299 doffset[0] = 0;
1300 dsddims[0] = keypoints.size();
1301
1302 // set custom amount of data
1303 if ( counts != H5_NONE )
1304 dsddims[0] = counts;
1305
1306 // open dataset
1307 hid_t dsdata = H5Dopen( m_h5_file_id, kplabel.c_str(), H5P_DEFAULT );
1308
1309 // create input data space
1310 hid_t dspace = H5Screate_simple( 1, dsddims, NULL );
1311
1312 // set custom offsets
1313 if ( offset != H5_NONE )
1314 doffset[0] = offset;
1315
1316 // get actual file space and dims
1317 hid_t fspace = H5Dget_space( dsdata );
1318 int f_dims = H5Sget_simple_extent_ndims( fspace );
1319 hsize_t *fsdims = new hsize_t[f_dims];
1320 H5Sget_simple_extent_dims( fspace, fsdims, NULL );
1321 H5Sclose( fspace );
1322
1323 CV_Assert( f_dims == 1 );
1324
1325 // compute new extents
1326 hsize_t nwdims[1] = { 0 };
1327 // add offset
1328 if ( offset != H5_NONE )
1329 nwdims[0] += offset;
1330 // add counts or matrixsize
1331 if ( counts != H5_NONE )
1332 nwdims[0] += counts;
1333 else
1334 nwdims[0] += keypoints.size();
1335
1336 // clamp back if smaller
1337 if ( nwdims[0] < fsdims[0] )
1338 nwdims[0] = fsdims[0];
1339
1340 // extend dataset
1341 H5Dextend( dsdata, nwdims );
1342
1343 // get the extended data space
1344 fspace = H5Dget_space( dsdata );
1345
1346 H5Sselect_hyperslab( fspace, H5S_SELECT_SET,
1347 doffset, NULL, dsddims, NULL );
1348
1349 // memory compound type
1350 hid_t mmtype = H5Tcreate( H5T_COMPOUND, sizeof( KeyPoint ) );
1351 H5Tinsert( mmtype, "xpos", HOFFSET( KeyPoint, pt.x ), H5T_NATIVE_FLOAT );
1352 H5Tinsert( mmtype, "ypos", HOFFSET( KeyPoint, pt.y ), H5T_NATIVE_FLOAT );
1353 H5Tinsert( mmtype, "size", HOFFSET( KeyPoint, size ), H5T_NATIVE_FLOAT );
1354 H5Tinsert( mmtype, "angle", HOFFSET( KeyPoint, angle ), H5T_NATIVE_FLOAT );
1355 H5Tinsert( mmtype, "response", HOFFSET( KeyPoint, response ), H5T_NATIVE_FLOAT );
1356 H5Tinsert( mmtype, "octave", HOFFSET( KeyPoint, octave ), H5T_NATIVE_INT32 );
1357 H5Tinsert( mmtype, "class_id", HOFFSET( KeyPoint, class_id ), H5T_NATIVE_INT32 );
1358
1359 // write into dataset
1360 H5Dwrite( dsdata, mmtype, dspace, fspace, H5P_DEFAULT, &keypoints[0] );
1361
1362 delete [] fsdims;
1363
1364 H5Tclose( mmtype );
1365 H5Sclose( dspace );
1366 H5Sclose( fspace );
1367 H5Dclose( dsdata );
1368 }
1369
kpread(vector<KeyPoint> & keypoints,const String & kplabel,const int offset,const int counts) const1370 void HDF5Impl::kpread( vector<KeyPoint>& keypoints, const String& kplabel,
1371 const int offset, const int counts ) const
1372 {
1373 CV_Assert( keypoints.size() == 0 );
1374
1375 // open the HDF5 dataset
1376 hid_t dsdata = H5Dopen( m_h5_file_id, kplabel.c_str(), H5P_DEFAULT );
1377
1378 // get data type
1379 hid_t dstype = H5Dget_type( dsdata );
1380
1381 // get file space
1382 hid_t fspace = H5Dget_space( dsdata );
1383
1384 // fetch rank
1385 int n_dims = H5Sget_simple_extent_ndims( fspace );
1386
1387 CV_Assert( n_dims == 1 );
1388
1389 // fetch dims
1390 hsize_t dsddims[1];
1391 H5Sget_simple_extent_dims( fspace, dsddims, NULL );
1392
1393 // set amount by custom offset
1394 if ( offset != H5_NONE )
1395 dsddims[0] -= offset;
1396
1397 // set custom amount of data
1398 if ( counts != H5_NONE )
1399 dsddims[0] = counts;
1400
1401 // get memory write window
1402 hsize_t foffset[1] = { 0 };
1403
1404 // allocate keypoints vector
1405 keypoints.resize( dsddims[0] );
1406
1407 // get blank data space
1408 hid_t dspace = H5Screate_simple( 1, dsddims, NULL );
1409
1410 // get matrix write window
1411 H5Sselect_hyperslab( dspace, H5S_SELECT_SET,
1412 foffset, NULL, dsddims, NULL );
1413
1414 // set custom offsets
1415 if ( offset != H5_NONE )
1416 foffset[0] = offset;
1417
1418 // get a file read window
1419 H5Sselect_hyperslab( fspace, H5S_SELECT_SET,
1420 foffset, NULL, dsddims, NULL );
1421
1422 // read from DS
1423 H5Dread( dsdata, dstype, dspace, fspace, H5P_DEFAULT, &keypoints[0] );
1424
1425 H5Tclose( dstype );
1426 H5Sclose( dspace );
1427 H5Sclose( fspace );
1428 H5Dclose( dsdata );
1429 }
1430
open(const String & HDF5Filename)1431 CV_EXPORTS Ptr<HDF5> open( const String& HDF5Filename )
1432 {
1433 return makePtr<HDF5Impl>( HDF5Filename );
1434 }
1435
1436 } // end namespace hdf
1437 } // end namespace cv
1438