CVB++ 15.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
24 CVB_BEGIN_INLINE_NS
25
26 namespace Foundation
27 {
28
30
40 namespace Blob
41 {
42
44 enum class BlobRangeFilter
45 {
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
79 class BlobResult;
80 class BlobFilter;
81
83 ValueRange<int> binarizationThreshold);
85 ValueRange<int> binarizationThreshold, Rect<int> aoi);
87 BinarizeAndSearchBlobs(const ImagePlane &plane, ValueRange<int> binarizationThreshold, const BlobFilter &filter);
89 ValueRange<int> binarizationThreshold, Rect<int> aoi,
90 const BlobFilter &filter);
91 inline std::vector<BlobResult> SearchBlobs(const Image &binarizedImage);
92 inline std::vector<BlobResult> SearchBlobs(const Image &binarizedImage, Rect<int> aoi);
93 inline std::vector<BlobResult> SearchBlobs(const Image &binarizedImage, const BlobFilter &filter);
94 inline std::vector<BlobResult> SearchBlobs(const Image &binarizedImage, Rect<int> aoi, const BlobFilter &filter);
95
96 namespace Internal
97 {
98
99 class BlobAnalyzer final
100 {
101 friend class BlobResult;
102 friend class BlobFilter;
103
105 ValueRange<int> binarizationThreshold);
107 Blob::BinarizeAndSearchBlobs(const ImagePlane &plane, ValueRange<int> binarizationThreshold, Rect<int> aoi);
109 ValueRange<int> binarizationThreshold,
110 const BlobFilter &filter);
112 ValueRange<int> binarizationThreshold,
113 Rect<int> aoi, const BlobFilter &filter);
114 friend std::vector<BlobResult> Blob::SearchBlobs(const Image &binarizedImage);
115 friend std::vector<BlobResult> Blob::SearchBlobs(const Image &binarizedImage, Rect<int> aoi);
116 friend std::vector<BlobResult> Blob::SearchBlobs(const Image &binarizedImage, const BlobFilter &filter);
117 friend std::vector<BlobResult> Blob::SearchBlobs(const Image &binarizedImage, Rect<int> aoi,
118 const BlobFilter &filter);
119
120 private:
121 explicit BlobAnalyzer(const ImagePlane &plane)
122 : handle_(
123 CExports::FBlobCreate(plane_.Parent().Handle(), static_cast<CExports::cvbdim_t>(plane_.Plane())))
124 , plane_(plane)
125 {
126 if (!handle_.Handle())
127 Utilities::SystemInfo::ThrowLastError();
128 }
129
130 void *Handle() const noexcept
131 {
132 return handle_.Handle();
133 }
134
135 void SetAOI(Rect<int> aoi)
136 {
137 auto result = CVB_CALL_CAPI(FBlobSetArea(
138 Handle(), static_cast<CExports::cvbdim_t>(plane_.Plane()), static_cast<CExports::cvbdim_t>(aoi.Left()),
139 static_cast<CExports::cvbdim_t>(aoi.Top()), static_cast<CExports::cvbdim_t>(aoi.Right()),
140 static_cast<CExports::cvbdim_t>(aoi.Bottom())));
141 if (result < 0)
142 Utilities::SystemInfo::ThrowLastError(result);
143 }
144
145 void SetSkipBinarzation(bool skip)
146 {
147 auto result = CVB_CALL_CAPI(FBlobSetSkipBinarization(Handle(), skip ? 1 : 0));
148 if (result < 0)
149 Utilities::SystemInfo::ThrowLastError(result);
150 }
151
152 void SetBorderFilter(BlobBorderFilter borderFilter)
153 {
154 auto result =
155 CVB_CALL_CAPI(FBlobSetObjectTouchBorder(Handle(), static_cast<CExports::cvbval_t>(borderFilter)));
156 if (result < 0)
157 Utilities::SystemInfo::ThrowLastError(result);
158 }
159
160 void SetSizeFilter(ValueRange<int> sizeFilter)
161 {
162 auto result = CVB_CALL_CAPI(FBlobSetLimitArea(Handle(), static_cast<CExports::cvbval_t>(sizeFilter.Min()),
163 static_cast<CExports::cvbval_t>(sizeFilter.Max())));
164 if (result < 0)
165 Utilities::SystemInfo::ThrowLastError(result);
166 }
167
168 void SetWidthFilter(ValueRange<int> widthFilter)
169 {
170 auto result = CVB_CALL_CAPI(FBlobSetLimitWidth(Handle(), static_cast<CExports::cvbval_t>(widthFilter.Min()),
171 static_cast<CExports::cvbval_t>(widthFilter.Max())));
172 if (result < 0)
173 Utilities::SystemInfo::ThrowLastError(result);
174 }
175
176 void SetHeightFilter(ValueRange<int> heightFilter)
177 {
178 auto result =
179 CVB_CALL_CAPI(FBlobSetLimitHeight(Handle(), static_cast<CExports::cvbval_t>(heightFilter.Min()),
180 static_cast<CExports::cvbval_t>(heightFilter.Max())));
181 if (result < 0)
182 Utilities::SystemInfo::ThrowLastError(result);
183 }
184
185 void SetBinarizationRange(ValueRange<int> binarizationRange)
186 {
187 auto result = CVB_CALL_CAPI(
188 FBlobSetObjectFeatureRange(Handle(), static_cast<CExports::cvbval_t>(binarizationRange.Min()),
189 static_cast<CExports::cvbval_t>(binarizationRange.Max())));
190 if (result < 0)
191 Utilities::SystemInfo::ThrowLastError(result);
192 }
193
194 std::vector<BlobResult> Run();
195
196 const ImagePlane &plane_;
197
198 ReleaseObjectGuard handle_;
199 };
200
201 } // namespace Internal
202
204
206 class BlobResult final
207 {
208 friend class Internal::BlobAnalyzer;
209
210 public:
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
268
272 double MinimumMoment() const noexcept
273 {
274 return minimumMoment_;
275 }
276
279
283 double MaximumMoment() const noexcept
284 {
285 return maximumMoment_;
286 }
287
289
293 double MomentRatio() const noexcept
294 {
295 return momentRatio_;
296 }
297
299
303 Angle MomentAngle() const noexcept
304 {
305 return momentAngle_;
306 }
307
309
314 {
315 return minimummomentPoints_;
316 }
317
318 private:
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(
342 FBlobGetMoments(analyzer.Handle(), index, minimumMoment_, maximumMoment_, momentRatio_, angleRad));
343 momentAngle_ = Angle::FromRadians(angleRad);
344
345 CExports::cvbval_t x0 = 0;
346 CExports::cvbval_t y0 = 0;
347 CExports::cvbval_t x1 = 0;
348 CExports::cvbval_t y1 = 0;
349 CVB_CALL_CAPI(FBlobGetMinMomentPointsEx(analyzer.Handle(), index, x0, y0, x1, y1));
350 minimummomentPoints_ = {Point2D<int>(static_cast<int>(x0), static_cast<int>(y0)),
351 Point2D<int>(static_cast<int>(x1), static_cast<int>(y1))};
352 }
353
354 Point2D<double> center_;
355 double size_ = 0.0;
356 Rect<int> boundingBox_;
357 double minimumMoment_ = 0.0;
358 double maximumMoment_ = 0.0;
359 double momentRatio_ = 0.0;
360 Angle momentAngle_;
361 std::vector<Point2D<int>> minimummomentPoints_;
362 };
363
364 inline std::vector<BlobResult> Internal::BlobAnalyzer::Run()
365 {
366 auto resutlExec = CExports::FBlobExec(Handle());
367 if (resutlExec < 0)
368 Utilities::SystemInfo::ThrowLastError(resutlExec);
369
370 CExports::cvbval_t numBlobs = 0;
371 auto resultNumBlobs = CExports::FBlobGetNumBlobs(Handle(), numBlobs);
372 if (resutlExec < 0)
373 Utilities::SystemInfo::ThrowLastError(resultNumBlobs);
374
375 std::vector<BlobResult> results(static_cast<std::size_t>(numBlobs));
376 for (int i = 0; i < static_cast<int>(numBlobs); ++i)
377 results[i] = BlobResult(*this, i);
378
379 return results;
380 }
381
383
385 class BlobFilter final
386 {
388 ValueRange<int> binarizationThreshold,
389 const BlobFilter &filter);
391 ValueRange<int> binarizationThreshold, Rect<int> aoi,
392 const BlobFilter &filter);
393 friend std::vector<BlobResult> SearchBlobs(const Image &binarizedImage, const BlobFilter &filter);
394 friend std::vector<BlobResult> SearchBlobs(const Image &binarizedImage, Rect<int> aoi,
395 const BlobFilter &filter);
396
397 public:
399
402 BlobFilter() = default;
403
405
410 {
411 return borderFilter_;
412 }
413
415
420 {
421 borderFilter_ = borderFilter;
422 }
423
425
430 bool ContainsRangeFilter(BlobRangeFilter rangeFilter) const noexcept
431 {
432 return rangeFilters_.find(rangeFilter) != rangeFilters_.end();
433 }
434
436
445 {
446 return rangeFilters_[rangeFilter];
447 }
448
449 private:
450 void Apply(Internal::BlobAnalyzer &analyzer) const
451 {
453 analyzer.SetBorderFilter(borderFilter_);
454 if (ContainsRangeFilter(BlobRangeFilter::Size))
455 analyzer.SetSizeFilter(rangeFilters_[BlobRangeFilter::Size]);
456 if (ContainsRangeFilter(BlobRangeFilter::Width))
457 analyzer.SetWidthFilter(rangeFilters_[BlobRangeFilter::Width]);
458 if (ContainsRangeFilter(BlobRangeFilter::Height))
459 analyzer.SetHeightFilter(rangeFilters_[BlobRangeFilter::Height]);
460 }
461
463 mutable std::map<BlobRangeFilter, ValueRange<int>> rangeFilters_;
464 };
465
467
474 ValueRange<int> binarizationThreshold)
475 {
476 Internal::BlobAnalyzer analyzer(plane);
477 analyzer.SetBinarizationRange(binarizationThreshold);
478 return analyzer.Run();
479 }
480
482
490 ValueRange<int> binarizationThreshold, Rect<int> aoi)
491 {
492 Internal::BlobAnalyzer analyzer(plane);
493 analyzer.SetBinarizationRange(binarizationThreshold);
494 analyzer.SetAOI(aoi);
495 return analyzer.Run();
496 }
497
499
507 BinarizeAndSearchBlobs(const ImagePlane &plane, ValueRange<int> binarizationThreshold, const BlobFilter &filter)
508 {
509 Internal::BlobAnalyzer analyzer(plane);
510 analyzer.SetBinarizationRange(binarizationThreshold);
511 filter.Apply(analyzer);
512 return analyzer.Run();
513 }
514
516
525 ValueRange<int> binarizationThreshold, Rect<int> aoi,
526 const BlobFilter &filter)
527 {
528 Internal::BlobAnalyzer analyzer(plane);
529 analyzer.SetBinarizationRange(binarizationThreshold);
530 analyzer.SetAOI(aoi);
531 filter.Apply(analyzer);
532 return analyzer.Run();
533 }
534
536
543 inline std::vector<BlobResult> SearchBlobs(const Image &binarizedImage)
544 {
545 Internal::BlobAnalyzer analyzer(binarizedImage.Plane(0));
546 analyzer.SetSkipBinarzation(true);
547 return analyzer.Run();
548 }
549
551
559 inline std::vector<BlobResult> SearchBlobs(const Image &binarizedImage, Rect<int> aoi)
560 {
561 Internal::BlobAnalyzer analyzer(binarizedImage.Plane(0));
562 analyzer.SetSkipBinarzation(true);
563 analyzer.SetAOI(aoi);
564 return analyzer.Run();
565 }
566
568
576 inline std::vector<BlobResult> SearchBlobs(const Image &binarizedImage, const BlobFilter &filter)
577 {
578 Internal::BlobAnalyzer analyzer(binarizedImage.Plane(0));
579 analyzer.SetSkipBinarzation(true);
580 filter.Apply(analyzer);
581 return analyzer.Run();
582 }
583
585
594 inline std::vector<BlobResult> SearchBlobs(const Image &binarizedImage, Rect<int> aoi, const BlobFilter &filter)
595 {
596 Internal::BlobAnalyzer analyzer(binarizedImage.Plane(0));
597 analyzer.SetSkipBinarzation(true);
598 analyzer.SetAOI(aoi);
599 filter.Apply(analyzer);
600 return analyzer.Run();
601 }
602
603 } // namespace Blob
604
607 using Blob::BlobFilter;
609 using Blob::BlobResult;
610 using Blob::SearchBlobs;
611
612 } // namespace Foundation
613
614 CVB_END_INLINE_NS
615
616} // namespace Cvb
617
618#endif
Object for convenient and type - safe handling of angles.
Definition angle.hpp:16
static Angle FromRadians(double rad, bool trim=false) noexcept
Create an angle in radians.
Definition angle.hpp:39
Class to build a filter for the blob search.
Definition blob.hpp:386
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:507
ValueRange< int > & operator[](BlobRangeFilter rangeFilter)
Sets the range filters via an attribute.
Definition blob.hpp:444
Cvb::Foundation::Blob::BlobBorderFilter BorderFilter() const noexcept
Gets whether to filter blobs that touch the borders of the image.
Definition blob.hpp:409
bool ContainsRangeFilter(BlobRangeFilter rangeFilter) const noexcept
Check if a range filter exists.
Definition blob.hpp:430
void SetBorderFilter(Cvb::Foundation::Blob::BlobBorderFilter borderFilter) noexcept
Sets whether to filter blobs that touch the borders of the image.
Definition blob.hpp:419
friend std::vector< BlobResult > SearchBlobs(const Image &binarizedImage, const BlobFilter &filter)
Searches for all blobs in the given binarized image.
Definition blob.hpp:576
Container for a blob analysis result.
Definition blob.hpp:207
std::vector< Point2D< int > > MinimumMomentPoints() const
Points where the major axis of the blob intersects with the blob's bounding box.
Definition blob.hpp:313
Angle MomentAngle() const noexcept
Angle between Major moment axis and the x-axis.
Definition blob.hpp:303
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:272
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:293
double MaximumMoment() const noexcept
Maximum inertial moment (larger 2nd order moments translated into the blob's major/minor axis coordin...
Definition blob.hpp:283
Class to build a filter for the blob search.
Definition blob.hpp:386
Container for a blob analysis result.
Definition blob.hpp:207
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:58
Image plane information container.
Definition decl_image_plane.hpp:29
Plane information container.
Definition decl_plane.hpp:25
Multi-purpose 2D vector class.
Definition point_2d.hpp:20
Rectangle object.
Definition rect.hpp:24
Stores a pair of numbers that represents the width and the height of a subject, typically a rectangle...
Definition size_2d.hpp:20
Container for range definitions.
Definition value_range.hpp:17
cvbres_t FBlobSetLimitWidth(FBLOB Handle, long Min, long Max)
cvbres_t FBlobSetArea(FBLOB Handle, long Index, long left, long top, long right, long bottom)
cvbres_t FBlobGetCenterEx(FBLOB Handle, long BlobNum, double &CenterX, double &CenterY)
FBLOB FBlobCreate(IMG Image, long Index)
cvbres_t FBlobSetLimitArea(FBLOB Handle, long AreaMin, long AreaMax)
cvbres_t FBlobSetLimitHeight(FBLOB Handle, long Min, long Max)
cvbres_t FBlobGetBoundingBoxEx(FBLOB Handle, long BlobNum, long &x, long &y, long &dx, long &dy)
cvbres_t FBlobSetObjectTouchBorder(FBLOB Handle, long Mask)
cvbres_t FBlobGetSize(FBLOB Handle, long BlobNum, long &Size)
cvbres_t FBlobGetMoments(FBLOB Handle, long BlobNum, double &Min, double &Max, double &Ratio, double &Angle)
cvbres_t FBlobGetMinMomentPointsEx(FBLOB Handle, long BlobNum, long &x0, long &y0, long &x1, long &y1)
cvbres_t FBlobSetSkipBinarization(FBLOB Handle, cvbbool_t Skip)
cvbres_t FBlobSetObjectFeatureRange(FBLOB Handle, long FeatureMin, long FeatureMax)
Blob search methods.
Definition blob.hpp:41
std::vector< BlobResult > BinarizeAndSearchBlobs(const ImagePlane &plane, ValueRange< int > binarizationThreshold)
Searches for all blobs in the given image plane.
Definition blob.hpp:473
BlobBorderFilter
Enumeration for filtering blobs that touch the boundaries of the AOI specified for blob extraction.
Definition blob.hpp:59
@ Bottom
Filter out those blobs that touch the bottom border.
Definition blob.hpp:69
@ None
Do not filter out those blobs that touch a border.
Definition blob.hpp:61
@ Right
Filter out those blobs that touch the right border.
Definition blob.hpp:63
@ Left
Filter out those blobs that touch the left border.
Definition blob.hpp:67
@ Top
Filter out those blobs that touch the top border.
Definition blob.hpp:65
@ All
Filter out those blobs that touch any border.
Definition blob.hpp:71
BlobRangeFilter
Defines the attribute for a blob filter range.
Definition blob.hpp:45
@ Width
Width of the blob in pixels.
Definition blob.hpp:49
@ Size
Area of the blob in pixels.
Definition blob.hpp:47
@ Height
Height of the blob in pixels.
Definition blob.hpp:51
std::vector< BlobResult > SearchBlobs(const Image &binarizedImage)
Searches for all blobs in the given binarized image.
Definition blob.hpp:543
Namespace for the Foundation package.
Definition decl_metric_aqs12_calibration_piece.hpp:11
Root namespace for the Image Manager interface.
Definition c_bayer_to_rgb.h:17