CVB++ 14.0
blob.hpp
1#pragma once
2
3#if defined _WIN32
4
5#include <map>
6
7#include "../_cexports/c_foundation.h"
8
9#include "../global.hpp"
10#include "../image.hpp"
11#include "../value_range.hpp"
12#include "../exception.hpp"
13#include "../point_2d.hpp"
14#include "../rect.hpp"
15#include "../size_2d.hpp"
16#include "../angle.hpp"
17
18#include <vector>
19#include <memory>
20
21namespace Cvb
22{
23
24CVB_BEGIN_INLINE_NS
25
26namespace Foundation
27{
28
30
39namespace Blob
40{
41
42
45{
47 Size,
49 Width,
51 Height
52};
53
55
59{
61 None = 0,
63 Right = 1,
65 Top = 2,
67 Left = 4,
69 Bottom = 8,
71 All = 15
72};
73
75{
76 return static_cast<BlobBorderFilter>(static_cast<std::uint32_t>(a) | static_cast<std::uint32_t>(b));
77}
78
79class BlobResult;
80class BlobFilter;
81
82inline std::vector<BlobResult> BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold);
83inline std::vector<BlobResult> BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, Rect<int> aoi);
84inline std::vector<BlobResult> BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, const BlobFilter & filter);
85inline std::vector<BlobResult> BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, Rect<int> aoi, const BlobFilter & filter);
86inline std::vector<BlobResult> SearchBlobs(const Image & binarizedImage);
87inline std::vector<BlobResult> SearchBlobs(const Image & binarizedImage, Rect<int> aoi);
88inline std::vector<BlobResult> SearchBlobs(const Image & binarizedImage, const BlobFilter & filter);
89inline std::vector<BlobResult> SearchBlobs(const Image & binarizedImage, Rect<int> aoi, const BlobFilter & filter);
90
91namespace Internal
92{
93
94class BlobAnalyzer final
95{
96 friend class BlobResult;
97 friend class BlobFilter;
98
99 friend std::vector<BlobResult> Blob::BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold);
100 friend std::vector<BlobResult> Blob::BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, Rect<int> aoi);
101 friend std::vector<BlobResult> Blob::BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, const BlobFilter & filter);
102 friend std::vector<BlobResult> Blob::BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, Rect<int> aoi, const BlobFilter & filter);
103 friend std::vector<BlobResult> Blob::SearchBlobs(const Image & binarizedImage);
104 friend std::vector<BlobResult> Blob::SearchBlobs(const Image & binarizedImage, Rect<int> aoi);
105 friend std::vector<BlobResult> Blob::SearchBlobs(const Image & binarizedImage, const BlobFilter & filter);
106 friend std::vector<BlobResult> Blob::SearchBlobs(const Image & binarizedImage, Rect<int> aoi, const BlobFilter & filter);
107
108 private:
109
110
111 explicit BlobAnalyzer(const ImagePlane& plane)
112 : handle_(CExports::FBlobCreate(plane_.Parent().Handle(), static_cast<CExports::cvbdim_t>(plane_.Plane())))
113 , plane_(plane)
114 {
115 if (!handle_.Handle())
116 Utilities::SystemInfo::ThrowLastError();
117 }
118
119
120
121
122 void* Handle() const noexcept
123 {
124 return handle_.Handle();
125 }
126
127 void SetAOI(Rect<int> aoi)
128 {
129 auto result = CVB_CALL_CAPI(FBlobSetArea(Handle(),
130 static_cast<CExports::cvbdim_t>(plane_.Plane()),
131 static_cast<CExports::cvbdim_t>(aoi.Left()),
132 static_cast<CExports::cvbdim_t>(aoi.Top()),
133 static_cast<CExports::cvbdim_t>(aoi.Right()),
134 static_cast<CExports::cvbdim_t>(aoi.Bottom())));
135 if (result < 0)
136 Utilities::SystemInfo::ThrowLastError(result);
137 }
138
139 void SetSkipBinarzation(bool skip)
140 {
141 auto result = CVB_CALL_CAPI(FBlobSetSkipBinarization(Handle(),
142 skip ? 1 : 0));
143 if (result < 0)
144 Utilities::SystemInfo::ThrowLastError(result);
145 }
146
147 void SetBorderFilter(BlobBorderFilter borderFilter)
148 {
149 auto result = CVB_CALL_CAPI(FBlobSetObjectTouchBorder(Handle(),
150 static_cast<CExports::cvbval_t>(borderFilter)));
151 if (result < 0)
152 Utilities::SystemInfo::ThrowLastError(result);
153 }
154
155 void SetSizeFilter(ValueRange<int> sizeFilter)
156 {
157 auto result = CVB_CALL_CAPI(FBlobSetLimitArea(Handle(),
158 static_cast<CExports::cvbval_t>(sizeFilter.Min()),
159 static_cast<CExports::cvbval_t>(sizeFilter.Max())));
160 if (result < 0)
161 Utilities::SystemInfo::ThrowLastError(result);
162 }
163
164 void SetWidthFilter(ValueRange<int> widthFilter)
165 {
166 auto result = CVB_CALL_CAPI(FBlobSetLimitWidth(Handle(),
167 static_cast<CExports::cvbval_t>(widthFilter.Min()),
168 static_cast<CExports::cvbval_t>(widthFilter.Max())));
169 if (result < 0)
170 Utilities::SystemInfo::ThrowLastError(result);
171 }
172
173 void SetHeightFilter(ValueRange<int> heightFilter)
174 {
175 auto result = CVB_CALL_CAPI(FBlobSetLimitHeight(Handle(),
176 static_cast<CExports::cvbval_t>(heightFilter.Min()),
177 static_cast<CExports::cvbval_t>(heightFilter.Max())));
178 if (result < 0)
179 Utilities::SystemInfo::ThrowLastError(result);
180 }
181
182 void SetBinarizationRange(ValueRange<int> binarizationRange)
183 {
184 auto result = CVB_CALL_CAPI(FBlobSetObjectFeatureRange(Handle(),
185 static_cast<CExports::cvbval_t>(binarizationRange.Min()),
186 static_cast<CExports::cvbval_t>(binarizationRange.Max())));
187 if (result < 0)
188 Utilities::SystemInfo::ThrowLastError(result);
189 }
190
192
193 const ImagePlane & plane_;
194
195
196
197 ReleaseObjectGuard handle_;
198};
199
200}
201
203
205class BlobResult final
206{
207 friend class Internal::BlobAnalyzer;
208
209 public:
210
211 BlobResult() noexcept
212 : boundingBox_(Rect<int>())
213 {}
214
215
217
221 double X() const noexcept
222 {
223 return center_.X();
224 }
225
227
231 double Y() const noexcept
232 {
233 return center_.Y();
234 }
235
237
241 Point2D<double> Center() const noexcept
242 {
243 return center_;
244 }
245
247
251 double Size() const noexcept
252 {
253 return size_;
254 }
255
257
261 Rect<int> BoundingBox() const noexcept
262 {
263 return boundingBox_;
264 }
265
267
271 double MinimumMoment() const noexcept
272 {
273 return minimumMoment_;
274 }
275
277
281 double MaximumMoment() const noexcept
282 {
283 return maximumMoment_;
284 }
285
287
291 double MomentRatio() const noexcept
292 {
293 return momentRatio_;
294 }
295
297
301 Angle MomentAngle() const noexcept
302 {
303 return momentAngle_;
304 }
305
307
312 {
313 return minimummomentPoints_;
314 }
315
316 private:
317
318
319 BlobResult(const Internal::BlobAnalyzer& analyzer, int index) noexcept
320 {
321 // for speed reasons (this ctor will be called potentially very
322 // often...) there will be no consistency checks here...
323 double x = 0.0;
324 double y = 0.0;
325 CVB_CALL_CAPI(FBlobGetCenterEx(analyzer.Handle(), index, x, y));
326 center_ = Point2D<double>(x, y);
327
328 CExports::cvbval_t size = 0;
329 CVB_CALL_CAPI(FBlobGetSize(analyzer.Handle(), index, size));
330 size_ = static_cast<double>(size);
331
332 CExports::cvbdim_t left = 0;
333 CExports::cvbdim_t top = 0;
334 CExports::cvbdim_t width = 0;
335 CExports::cvbdim_t height = 0;
336 CVB_CALL_CAPI(FBlobGetBoundingBoxEx(analyzer.Handle(), index, left, top, width, height));
337 boundingBox_ = Rect<int>(Point2D<int>(static_cast<int>(left), static_cast<int>(top)),
338 Size2D<int>(static_cast<int>(width), static_cast<int>(height)));
339
340 double angleRad = 0.0;
341 CVB_CALL_CAPI(FBlobGetMoments(analyzer.Handle(), index, minimumMoment_, maximumMoment_, momentRatio_, angleRad));
342 momentAngle_ = Angle::FromRadians(angleRad);
343
344 CExports::cvbval_t x0 = 0;
345 CExports::cvbval_t y0 = 0;
346 CExports::cvbval_t x1 = 0;
347 CExports::cvbval_t y1 = 0;
348 CVB_CALL_CAPI(FBlobGetMinMomentPointsEx(analyzer.Handle(), index, x0, y0, x1, y1));
349 minimummomentPoints_ = { Point2D<int>(static_cast<int>(x0), static_cast<int>(y0)),
350 Point2D<int>(static_cast<int>(x1), static_cast<int>(y1)) };
351 }
352
353 Point2D<double> center_;
354 double size_ = 0.0;
355 Rect<int> boundingBox_;
356 double minimumMoment_ = 0.0;
357 double maximumMoment_ = 0.0;
358 double momentRatio_ = 0.0;
359 Angle momentAngle_;
360 std::vector<Point2D<int>> minimummomentPoints_;
361
362};
363
364
365inline std::vector<BlobResult> Internal::BlobAnalyzer::Run()
366{
367 auto resutlExec = CExports::FBlobExec(Handle());
368 if (resutlExec < 0)
369 Utilities::SystemInfo::ThrowLastError(resutlExec);
370
371 CExports::cvbval_t numBlobs = 0;
372 auto resultNumBlobs = CExports::FBlobGetNumBlobs(Handle(), numBlobs);
373 if (resutlExec < 0)
374 Utilities::SystemInfo::ThrowLastError(resultNumBlobs);
375
376 std::vector<BlobResult> results(static_cast<std::size_t>(numBlobs));
377 for (int i = 0; i < static_cast<int>(numBlobs); ++i)
378 results[i] = BlobResult(*this, i);
379
380 return results;
381}
382
384
386class BlobFilter final
387{
388 friend std::vector<BlobResult> BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, const BlobFilter & filter);
389 friend std::vector<BlobResult> BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, Rect<int> aoi, const BlobFilter & filter);
390 friend std::vector<BlobResult> SearchBlobs(const Image & binarizedImage, const BlobFilter & filter);
391 friend std::vector<BlobResult> SearchBlobs(const Image & binarizedImage, Rect<int> aoi, const BlobFilter & filter);
392
393 public:
394
395
397
400 BlobFilter() = default;
401
402
404
409 {
410 return borderFilter_;
411 }
412
414
419 {
420 borderFilter_ = borderFilter;
421 }
422
424
429 bool ContainsRangeFilter(BlobRangeFilter rangeFilter) const noexcept
430 {
431 return rangeFilters_.find(rangeFilter) != rangeFilters_.end();
432 }
433
434
435
437
446 {
447 return rangeFilters_[rangeFilter];
448 }
449
450 private:
451
452 void Apply(Internal::BlobAnalyzer & analyzer) const
453 {
455 analyzer.SetBorderFilter(borderFilter_);
457 analyzer.SetSizeFilter(rangeFilters_[BlobRangeFilter::Size]);
459 analyzer.SetWidthFilter(rangeFilters_[BlobRangeFilter::Width]);
461 analyzer.SetHeightFilter(rangeFilters_[BlobRangeFilter::Height]);
462 }
463
465 mutable std::map<BlobRangeFilter, ValueRange<int>> rangeFilters_;
466};
467
468
469
470
471
472
473
474
475
477
484{
485 Internal::BlobAnalyzer analyzer(plane);
486 analyzer.SetBinarizationRange(binarizationThreshold);
487 return analyzer.Run();
488}
489
490
491
493
501{
502 Internal::BlobAnalyzer analyzer(plane);
503 analyzer.SetBinarizationRange(binarizationThreshold);
504 analyzer.SetAOI(aoi);
505 return analyzer.Run();
506}
507
508
509
511
518inline std::vector<BlobResult> BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, const BlobFilter & filter)
519{
520 Internal::BlobAnalyzer analyzer(plane);
521 analyzer.SetBinarizationRange(binarizationThreshold);
522 filter.Apply(analyzer);
523 return analyzer.Run();
524}
525
526
527
529
537inline std::vector<BlobResult> BinarizeAndSearchBlobs(const ImagePlane & plane, ValueRange<int> binarizationThreshold, Rect<int> aoi, const BlobFilter & filter)
538{
539 Internal::BlobAnalyzer analyzer(plane);
540 analyzer.SetBinarizationRange(binarizationThreshold);
541 analyzer.SetAOI(aoi);
542 filter.Apply(analyzer);
543 return analyzer.Run();
544}
545
546
548
555inline std::vector<BlobResult> SearchBlobs(const Image & binarizedImage)
556{
557 Internal::BlobAnalyzer analyzer(binarizedImage.Plane(0));
558 analyzer.SetSkipBinarzation(true);
559 return analyzer.Run();
560}
561
563
571inline std::vector<BlobResult> SearchBlobs(const Image & binarizedImage, Rect<int> aoi)
572{
573 Internal::BlobAnalyzer analyzer(binarizedImage.Plane(0));
574 analyzer.SetSkipBinarzation(true);
575 analyzer.SetAOI(aoi);
576 return analyzer.Run();
577}
578
580
588inline std::vector<BlobResult> SearchBlobs(const Image & binarizedImage, const BlobFilter & filter)
589{
590 Internal::BlobAnalyzer analyzer(binarizedImage.Plane(0));
591 analyzer.SetSkipBinarzation(true);
592 filter.Apply(analyzer);
593 return analyzer.Run();
594}
595
597
606inline std::vector<BlobResult> SearchBlobs(const Image & binarizedImage, Rect<int> aoi, const BlobFilter & filter)
607{
608 Internal::BlobAnalyzer analyzer(binarizedImage.Plane(0));
609 analyzer.SetSkipBinarzation(true);
610 analyzer.SetAOI(aoi);
611 filter.Apply(analyzer);
612 return analyzer.Run();
613}
614
615
616}
617
620using Blob::BlobResult;
621using Blob::BlobFilter;
624
625
626
627
628}
629
630
631
632
633CVB_END_INLINE_NS
634
635}
636
637#endif
Object for convenient and type - safe handling of angles.
Definition: angle.hpp:19
static Angle FromRadians(double rad, bool trim=false) noexcept
Create an angle in radians.
Definition: angle.hpp:44
Class to build a filter for the blob search.
Definition: blob.hpp:387
BlobFilter()=default
Default filter without any filter set.
friend std::vector< BlobResult > BinarizeAndSearchBlobs(const ImagePlane &plane, ValueRange< int > binarizationThreshold, const BlobFilter &filter)
Searches for all blobs in the given image plane.
Definition: blob.hpp:518
ValueRange< int > & operator[](BlobRangeFilter rangeFilter)
Sets the range filters via an attribute.
Definition: blob.hpp:445
Cvb::Foundation::Blob::BlobBorderFilter BorderFilter() const noexcept
Gets whether to filter blobs that touch the borders of the image.
Definition: blob.hpp:408
bool ContainsRangeFilter(BlobRangeFilter rangeFilter) const noexcept
Check if a range filter exists.
Definition: blob.hpp:429
void SetBorderFilter(Cvb::Foundation::Blob::BlobBorderFilter borderFilter) noexcept
Sets whether to filter blobs that touch the borders of the image.
Definition: blob.hpp:418
friend std::vector< BlobResult > SearchBlobs(const Image &binarizedImage, const BlobFilter &filter)
Searches for all blobs in the given binarized image.
Definition: blob.hpp:588
Container for a blob analysis result.
Definition: blob.hpp:206
std::vector< Point2D< int > > MinimumMomentPoints() const
Points where the major axis of the blob intersects with the blob's bounding box.
Definition: blob.hpp:311
Angle MomentAngle() const noexcept
Angle between Major moment axis and the x-axis.
Definition: blob.hpp:301
Point2D< double > Center() const noexcept
Position of the blob's center.
Definition: blob.hpp:241
double Size() const noexcept
Size (area) of the blob in pixels.
Definition: blob.hpp:251
Rect< int > BoundingBox() const noexcept
Bounding box of the blob.
Definition: blob.hpp:261
double Y() const noexcept
Get Y component of the blob center.
Definition: blob.hpp:231
double MinimumMoment() const noexcept
Minimum inertial moment (smaller 2nd order moment translated into the blob's major/minor axis coordin...
Definition: blob.hpp:271
double X() const noexcept
Get X component of the blob center.
Definition: blob.hpp:221
double MomentRatio() const noexcept
Ratio of the minimum moment and the maximum moment of this blob.
Definition: blob.hpp:291
double MaximumMoment() const noexcept
Maximum inertial moment (larger 2nd order moments translated into the blob's major/minor axis coordin...
Definition: blob.hpp:281
The Common Vision Blox image.
Definition: decl_image.hpp:45
ImagePlane Plane(int plane) const
Indexed access to the individual plane information.
Definition: detail_image.hpp:65
Image plane information container.
Definition: decl_image_plane.hpp:33
Plane information container.
Definition: decl_plane.hpp:28
T X() const noexcept
Gets the x-component of the point.
Definition: point_2d.hpp:86
T Y() const noexcept
Gets the y-component of the point.
Definition: point_2d.hpp:106
std::vector< BlobResult > BinarizeAndSearchBlobs(const ImagePlane &plane, ValueRange< int > binarizationThreshold)
Searches for all blobs in the given image plane.
Definition: blob.hpp:483
BlobBorderFilter
Enumeration for filtering blobs that touch the boundaries of the AOI specified for blob extraction.
Definition: blob.hpp:59
@ None
Do not filter out those blobs that touch a border.
BlobRangeFilter
Defines the attribute for a blob filter range.
Definition: blob.hpp:45
@ Width
Width of the blob in pixels.
@ Size
Area of the blob in pixels.
@ Height
Height of the blob in pixels.
std::vector< BlobResult > SearchBlobs(const Image &binarizedImage)
Searches for all blobs in the given binarized image.
Definition: blob.hpp:555
Root namespace for the Image Manager interface.
Definition: c_barcode.h:24