14 #ifndef AUGMENTATIONS_H_ 15 #define AUGMENTATIONS_H_ 26 #include <unordered_map> 31 #define ECVL_ERROR_AUGMENTATION_NAME throw std::runtime_error(ECVL_ERROR_MSG "Cannot load augmentation name"); 32 #define ECVL_ERROR_AUGMENTATION_FORMAT throw std::runtime_error(ECVL_ERROR_MSG "Format error while loading augmentation parameters"); 38 static std::istream& read_until(std::istream& is, std::string& s,
const std::string& list)
41 while (is.peek() && is && list.find(is.peek()) == list.npos) {
47 void read_vals(std::istream& is,
char closing_char)
58 }
while (next_char ==
',');
59 if (!is || next_char != closing_char) {
60 std::cerr <<
"Error while reading values of parameter " <<
name_ <<
"\n";
61 throw std::runtime_error(
"Cannot read parameter value");
89 read_until(is,
name_,
" =");
91 is >> std::ws >> next_char;
92 if (next_char !=
'=') {
93 throw std::runtime_error(
"Cannot read parameter name");
96 next_char = is.peek();
97 if (next_char ==
'[') {
101 }
else if (next_char ==
'(') {
105 }
else if (next_char ==
'"') {
108 std::getline(is,
str_,
'"');
115 std::cerr <<
"Error while reading value of parameter " <<
name_ <<
"\n";
116 throw std::runtime_error(
"Cannot read parameter value");
126 std::unordered_map<std::string, param> m_;
127 const std::string fn_name_;
138 auto it = m_.find(name);
140 auto& p = it->second;
141 if (p.type_ != type) {
142 throw std::runtime_error(fn_name_ +
": " + name +
" parameter must be a " +
param::to_string(type));
148 throw std::runtime_error(fn_name_ +
": " + name +
" is a required parameter");
155 auto it = m_.find(name);
157 auto& p = it->second;
162 throw std::runtime_error(fn_name_ +
": " + name +
" is a required parameter");
188 static std::default_random_engine
re_;
190 static constexpr
unsigned seed_min = std::numeric_limits<unsigned>::min();
191 static constexpr
unsigned seed_max = std::numeric_limits<unsigned>::max();
209 std::unordered_map<std::string, AugmentationParam>
params_;
218 x.second.GenerateValue();
222 virtual std::shared_ptr<Augmentation>
Clone()
const = 0;
228 #define DEFINE_AUGMENTATION_CLONE(class_name) std::shared_ptr<Augmentation> Clone() const override { return std::make_shared<class_name>(*this); } 232 static std::shared_ptr<Augmentation>
create(std::istream& is)
242 static std::shared_ptr<Augmentation>
create(
const std::string& name, std::istream& is);
260 for (
auto& x : augs_) {
264 std::vector<std::shared_ptr<Augmentation>> augs_;
268 template<
typename ...Ts>
275 for (
const auto& a : other.augs_) {
276 augs_.emplace_back(a->Clone());
313 if (
params_[
"p"].value_ <= p_) {
314 augs_[index]->Apply(img, gt);
317 std::vector<std::shared_ptr<Augmentation>> augs_;
322 template<
typename ...Ts>
335 for (
const auto& a : other.augs_) {
336 augs_.emplace_back(a->Clone());
345 auto m =
param::read(is,
"OneOfAugmentationContainer");
349 }
catch (std::runtime_error&) {
350 std::cout <<
ECVL_ERROR_MSG "The first parameter in OneOfAugmentationContainer must be the probability p" << std::endl;
381 std::vector<double> center_;
387 const auto angle =
params_[
"angle"].value_;
388 Rotate2D(img, img, angle, center_, scale_, interp_);
390 Rotate2D(gt, const_cast<Image&>(gt), angle, center_, scale_, gt_interp_);
406 const std::vector<
double>& center = {},
407 const double& scale = 1.,
410 : center_(center), scale_(scale), interp_(interp), gt_interp_(gt_interp)
450 std::vector<int> dims_;
457 ResizeDim(gt, const_cast<Image&>(gt), dims_, gt_interp_);
472 : dims_{ dims }, interp_(interp), gt_interp_(gt_interp) {}
480 for (
const auto& x : p.
vals_) {
481 dims_.emplace_back(static_cast<int>(x));
502 std::vector<double> scale_;
509 ResizeScale(gt, const_cast<Image&>(gt), scale_, gt_interp_);
524 ) : scale_{ scale }, interp_(interp), gt_interp_(gt_interp){}
556 const auto p =
params_[
"p"].value_;
560 Flip2D(gt, const_cast<Image&>(gt));
597 const auto p =
params_[
"p"].value_;
601 Mirror2D(gt, const_cast<Image&>(gt));
636 const auto sigma =
params_[
"sigma"].value_;
669 const auto std_dev =
params_[
"std_dev"].value_;
687 auto m =
param::read(is,
"AugAdditiveLaplaceNoise");
703 const auto lambda =
params_[
"lambda"].value_;
721 auto m =
param::read(is,
"AugAdditivePoissonNoise");
737 const auto gamma =
params_[
"gamma"].value_;
773 const auto p =
params_[
"p"].value_;
774 const auto drop_size =
params_[
"drop_size"].value_;
775 const bool per_channel =
params_[
"per_channel"].value_ <= per_channel_ ? true :
false;
787 AugCoarseDropout(const std::array<
double, 2>& p, const std::array<
double, 2>& drop_size, const
double& per_channel) : per_channel_(per_channel)
789 assert(per_channel >= 0 && per_channel <= 1);
807 per_channel_ = p.
vals_[0];
821 const auto p =
params_[
"p"].value_;
860 const auto beta =
params_[
"beta"].value_;
893 std::array<float, 2> distort_limit_;
900 const auto num_steps =
params_[
"num_steps"].value_;
901 const auto seed =
params_[
"seed"].value_;
902 GridDistortion(img, img, static_cast<int>(num_steps), distort_limit_, interp_, border_type_,
903 border_value_, static_cast<unsigned>(seed));
905 GridDistortion(gt, const_cast<Image&>(gt), static_cast<int>(num_steps), distort_limit_,
906 interp_, border_type_, border_value_, static_cast<unsigned>(seed));
921 const std::array<
float, 2>& distort_limit,
924 const
int& border_value = 0)
925 : distort_limit_(distort_limit), interp_(interp), border_type_(border_type), border_value_(border_value)
944 distort_limit_ = { static_cast<float>(p.
vals_[0]), static_cast<float>(p.
vals_[1]) };
953 if (p.
str_ ==
"constant") {
955 }
else if (p.
str_ ==
"replicate") {
957 }
else if (p.
str_ ==
"reflect") {
959 }
else if (p.
str_ ==
"wrap") {
961 }
else if (p.
str_ ==
"reflect_101") {
963 }
else if (p.
str_ ==
"transparent") {
966 throw std::runtime_error(
"AugGridDistortion: invalid border type");
972 border_value_ = static_cast<int>(p.
vals_[0]);
988 const auto alpha =
params_[
"alpha"].value_;
989 const auto sigma =
params_[
"sigma"].value_;
990 const auto seed =
params_[
"seed"].value_;
991 ElasticTransform(img, img, alpha, sigma, interp_, border_type_, border_value_, static_cast<unsigned>(seed));
994 border_type_, border_value_, static_cast<unsigned>(seed));
1009 const std::array<
double, 2>& sigma,
1012 const
int& border_value = 0)
1013 : interp_(interp), border_type_(border_type), border_value_(border_value)
1042 if (p.
str_ ==
"constant") {
1044 }
else if (p.
str_ ==
"replicate") {
1046 }
else if (p.
str_ ==
"reflect") {
1048 }
else if (p.
str_ ==
"wrap") {
1050 }
else if (p.
str_ ==
"reflect_101") {
1052 }
else if (p.
str_ ==
"transparent") {
1055 throw std::runtime_error(
"AugGridDistortion: invalid border type");
1061 border_value_ = static_cast<int>(p.
vals_[0]);
1071 std::array<float, 2> distort_limit_;
1072 std::array<float, 2> shift_limit_;
1079 const auto seed =
params_[
"seed"].value_;
1080 OpticalDistortion(img, img, distort_limit_, shift_limit_, interp_, border_type_,
1081 border_value_, static_cast<unsigned>(seed));
1082 if (!gt.IsEmpty()) {
1083 OpticalDistortion(gt, const_cast<Image&>(gt), distort_limit_, shift_limit_, interp_, border_type_,
1084 border_value_, static_cast<unsigned>(seed));
1099 const std::array<
float, 2>& shift_limit,
1102 const
int& border_value = 0)
1103 : distort_limit_(distort_limit), shift_limit_(shift_limit), interp_(interp), border_type_(border_type), border_value_(border_value)
1118 distort_limit_ = { static_cast<float>(p.
vals_[0]), static_cast<float>(p.
vals_[1]) };
1121 shift_limit_ = { static_cast<float>(p.
vals_[0]), static_cast<float>(p.
vals_[1]) };
1130 if (p.
str_ ==
"constant") {
1132 }
else if (p.
str_ ==
"replicate") {
1134 }
else if (p.
str_ ==
"reflect") {
1136 }
else if (p.
str_ ==
"wrap") {
1138 }
else if (p.
str_ ==
"reflect_101") {
1140 }
else if (p.
str_ ==
"transparent") {
1143 throw std::runtime_error(
"AugGridDistortion: invalid border type");
1149 border_value_ = static_cast<int>(p.
vals_[0]);
1159 double per_channel_;
1163 const auto p =
params_[
"p"].value_;
1164 const auto seed =
params_[
"seed"].value_;
1165 const bool per_channel =
params_[
"per_channel"].value_ <= per_channel_ ? true :
false;
1166 Salt(img, img, p, per_channel, static_cast<unsigned>(seed));
1176 AugSalt(const std::array<
double, 2>& p, const
double& per_channel) : per_channel_(per_channel)
1178 assert(per_channel >= 0 && per_channel <= 1);
1196 per_channel_ = p.
vals_[0];
1206 double per_channel_;
1210 const auto p =
params_[
"p"].value_;
1211 const auto seed =
params_[
"seed"].value_;
1212 const bool per_channel =
params_[
"per_channel"].value_ <= per_channel_ ? true :
false;
1213 Pepper(img, img, p, per_channel, static_cast<unsigned>(seed));
1223 AugPepper(const std::array<
double, 2>& p, const
double& per_channel) : per_channel_(per_channel)
1225 assert(per_channel >= 0 && per_channel <= 1);
1243 per_channel_ = p.
vals_[0];
1253 double per_channel_;
1257 const auto p =
params_[
"p"].value_;
1258 const auto seed =
params_[
"seed"].value_;
1259 const bool per_channel =
params_[
"per_channel"].value_ <= per_channel_ ? true :
false;
1260 SaltAndPepper(img, img, p, per_channel, static_cast<unsigned>(seed));
1270 AugSaltAndPepper(const std::array<
double, 2>& p, const
double& per_channel) : per_channel_(per_channel)
1272 assert(per_channel >= 0 && per_channel <= 1);
1290 per_channel_ = p.
vals_[0];
1300 double mean_ = 0., std_ = 1.;
1302 std::vector<double> ch_mean_;
1303 std::vector<double> ch_std_;
1323 AugNormalize(const
double& mean, const
double& std) : mean_(mean), std_(std), per_channel_(false) {}
1330 AugNormalize(
const std::vector<double>& mean,
const std::vector<double>& std) : ch_mean_(mean), ch_std_(std), per_channel_(true) {}
1337 m.GenericGet(
"mean",
true, p);
1340 per_channel_ =
false;
1343 per_channel_ =
true;
1345 throw std::runtime_error(
"AugNormalize: invalid mean type");
1348 if (per_channel_ ==
false) {
1364 std::vector<int> size_;
1369 std::vector<int> new_size = size_;
1372 new_size = std::vector<int>(2, std::min(img.
Width(), img.
Height()));
1375 if (!gt.IsEmpty()) {
1376 CenterCrop(gt, const_cast<Image&>(gt), new_size);
1401 for (
const auto& x : p.
vals_) {
1402 size_.emplace_back(static_cast<int>(x));
1419 double divisor_, divisor_gt_;
1426 if (!gt.IsEmpty()) {
1428 const_cast<Image&>(gt).Div(divisor_gt_);
1439 AugToFloat32(const
double& divisor = 1., const
double& divisor_gt = 1.) : divisor_{ divisor }, divisor_gt_{ divisor_gt } {}
1446 divisor_ = p.
vals_[0];
1448 divisor_gt_ = p.
vals_[0];
1464 if (!gt.IsEmpty()) {
1465 const_cast<Image&>(gt).Div(255);
1482 double new_min_, new_max_;
1486 ScaleTo(img, img, new_min_, new_max_);
1496 AugScaleTo(const
double& new_min, const
double& new_max) : new_min_{ new_min }, new_max_{ new_max } {}
1503 new_min_ = p.
vals_[0];
1506 new_max_ = p.
vals_[0];
1516 std::vector<int> size_;
1522 const auto seed =
params_[
"seed"].value_;
1523 RandomCrop(img, img, size_,
true, border_type_, border_value_, static_cast<unsigned>(seed));
1524 if (!gt.IsEmpty()) {
1525 RandomCrop(gt, const_cast<Image&>(gt), size_,
true, border_type_, border_value_, static_cast<unsigned>(seed));
1538 size_{ size }, border_type_{ border_type }, border_value_{ border_value }
1549 for (
const auto& x : p.
vals_) {
1550 size_.emplace_back(static_cast<int>(x));
1557 border_value_ = static_cast<int>(p.
vals_[0]);
1564 #endif // AUGMENTATIONS_H_ AugCenterCrop(const std::vector< int > &size)
AugCenterCrop constructor.
Augmentation wrapper for ecvl::Flip2D.
Augmentation wrapper for ecvl::Normalize.
AugmentationParam(const double min, const double max)
void ResizeDim(const ecvl::Image &src, ecvl::Image &dst, const std::vector< int > &newdims, InterpolationType interp=InterpolationType::linear)
Resizes an Image to the specified dimensions.
void CoarseDropout(const Image &src, Image &dst, double p, double drop_size, bool per_channel)
Sets rectangular areas within an Image to zero.
void GridDistortion(const Image &src, Image &dst, int num_steps=5, const std::array< float, 2 > &distort_limit={ -0.3f, 0.3f }, InterpolationType interp=InterpolationType::linear, BorderType border_type=BorderType::BORDER_REFLECT_101, const int &border_value=0, const unsigned seed=std::default_random_engine::default_seed)
Randomly stretch or reduce each cell of the grid in which the input Image is divided into....
void ScaleTo(const Image &src, Image &dst, const double &new_min, const double &new_max)
Linearly scale an Image into a new range.
BorderType StrToBorderType(const std::string &interp, const std::string &aug_name)
OneOfAugmentationContainer(double p, std::vector< std::shared_ptr< Augmentation >> augs)
int Width() const
Returns the width of Image.
AugBrightness(std::istream &is)
AugRotate(std::istream &is)
Augmentation wrapper for ecvl::GridDistortion.
OneOfAugmentationContainer.
bool GenericGet(const std::string &name, bool required, param &value)
AugResizeScale(std::istream &is)
AugDivBy255(std::istream &is)
int vsize(const std::vector< T > &v)
void RandomCrop(const Image &src, Image &dst, const std::vector< int > &size, bool pad_if_needed=false, BorderType border_type=BorderType::BORDER_CONSTANT, const int &border_value=0, const unsigned seed=std::default_random_engine::default_seed)
Crop the source Image at a random location with the size specified.
void CenterCrop(const ecvl::Image &src, ecvl::Image &dst, const std::vector< int > &size)
Crops the given image at the center.
bool Get(const std::string &name, param::type type, bool required, param &value)
SequentialAugmentationContainer(std::vector< std::shared_ptr< Augmentation >> augs)
AugMirror(std::istream &is)
AugToFloat32(std::istream &is)
AugmentationParam()=default
SequentialAugmentationContainer.
std::unordered_map< std::string, AugmentationParam > params_
AugFlip(std::istream &is)
InterpolationType
Enum class representing the ECVL interpolation types.
void AdditiveLaplaceNoise(const Image &src, Image &dst, double std_dev)
Adds Laplace distributed noise to an Image.
void Add(const Image &src1, const Image &src2, Image &dst, DataType dst_type=DataType::none, bool saturate=true)
Adds two source Images storing the result into a destination Image.
AugTranspose(std::istream &is)
void Transpose(const Image &src, Image &dst)
Swap rows and columns of an Image.
AugAdditivePoissonNoise(std::istream &is)
int Height() const
Returns the height of Image.
Augmentation wrapper for ecvl::Mirror2D.
static void SetSeed(unsigned seed)
Set a fixed seed for the random generated values. Useful to reproduce experiments with same augmentat...
iiiiii|abcdefgh|iiiiiii with some specified i
void Salt(const Image &src, Image &dst, double p, bool per_channel=false, const unsigned seed=std::default_random_engine::default_seed)
Adds salt noise (white pixels) to an Image.
void ResizeScale(const ecvl::Image &src, ecvl::Image &dst, const std::vector< double > &scales, InterpolationType interp=InterpolationType::linear)
Resizes an Image by scaling the dimensions to a given scale factor.
AugGridDistortion(std::istream &is)
Augmentation CenterCrop wrapper for ecvl::CenterCrop.
#define DEFINE_AUGMENTATION_CLONE(class_name)
SequentialAugmentationContainer(const SequentialAugmentationContainer &other)
static std::shared_ptr< Augmentation > create(std::istream &is)
void GaussianBlur(const Image &src, Image &dst, int sizeX, int sizeY, double sigmaX, double sigmaY=0)
Blurs an Image using a Gaussian kernel.
Augmentation wrapper for ecvl::AdditivePoissonNoise.
AugRandomCrop(std::istream &is)
void Normalize(const Image &src, Image &dst, const double &mean, const double &std)
Normalize Image image with mean and standard deviation.
void ConvertTo(DataType dtype, bool saturate=true)
Convert Image to another DataType.
static std::default_random_engine re_
BorderType
Enum class representing the ECVL border types.
void SaltAndPepper(const Image &src, Image &dst, double p, bool per_channel=false, const unsigned seed=std::default_random_engine::default_seed)
Adds salt and pepper noise (white and black pixels) to an Image. White and black pixels are equally l...
AugCoarseDropout(std::istream &is)
Augmentations parameters.
Augmentation wrapper for ecvl::Transpose.
AugNormalize(const std::vector< double > &mean, const std::vector< double > &std)
AugNormalize constructor with separate statistics for each channel.
static param_list read(std::istream &is, std::string fn_name_)
param_list(std::string fn_name)
InterpolationType StrToInterpolationType(const std::string &interp, const std::string &aug_name)
#define ECVL_ERROR_NOT_REACHABLE_CODE
AugGaussianBlur(std::istream &is)
void AdditivePoissonNoise(const Image &src, Image &dst, double lambda)
Adds Poisson distributed noise to an Image.
void Rotate2D(const ecvl::Image &src, ecvl::Image &dst, double angle, const std::vector< double > ¢er={}, double scale=1.0, InterpolationType interp=InterpolationType::linear)
Rotates an Image.
auto & operator[](const std::string &s)
static constexpr unsigned seed_min
Augmentation wrapper for ecvl::GaussianBlur.
void Div(const T &rhs, bool saturate=true)
In-place division.
SequentialAugmentationContainer(Ts &&... t)
Augmentation wrapper for ecvl::AdditiveLaplaceNoise.
Augmentation wrapper for ecvl::Pepper.
void OpticalDistortion(const Image &src, Image &dst, const std::array< float, 2 > &distort_limit={ -0.3f, 0.3f }, const std::array< float, 2 > &shift_limit={ -0.1f, 0.1f }, InterpolationType interp=InterpolationType::linear, BorderType border_type=BorderType::BORDER_REFLECT_101, const int &border_value=0, const unsigned seed=std::default_random_engine::default_seed)
Barrel / pincushion distortion. Based on https://github.com/albumentations-team/albumentations/blob/m...
AugAdditiveLaplaceNoise(std::istream &is)
Augmentation wrapper for ecvl::CoarseDropout.
AugCenterCrop(std::istream &is)
AugSalt(std::istream &is)
OneOfAugmentationContainer(double p, Ts &&... t)
void Apply(ecvl::Image &img, const ecvl::Image >=Image())
Generate the random value for each parameter and call the specialized augmentation functions.
OneOfAugmentationContainer(std::istream &is)
Augmentation wrapper for ecvl::Rotate2D.
Augmentation wrapper for ecvl::ResizeDim.
AugGammaContrast(std::istream &is)
Abstract class which represent a generic Augmentation function.
AugSaltAndPepper(std::istream &is)
SequentialAugmentationContainer(std::istream &is)
void GammaContrast(const Image &src, Image &dst, double gamma)
Adjust contrast by scaling each pixel value X to 255 * ((X/255) ** gamma).
AugResizeDim(std::istream &is)
Augmentation wrapper for brightness adjustment.
static constexpr unsigned seed_max
static const char * to_string(type t)
void Flip2D(const ecvl::Image &src, ecvl::Image &dst)
Flips an Image.
virtual ~Augmentation()=default
Augmentation wrapper for ecvl::RandomCrop.
virtual std::shared_ptr< Augmentation > Clone() const =0
AugNormalize(std::istream &is)
Augmentation wrapper for ecvl::SaltAndPepper.
AugOpticalDistortion(std::istream &is)
std::vector< double > vals_
#define ECVL_ERROR_AUGMENTATION_NAME
Augmentation wrapper for ecvl::ScaleTo.
void Pepper(const Image &src, Image &dst, double p, bool per_channel=false, const unsigned seed=std::default_random_engine::default_seed)
Adds pepper noise (black pixels) to an Image.
void GenerateValue()
Generate the random value between min_ and max_.
AugPepper(std::istream &is)
Augmentation wrapper for ecvl::GammaContrast.
void ElasticTransform(const Image &src, Image &dst, double alpha=34., double sigma=4., InterpolationType interp=InterpolationType::linear, BorderType border_type=BorderType::BORDER_REFLECT_101, const int &border_value=0, const unsigned seed=std::default_random_engine::default_seed)
Elastic deformation of input Image. Based on https://github.com/albumentations-team/albumentations/bl...
Augmentation wrapper for ecvl::OpticalDistortion.
void Mirror2D(const ecvl::Image &src, ecvl::Image &dst)
Mirrors an Image.
OneOfAugmentationContainer(const OneOfAugmentationContainer &other)
Augmentation wrapper for ecvl::Salt.
#define ECVL_ERROR_AUGMENTATION_FORMAT
Augmentation wrapper for ecvl::ResizeScale.
AugScaleTo(std::istream &is)