CVB++ 14.0
sample_list.hpp
1#pragma once
2
3#include "../_cexports/c_sample_database.h"
4
5#include "../global.hpp"
6#include "../image.hpp"
7#include "../string.hpp"
8#include "../point_2d.hpp"
9
10#include <utility>
11#include <memory>
12#include <vector>
13#include <ctime>
14#include <chrono>
15
16namespace Cvb
17{
18CVB_BEGIN_INLINE_NS
19
21namespace SampleDatabase
22{
23
24namespace Private
25{
26// Helpers to validate new/changed labels
27size_t GetFloatRegressionDimension (CExports::TSIL hSil)
28{
29 auto labelType = CVB_CALL_CAPI (SilGetLabelType(hSil));
30 size_t dim = 0;
31 CVB_CALL_CAPI_CHECKED (SilGetFloatVectorLabelDim(labelType, dim));
32 return dim;
33}
34
35inline void ValidateLabel (CExports::TSIL /*hSil*/, const String &label)
36{
37 if (label.empty ())
38 {
39 throw std::invalid_argument ("empty string is not a valid label");
40 }
41}
42
43inline void ValidateLabel (CExports::TSIL hSil, const std::vector<float> &label)
44{
45 if (label.size () != GetFloatRegressionDimension (hSil))
46 {
47 throw std::invalid_argument ("invalid dimension of the float vector label");
48 }
49}
50
51// Helper to relabel a string label
52inline void Relabel (CExports::TSIL hSil, int index, const String &label)
53{
54 ValidateLabel (hSil, label);
55
56 CVB_CALL_CAPI_CHECKED(SilChangeStringLabelTyped(hSil, index, label.c_str()));
57}
58
59// Helper to relabel a float label
60inline void Relabel (CExports::TSIL hSil, int index, const std::vector<float> &label)
61{
62 ValidateLabel (hSil, label);
63
64 /* Note: need to cast-away const of "label" parameter to match the C-API, the function does not modify it. */
65 CVB_CALL_CAPI_CHECKED(SilChangeVectorLabel(hSil, index, const_cast<float*>(label.data()), label.size()));
66}
67
68// Generic label transformation callback
69template<typename TLabelOut, typename TLabelIn>
70using LabelTransform = std::function<TLabelOut (const TLabelIn &labelIn)>;
71} /* namespace Private */
72
74
76template <class TLabelInformation>
78{
79public:
80 LabelInfoCollection (const SharedReleaseObjectGuard &sguardSil)
81 : shandleSil_(sguardSil)
82 {}
83
85 LabelInfoCollection& operator= (const LabelInfoCollection&) = default;
86
87 virtual ~LabelInfoCollection () = default;
88
89public:
91 using LabelType = typename TLabelInformation::LabelType;
92
94
99 int Count () const
100 {
101 return CVB_CALL_CAPI(SilGetNumLabelEntries(shandleSil_.Handle()));
102 }
103
105
111 TLabelInformation ReadInfo (int index) const
112 {
113 return GetInfo (index);
114 }
115
117
123 {
124 auto count = Count ();
126 for (decltype(count) i = 0; i < count; ++i)
127 {
128 info.push_back (ReadInfo (i));
129 }
130
131 return info;
132 }
133
135
140 void RemoveAt (int index)
141 {
142 CVB_CALL_CAPI_CHECKED(SilDeleteLabel(shandleSil_.Handle(), index));
143 }
144
146
151 void Remove (const LabelType & label)
152 {
153 auto index = LabelToIndex(label);
154 if (index < 0)
155 {
156 throw std::invalid_argument ("cannot remove class because it is not part of the sample database");
157 }
158
159 RemoveAt(index);
160 }
161
163
168 void Clear ()
169 {
170 while (Count () > 0)
171 {
172 RemoveAt (0);
173 }
174 }
175
177
185 void MergeClasses (int fromIndex, int toIndex)
186 {
187 if (fromIndex == toIndex)
188 {
189 return;
190 }
191 Private::Relabel (shandleSil_.Handle (), fromIndex, ReadInfo (toIndex).Label ());
192 }
193
195
203 void MergeClasses (const LabelType & fromLabel, const LabelType & toLabel)
204 {
205 auto fromIndex = LabelToIndex (fromLabel);
206 auto toIndex = LabelToIndex (toLabel);
207 if (fromIndex < 0 || toIndex < 0)
208 {
209 throw std::invalid_argument ("cannot classes, at least one is not part of the collection");
210 }
211
212 MergeClasses (fromIndex, toIndex);
213 }
214
215
216protected:
217 virtual TLabelInformation GetInfo (int index) const = 0;
218
219 int LabelToIndex (const LabelType &label) const
220 {
221 auto count = Count ();
222 for (int i = 0; i < count; ++i)
223 {
224 if (ReadInfo(i).Label() == label)
225 {
226 return i;
227 }
228 }
229 return -1;
230 }
231protected:
232 SharedReleaseObjectGuard shandleSil_;
233}; /* class LabelInfoCollection */
234
236
238template <class TData>
240{
241public:
242 SampleCollection (const SharedReleaseObjectGuard &sguardSil)
243 : shandleSil_(sguardSil)
244 {}
245
246 SampleCollection (const SampleCollection&) = default;
247 SampleCollection& operator= (const SampleCollection&) = default;
248
249 virtual ~SampleCollection () = default;
250
251public:
253
258 int Count () const
259 {
260 auto label = CVB_CALL_CAPI(SilGetLabel (shandleSil_.Handle(), GetLabelIndex()));
261 return CVB_CALL_CAPI(SilGetNumDataReferences(label));
262 }
263
265
271 TData ReadData (int index) const
272 {
273 auto data = CVB_CALL_CAPI(SilGetDataByLabel (shandleSil_.Handle(), GetLabelIndex(), index));
274 return GetData (data);
275 }
276
278
284 TData RemoveAt (int index)
285 {
286 TData retval = ReadData (index);
287 CVB_CALL_CAPI_CHECKED(SilDeleteDataByLabel(shandleSil_.Handle(), GetLabelIndex(), index));
288 return retval;
289 }
290
291protected:
292 std::shared_ptr<Image> GetImage (CExports::TSILDATA dataHandle) const
293 {
294 return Internal::DoBoolCallObjectOut<Image>([&](void* & resimg)
295 {
296 CVB_CALL_CAPI_CHECKED(SilGetImageData (dataHandle, resimg));
297 return CVB_CALL_CAPI(ShareObject (resimg));
298 });
299 }
300
301 int GetLabelIndex () const
302 {
303 return 0;
304 }
305
306 virtual TData GetData (CExports::TSILDATA dataHandle) const = 0;
307
308protected:
309 SharedReleaseObjectGuard shandleSil_;
310}; /* class SampleCollection */
311
313
319
321
327
329
335
337
343
345
351
353
360{
361protected:
362 SampleList (ReleaseObjectGuard&& guardSil, const String &fileName = String())
363 : shandleSil_(std::move(guardSil)),
364 fileName_ (fileName)
365 {}
366
367 SampleList (SampleList&&) noexcept = default;
368
369 SampleList& operator=(SampleList&&) noexcept = default;
370
371 virtual ~SampleList () = default;
372
373 // Helper to load a sample list from file
374 static ReleaseObjectGuard LoadInternal (const String & fileName, CExports::TSilLabelType expectedLabelType)
375 {
376 CExports::TSIL sil = nullptr;
377
378 CVB_CALL_CAPI_CHECKED (SilLoadTyped (fileName.c_str(), sil));
379 ReleaseObjectGuard silGuard (sil);
380
381 auto dataType = CVB_CALL_CAPI (SilGetDataTypeEnum(silGuard.Handle()));
382 auto labelType = CVB_CALL_CAPI (SilGetLabelTypeEnum(silGuard.Handle()));
383 if (dataType != CExports::SDT_ImageData)
384 {
385 throw std::invalid_argument ("the loaded SIL file does not contain image data type");
386 }
387 if (labelType != expectedLabelType)
388 {
389 throw std::invalid_argument ("the loaded SIL file does not contain expected label type");
390 }
391
392 return silGuard;
393 }
394
395public:
397
403 void * Handle() const noexcept
404 {
405 return shandleSil_.Handle();
406 }
407
409
414 {
415 return fileName_;
416 }
417
419
424 {
425 size_t bufferSize = 0;
426 CVB_CALL_CAPI_CHECKED (SilGetCommentTyped(Handle(), static_cast<Char*>(nullptr), bufferSize));
427 std::vector<Char> comment (bufferSize);
428 CVB_CALL_CAPI_CHECKED (SilGetCommentTyped(Handle(), comment.data(), bufferSize));
429 return String (comment.begin(), comment.end());
430 }
431
433
437 void SetComment(String comment)
438 {
439 CVB_CALL_CAPI_CHECKED (SilSetCommentTyped (Handle(), comment.c_str()));
440 }
441
443
447 std::chrono::system_clock::time_point CreationDate() const
448 {
449 CExports::CV_SYSTEMTIME st;
450 CVB_CALL_CAPI_CHECKED (SilGetCreationDate(Handle(), st));
451 std::tm tm = {};
452 tm.tm_sec = st.wSecond;
453 tm.tm_min = st.wMinute;
454 tm.tm_hour = st.wHour;
455 tm.tm_mday = st.wDay;
456 tm.tm_mon = st.wMonth - 1;
457 tm.tm_year = st.wYear - 1900;
458 tm.tm_isdst = -1;
459
460 return std::chrono::system_clock::from_time_t (std::mktime (&tm));
461 }
462
464
468 std::chrono::system_clock::time_point ModificationDate() const
469 {
470 CExports::CV_SYSTEMTIME st;
471 CVB_CALL_CAPI_CHECKED (SilGetModificationDate(Handle(), st));
472 std::tm tm = {};
473 tm.tm_sec = st.wSecond;
474 tm.tm_min = st.wMinute;
475 tm.tm_hour = st.wHour;
476 tm.tm_mday = st.wDay;
477 tm.tm_mon = st.wMonth - 1;
478 tm.tm_year = st.wYear - 1900;
479 tm.tm_isdst = -1;
480
481 return std::chrono::system_clock::from_time_t (std::mktime (&tm));
482 }
483
485
489 int NumClasses() const
490 {
491 size_t numClasses, dummy1, dummy2;
492 double dummy3;
493 CVB_CALL_CAPI_CHECKED(SilGetStatistics(Handle(), numClasses, dummy1, dummy2, dummy3));
494 return static_cast<int>(numClasses);
495 }
496
498
502 int NumSamples() const
503 {
504 return static_cast<int>(CVB_CALL_CAPI(SilGetNumDataEntries(Handle())));
505 }
506
508
512 int MinSampleCount() const
513 {
514 size_t minCount, dummy1, dummy2;
515 double dummy3;
516 CVB_CALL_CAPI_CHECKED(SilGetStatistics(Handle(), dummy1, minCount, dummy2, dummy3));
517 return static_cast<int>(minCount);
518 }
519
521
525 int MaxSampleCount() const
526 {
527 size_t maxCount, dummy1, dummy2;
528 double dummy3;
529 CVB_CALL_CAPI_CHECKED(SilGetStatistics(Handle(), dummy1, dummy2, maxCount, dummy3));
530 return static_cast<int>(maxCount);
531 }
532
534
538 double AverageSampleCount() const
539 {
540 size_t dummy1, dummy2, dummy3;
541 double avgCount;
542 CVB_CALL_CAPI_CHECKED(SilGetStatistics(Handle(), dummy1, dummy2, dummy3, avgCount));
543 return avgCount;
544 }
545
547
553 void Save (const String & fileName) const
554 {
555 CVB_CALL_CAPI_CHECKED (SilStoreTyped (Handle(), fileName.c_str()));
556 fileName_ = fileName;
557 }
558
559protected:
560 // Sample image list transformation workers
561 template <class TOut>
562 std::unique_ptr<TOut> TransformData (DataTransformImageToImage cbk) const
563 {
564 CExports::TSIL sil = nullptr;
565
566 CVB_CALL_CAPI_CHECKED (SilTransformDataList (Handle (), NativeDataTransformCallback, &cbk, sil));
567 ReleaseObjectGuard silGuard (sil);
568
569 return TOut::FromHandle (std::move (silGuard));
570 }
571
572 template <class TOut, class TLabelOut, class TLabelIn>
573 std::unique_ptr<TOut> TransformLabels (Private::LabelTransform<TLabelOut, TLabelIn> cbk) const
574 {
575 CExports::TSIL sil = nullptr;
576
577 CVB_CALL_CAPI_CHECKED (SilTransformLabelList (Handle (), NativeLabelTransformCallback<TLabelOut, TLabelIn>, &cbk, sil));
578 ReleaseObjectGuard silGuard (sil);
579
580 return TOut::FromHandle (std::move (silGuard));
581 }
582
583private:
584 static CExports::cvbbool_t __stdcall NativeDataTransformCallback (void* pPrivate, CExports::TSILDATA DataIn, CExports::TSILDATA& DataOut)
585 {
586 try
587 {
588 DataTransformImageToImage *cbk = reinterpret_cast<DataTransformImageToImage*> (pPrivate);
589
590 auto imgIn = Internal::DoBoolCallObjectOut<Image>([&](void* & resimg)
591 {
592 CVB_CALL_CAPI_CHECKED(SilGetImageData (DataIn, resimg));
593 return CVB_CALL_CAPI(ShareObject (resimg));
594 });
595
596 auto imgOut = (*cbk) (*imgIn);
597 DataOut = CVB_CALL_CAPI(SilCreateImageData(imgOut->Handle(), 0, 0, imgOut->Size().Width(), imgOut->Size().Height()));
598 return true;
599 }
600 catch (const std::exception &)
601 {
602 return false;
603 }
604 }
605
606 template <class TLabelOut, class TLabelIn>
607 static CExports::cvbbool_t __stdcall NativeLabelTransformCallback (void* pPrivate, CExports::TSILLABEL LabelIn, CExports::TSILLABEL& LabelOut)
608 {
609 try
610 {
611 Private::LabelTransform<TLabelOut, TLabelIn> *cbk = reinterpret_cast<Private::LabelTransform<TLabelOut, TLabelIn>*> (pPrivate);
612
613 TLabelIn objectIn;
614 NativeLabelToObject (LabelIn, objectIn);
615
616 auto objectOut = (*cbk) (objectIn);
617 LabelOut = CreateNativeLabel (objectOut);
618 return true;
619 }
620 catch (const std::exception &)
621 {
622 return false;
623 }
624 }
625
626 static void NativeLabelToObject (CExports::TSILLABEL label, String &object)
627 {
628 size_t bufferSize = 0;
629 CVB_CALL_CAPI_CHECKED (SilGetStringLabelTyped(label, static_cast<Char*>(nullptr), bufferSize));
630 std::vector<Char> stringLabel (bufferSize);
631 CVB_CALL_CAPI_CHECKED (SilGetStringLabelTyped(label, stringLabel.data(), bufferSize));
632 object.assign (stringLabel.begin (), stringLabel.end ());
633 }
634
635 static CExports::TSILLABEL CreateNativeLabel (const String &object)
636 {
637 return CVB_CALL_CAPI(SilCreateStringLabelTyped(object.c_str()));
638 }
639
640 static void NativeLabelToObject (CExports::TSILLABEL label, std::vector<float> &object)
641 {
642 size_t dim = 0;
643 CVB_CALL_CAPI_CHECKED (SilGetFloatVectorLabel(label, static_cast<float*>(nullptr), dim));
644 object.resize (dim);
645 CVB_CALL_CAPI_CHECKED (SilGetFloatVectorLabel(label, object.data(), dim));
646 }
647
648 static CExports::TSILLABEL CreateNativeLabel (const std::vector<float> &object)
649 {
650 return CVB_CALL_CAPI(SilCreateVectorLabel(object.data(), object.size()));
651 }
652
653protected:
654 SharedReleaseObjectGuard shandleSil_;
655
656private:
657 mutable String fileName_;
658}; /* class SampleList */
659
662
663
664} /* namespace SampleDatabase */
665CVB_END_INLINE_NS
666} /* namespace Cvb */
The Common Vision Blox image.
Definition: decl_image.hpp:45
Information collection for class labels.
Definition: sample_list.hpp:78
void MergeClasses(const LabelType &fromLabel, const LabelType &toLabel)
Merge two classes into one class.
Definition: sample_list.hpp:203
typename TLabelInformation::LabelType LabelType
Type of the labels.
Definition: sample_list.hpp:91
std::vector< TLabelInformation > ReadInfos() const
Retrieves all the items stored in the collection.
Definition: sample_list.hpp:122
void Remove(const LabelType &label)
Remove a class and all the data objects associated with it based on its name.
Definition: sample_list.hpp:151
int Count() const
Retrieves the number of elements in the collection.
Definition: sample_list.hpp:99
TLabelInformation ReadInfo(int index) const
Retrieves the indexed item.
Definition: sample_list.hpp:111
void Clear()
Remove all labels (and their associated data) from the sample list.
Definition: sample_list.hpp:168
void MergeClasses(int fromIndex, int toIndex)
Merge two classes into one class.
Definition: sample_list.hpp:185
void RemoveAt(int index)
Remove a class by index.
Definition: sample_list.hpp:140
Collection of data samples.
Definition: sample_list.hpp:240
TData RemoveAt(int index)
Remove a sample.
Definition: sample_list.hpp:284
int Count() const
Get the number of samples for this collection.
Definition: sample_list.hpp:258
TData ReadData(int index) const
Access one of the sample images.
Definition: sample_list.hpp:271
Base class for sample lists.
Definition: sample_list.hpp:360
int NumClasses() const
Number of distinguishable classes in the sample list.
Definition: sample_list.hpp:489
std::chrono::system_clock::time_point CreationDate() const
Date on which the sample list was created.
Definition: sample_list.hpp:447
String Comment() const
Get the comment text.
Definition: sample_list.hpp:423
void Save(const String &fileName) const
Save the sample list to a file.
Definition: sample_list.hpp:553
double AverageSampleCount() const
Average number samples in per class of the sample list.
Definition: sample_list.hpp:538
void SetComment(String comment)
Set the comment text.
Definition: sample_list.hpp:437
std::chrono::system_clock::time_point ModificationDate() const
Date on which the sample list was modified.
Definition: sample_list.hpp:468
int MaxSampleCount() const
Number samples in the largest class of the sample list.
Definition: sample_list.hpp:525
int NumSamples() const
Total number of samples in the sample list.
Definition: sample_list.hpp:502
String FileName() const
Name of the file from which this image list was loaded (empty string if this image list was neither l...
Definition: sample_list.hpp:413
int MinSampleCount() const
Number samples in the smallest class of the sample list.
Definition: sample_list.hpp:512
void * Handle() const noexcept
Classic API SIL handle.
Definition: sample_list.hpp:403
@ Private
Private name space.
std::function< std::vector< float >(const std::vector< float > &labelIn)> LabelTransformVectorToVector
Callback for label transformation.
Definition: sample_list.hpp:334
std::function< String(const String &labelIn)> LabelTransformStringToString
Callback for label transformation.
Definition: sample_list.hpp:318
std::function< String(const std::vector< float > &labelIn)> LabelTransformVectorToString
Callback for label transformation.
Definition: sample_list.hpp:342
std::function< std::vector< float >(const String &labelIn)> LabelTransformStringToVector
Callback for label transformation.
Definition: sample_list.hpp:326
std::function< std::unique_ptr< Image >(const Image &imgIn)> DataTransformImageToImage
Image data transformation callback.
Definition: sample_list.hpp:350
Root namespace for the Image Manager interface.
Definition: c_barcode.h:24
char Char
Character type for wide characters or unicode characters.
Definition: string.hpp:59
std::string String
String for wide characters or unicode characters.
Definition: string.hpp:45