classifier_factory.hpp
1 #pragma once
2 
3 #include "../angle.hpp"
4 #include "../value_range.hpp"
5 #include "../point_2d.hpp"
6 #include "../_detail/detail_pixel_list.hpp"
7 #include "../image.hpp"
8 
9 #include "shapefinder2.hpp"
10 #include "classifier.hpp"
11 
12 
13 namespace Cvb
14 {
15 CVB_BEGIN_INLINE_NS
16 
17 
18 
19 namespace ShapeFinder2
20 {
21 
22 
24 
26 class ClassifierFactory final
27 {
28 public:
29 
31 
34  ClassifierFactory() noexcept = default;
35  virtual ~ClassifierFactory() = default;
36 
37 
39 
47  {
48  if ((plane.DataType().BitsPerPixel() != 8) || (!plane.DataType().IsUnsignedInteger()))
49  std::rethrow_exception(CvbException::FromCvbResult(ErrorCodes::CVB_INVALIDDATATYPE, "invalid plane datatype"));
50 
51  CExports::cvbval_t retval[256];
52  CExports::SFGradHistogram(plane.Parent().Handle(), plane.Plane(), aoi.Left(), aoi.Top(), aoi.Right(), aoi.Bottom(), static_cast<CExports::TSFGradientType>(gradient), &retval[0]);
53  return std::vector<int>(retval, retval + sizeof retval / sizeof retval[0]);
54  }
55 
57 
62  {
64  }
65 
67 
72  {
73  return rotationRange_;
74  }
75 
77 
82  {
83  if (value.Min() < RotationRangeMax().Min() || value.Max() > RotationRangeMax().Max())
84  throw std::out_of_range("rotation range must be in [-180.0, 180.0]");
85  rotationRange_ = value;
86  }
87 
89 
94  {
95  return ValueRange<double>(0.66, 1.50);
96  }
97 
99 
104  {
105  return scaleRange_;
106  }
107 
109 
114  {
115  if (value.Min() < ScaleRangeMax().Min() || value.Max() > ScaleRangeMax().Max())
116  throw std::out_of_range("scale range must be in [0.66, 1.50]");
117  scaleRange_ = value;
118  }
119 
121 
125  int FeatureCount() const noexcept // Function exists twice
126  {
127  return featureCount_;
128  }
129 
131 
135  void SetFeatureCount(int value)
136  {
137  if (value < FeatureCountMin)
138  throw std::out_of_range("feature count must be >= " + FeatureCountMin);
139  featureCount_ = value;
140  }
141 
143 
147  int ContrastThreshold() const noexcept
148  {
149  return contrastThreshold_;
150  }
151 
153 
157  void SetContrastThreshold(int value)
158  {
159  if (value < ContrastThresholdMin)
160  throw std::out_of_range("contrast threshold must be >= " + FeatureCountMin);
161  contrastThreshold_ = value;
162  }
163 
165 
169  int MaxCoarseLayerScale() const noexcept
170  {
171  return maxCoarseScale_;
172  }
173 
175 
179  void SetMaxCoarseLayerScale(int value)
180  {
181  if (value < -1)
182  throw std::out_of_range("maximum coarse layer scale must be >= -1");
183  maxCoarseScale_ = value;
184  }
185 
187 
192  {
193  return contrastMode_;
194  }
195 
197 
202  {
203  contrastMode_ = mode;
204  }
205 
207 
211  int ProfileSize() const noexcept
212  {
213  return profileSize_;
214  }
215 
217 
221  void SetProfileSize(int value)
222  {
223  if (value < 1)
224  throw std::out_of_range("profile size must be >= 1");
225  if ((value % 2) == 0)
226  throw std::invalid_argument("profile size must be %2 != 0");
227  profileSize_ = value;
228  }
229 
231 
235  int ProfileDelta() const noexcept
236  {
237  return profileDelta_;
238  }
239 
241 
245  void SetProfileDelta(int value)
246  {
247  if (value < 1)
248  throw std::out_of_range("profile delta must be >= 1");
249  profileDelta_ = value;
250  }
251 
253 
261  std::unique_ptr<Classifier> Learn(const ImagePlane & plane, Point2D<double> position, Rect<int> teachWindow, const std::vector<Point2D<int>>& dontCarePoints) const
262  {
263  return Learn(plane, position, Angle(), 0.0, teachWindow, dontCarePoints);
264  }
265 
267 
274  std::unique_ptr<Classifier> Learn(const ImagePlane & plane, Point2D<double> position, Rect<int> teachWindow) const
275  {
276  return Learn(plane, position, Angle(), 0.0, teachWindow);
277  }
278 
280 
289  std::unique_ptr<Classifier> Learn(const ImagePlane & plane, Point2D<double> position, Angle angleOffset, double scaleFactor, Rect<int> teachWindow) const
290  {
291  CExports::PIXELLIST dontCarePointsNative = nullptr;
292 
293  if (plane.Parent().Handle() != nullptr && plane.DataType().HasOverlayBit())
294  {
295  CExports::CreatePixelListFromOverlay(plane.Parent().Handle(), plane.Plane(), 0, 0, plane.Parent().Width() - 1, plane.Parent().Height() - 1, dontCarePointsNative);
296  if (dontCarePointsNative)
297  {
298  CExports::TMatrix matrix;
299  matrix.A11 = Matrix2D::Identity().A11();
300  matrix.A12 = Matrix2D::Identity().A12();
301  matrix.A21 = Matrix2D::Identity().A21();
302  matrix.A22 = Matrix2D::Identity().A22();
303  CExports::TransformPixelListMatrix(dontCarePointsNative, matrix, -position.X(), -position.Y());
304  }
305  }
306 
307  return Learn(plane, position, angleOffset, scaleFactor, teachWindow, dontCarePointsNative);
308  }
309 
311 
321  std::unique_ptr<Classifier> Learn(const ImagePlane & plane, Point2D<double> position, Angle angleOffset, double scaleFactor, Rect<int> teachWindow, const std::vector<Point2D<int>>& dontCarePoints) const
322  {
323  CExports::PIXELLIST dontCareList = static_cast<CExports::PIXELLIST>(Point2DToPixelList(dontCarePoints));
324  return Learn(plane, position, angleOffset, scaleFactor, teachWindow, dontCareList);
325  }
326 
327 private:
328 
329  ClassifierFactory(ClassifierFactory & /*other*/) noexcept
330  {
331  }
332 
333  ClassifierFactory & operator=(ClassifierFactory & other) = default;
334 
335  static ValueRange<Angle> RotationRangeDefault() noexcept
336  {
338  }
339 
340  static ValueRange<double> ScaleRangeDefault() noexcept
341  {
342  return ValueRange<double>(1.0, 1.0);
343  }
344 
345  std::unique_ptr<Classifier> Learn(const ImagePlane & plane, Point2D<double> position, Angle angleOffset, double scaleFactor, Rect<int> teachWindow, CExports::PIXELLIST dontCareList ) const
346  {
347  CExports::TSymmetryParams symmetries;
348  symmetries.ContrastMode = (int)contrastMode_;
349  symmetries.A0 = RotationRange().Min().Deg();
350  symmetries.A1 = RotationRange().Max().Deg();
351  symmetries.R0 = ScaleRange().Min();
352  symmetries.R1 = ScaleRange().Max();
353 
354  int maxCoarseScale = MaxCoarseLayerScale();
355  if (maxCoarseScale < 0)
356  maxCoarseScale = 16;
357 
358  CExports::SF sf = nullptr;
359  if (ProfileSize() > 1)
360  {
361  sf = CExports::CreateSF2ExEx(plane.Parent().Handle(), plane.Plane(), (CExports::cvbdim_t)position.X(), (CExports::cvbdim_t)position.Y(), angleOffset.Rad(), scaleFactor
362  , teachWindow.Left(), teachWindow.Top(), teachWindow.Right(), teachWindow.Bottom(), ContrastThreshold(), FeatureCount()
363  , maxCoarseScale, symmetries, dontCareList, true, ProfileSize(), ProfileDelta());
364  }
365  else
366  {
367  sf = CExports::CreateSF2Ex(plane.Parent().Handle(), plane.Plane(), (CExports::cvbdim_t)position.X(), (CExports::cvbdim_t)position.Y(), angleOffset.Rad(), scaleFactor
368  , teachWindow.Left(), teachWindow.Top(), teachWindow.Right(), teachWindow.Bottom(), ContrastThreshold(), FeatureCount()
369  , maxCoarseScale, symmetries, dontCareList);
370  }
371 
372  if (sf == nullptr)
373  Utilities::SystemInfo::ThrowLastError();
374  else
375  return Classifier::FromHandle(HandleGuard<Classifier>(sf));
376 
377  return nullptr;
378  }
379 
380 
381  static Internal::PixelList* Point2DToPixelList(const std::vector<Point2D<int>>& points)
382  {
384  for (std::size_t i = 0; i < points.size(); i++)
385  {
386  tmp.push_back(static_cast<Point2D<double>>(points.at(i)));
387  }
388  auto pixelList = Internal::PixelList::FromPoints (tmp);
389  return pixelList.get();
390  }
391 
392 
393 public:
394  static const int FeatureCountMin = 10;
395  static const int ContrastThresholdMin = 1;
396 
397 private:
398 
399  static const int FeatureCountDefault = 100;
400  static const int ContrastThresholdDefault = 25;
401  static const int MaxCoarseLayerDefault = 8;
402 
403  int featureCount_ = FeatureCountDefault;
404  int contrastThreshold_ = ContrastThresholdDefault;
405  int maxCoarseScale_ = MaxCoarseLayerDefault;
406  int profileSize_ = 1;
407  int profileDelta_ = 1;
408 
409  Cvb::ValueRange<Cvb::Angle> rotationRange_ = RotationRangeDefault();
410  Cvb::ValueRange<double> scaleRange_ = ScaleRangeDefault();
412 
413 };
414 
415 }
416 
417 using ShapeFinder2::ClassifierFactory;
418 
419 CVB_END_INLINE_NS
420 
421 }
422 
423 
static std::unique_ptr< Classifier > FromHandle(HandleGuard< Classifier > &&guard)
Creates a classifier from a classic API handle.
Definition: classifier.hpp:49
int MaxCoarseLayerScale() const noexcept
Maximum exponent of the scale factor between the coarse layer and the image.
Definition: classifier_factory.hpp:169
Image plane information container.
Definition: decl_image_plane.hpp:31
T Top() const noexcept
Gets first row of the rectangle.
Definition: rect.hpp:111
void SetProfileSize(int value)
Profile size gives the number of profile points to be used for correlation around each feature.
Definition: classifier_factory.hpp:221
double A21() const noexcept
Gets bottom left matrix element.
Definition: matrix_2d.hpp:205
ValueRange< Angle > RotationRangeMax() const noexcept
The maximum range of rotations (in degrees), that may be set on the learner.
Definition: classifier_factory.hpp:61
class DataType DataType() const noexcept override
Data type descriptor for this array.
Definition: detail_image_plane.hpp:340
void SetRotationRange(ValueRange< Angle > value)
Range of rotations, that the classifier should be able to cover.
Definition: classifier_factory.hpp:81
T Min() const noexcept
Gets the minimum value.
Definition: value_range.hpp:50
GradientType
Type of Gradient used for feature extraction.
Definition: shapefinder2.hpp:58
T Max() const noexcept
Gets the maximum value.
Definition: value_range.hpp:72
const Image & Parent() const noexcept
Image to which this plane descriptor refers to.
Definition: detail_image_plane.hpp:87
Cvb::ShapeFinder2::ContrastMode ContrastMode() const noexcept
Contrast mode to be used for feature extraction.
Definition: classifier_factory.hpp:191
void SetScaleRange(ValueRange< double > value)
Range of scales, that the classifier should be able to cover.
Definition: classifier_factory.hpp:113
int FeatureCount() const noexcept
Minimum number of features the result classifier should have.
Definition: classifier_factory.hpp:125
T Bottom() const noexcept
Gets bottom row of the rectangle (still inside the rectangle).
Definition: rect.hpp:151
static Matrix2D Identity() noexcept
The identity element.
Definition: matrix_2d.hpp:24
void SetContrastThreshold(int value)
Minimum contrast a feature must have to enter into the classifier.
Definition: classifier_factory.hpp:157
T Left() const noexcept
Gets first column of the rectangle.
Definition: rect.hpp:91
ValueRange< double > ScaleRange() const noexcept
Range of scales, that the classifier should be able to cover.
Definition: classifier_factory.hpp:103
int Plane() const noexcept
Plane index in the image, to which this plane refers to.
Definition: decl_image_plane.hpp:169
Root namespace for the Image Manager interface.
Definition: version.hpp:11
static Angle FromDegrees(double deg, bool trim=false) noexcept
Create an angle in degrees.
Definition: angle.hpp:30
void SetMaxCoarseLayerScale(int value)
Maximum exponent of the scale factor between the coarse layer and the image.
Definition: classifier_factory.hpp:179
int ProfileSize() const noexcept
Profile size gives the number of profile points to be used for correlation around each feature.
Definition: classifier_factory.hpp:211
std::unique_ptr< Classifier > Learn(const ImagePlane &plane, Point2D< double > position, Angle angleOffset, double scaleFactor, Rect< int > teachWindow, const std::vector< Point2D< int >> &dontCarePoints) const
Create a ShapeFinder2 classifier from the input image.
Definition: classifier_factory.hpp:321
T Y() const noexcept
Gets the y-component of the point.
Definition: point_2d.hpp:106
ClassifierFactory() noexcept=default
The object that holds methods for generating ShapeFinder classifier factory.
T Right() const noexcept
Gets rightmost column of the rectangle (still inside the rectangle).
Definition: rect.hpp:131
std::vector< int > GradientHistogram(const ImagePlane &plane, Rect< int > aoi, ShapeFinder2::GradientType gradient) const
Calculate the gradient histogram.
Definition: classifier_factory.hpp:46
ContrastMode
Normal contrast features.
Definition: shapefinder2.hpp:36
void * Handle() const noexcept
Classic API image handle.
Definition: decl_image.hpp:223
T X() const noexcept
Gets the x-component of the point.
Definition: point_2d.hpp:86
bool HasOverlayBit() const noexcept
Gets whether bit 0 of the pixels of the plane are being used as an overlay indicator bit.
Definition: data_type.hpp:394
STL class.
double A22() const noexcept
Gets bottom right matrix element.
Definition: matrix_2d.hpp:225
ValueRange< double > ScaleRangeMax() const noexcept
The maximum range of scales, that may be set on the learner.
Definition: classifier_factory.hpp:93
std::unique_ptr< Classifier > Learn(const ImagePlane &plane, Point2D< double > position, Angle angleOffset, double scaleFactor, Rect< int > teachWindow) const
Create a ShapeFinder2 classifier from the input image.
Definition: classifier_factory.hpp:289
void SetProfileDelta(int value)
Distance (in pixels) between adjacent profile points.
Definition: classifier_factory.hpp:245
double A11() const noexcept
Gets top left matrix element.
Definition: matrix_2d.hpp:165
int Width() const noexcept
Width of the image in pixels.
Definition: decl_image.hpp:285
Container for range definitions.
Definition: value_range.hpp:16
std::unique_ptr< Classifier > Learn(const ImagePlane &plane, Point2D< double > position, Rect< int > teachWindow) const
Create a ShapeFinder2 classifier from plane 0 of the input image.
Definition: classifier_factory.hpp:274
int ProfileDelta() const noexcept
Distance (in pixels) between adjacent profile points.
Definition: classifier_factory.hpp:235
std::unique_ptr< Classifier > Learn(const ImagePlane &plane, Point2D< double > position, Rect< int > teachWindow, const std::vector< Point2D< int >> &dontCarePoints) const
Creates a ShapeFinder2 classifier from plane 0 of the input image.
Definition: classifier_factory.hpp:261
double A12() const noexcept
Gets top right matrix element.
Definition: matrix_2d.hpp:185
ShapeFinder2 classifier factory object.
Definition: classifier_factory.hpp:26
void SetFeatureCount(int value)
Minimum number of features the result classifier should have.
Definition: classifier_factory.hpp:135
int Height() const noexcept
Height of the image in pixels.
Definition: decl_image.hpp:278
int BitsPerPixel() const noexcept
Number of actually valid bits per pixel.
Definition: data_type.hpp:332
int ContrastThreshold() const noexcept
Minimum contrast a feature must have to enter into the classifier.
Definition: classifier_factory.hpp:147
void SetContrastMode(Cvb::ShapeFinder2::ContrastMode mode) noexcept
Contrast mode to be used for feature extraction.
Definition: classifier_factory.hpp:201
bool IsUnsignedInteger() const noexcept
Gets whether the pixels of the plane have unsigned integer values.
Definition: data_type.hpp:374
Object for convenient and type - safe handling of angles.
Definition: angle.hpp:18
const int CVB_INVALIDDATATYPE
Invalid data type.
Definition: exception.hpp:78
ValueRange< Angle > RotationRange() const noexcept
Range of rotations, that the classifier should be able to cover.
Definition: classifier_factory.hpp:71