Skip to content

Commit

Permalink
On the fly distortion is added
Browse files Browse the repository at this point in the history
  • Loading branch information
milakov committed Jun 23, 2013
1 parent b53926f commit 33c6124
Show file tree
Hide file tree
Showing 14 changed files with 748 additions and 140 deletions.
30 changes: 12 additions & 18 deletions examples/gtsrb/gtsrb_toolset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,24 +209,18 @@ void gtsrb_toolset::write_single_entry(
{
cv::Mat3b image = cv::imread(absolute_file_path.string());

if ((contrast != 1.0F) || (brightness_shift != 0.0F))
{
image = change_brightness_and_contrast(
image,
contrast,
brightness_shift);
}

if ((rotation_angle_in_degrees != 0.0F) || (scale_factor != 1.0F) || (shift_x != 0.0F) || (shift_y != 0.0F))
{
image = rotate_scale_shift(
image,
cv::Point2f(static_cast<float>(roi_top_left_x + roi_bottom_right_x) * 0.5F, static_cast<float>(roi_top_left_y + roi_bottom_right_y) * 0.5F),
rotation_angle_in_degrees,
scale_factor,
shift_x,
shift_y);
}
nnforge::data_transformer_util::change_brightness_and_contrast(
image,
contrast,
brightness_shift);

nnforge::data_transformer_util::rotate_scale_shift(
image,
cv::Point2f(static_cast<float>(roi_top_left_x + roi_bottom_right_x) * 0.5F, static_cast<float>(roi_top_left_y + roi_bottom_right_y) * 0.5F),
rotation_angle_in_degrees,
scale_factor,
shift_x,
shift_y);

if (use_roi)
image = image.rowRange(roi_top_left_y, roi_bottom_right_y).colRange(roi_top_left_x, roi_bottom_right_x);
Expand Down
42 changes: 42 additions & 0 deletions nnforge/data_transformer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright 2011-2013 Maxim Milakov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "data_transformer.h"

namespace nnforge
{
data_transformer::data_transformer()
{
}

data_transformer::~data_transformer()
{
}

layer_configuration_specific data_transformer::get_transformed_configuration(const layer_configuration_specific& original_config) const
{
return original_config;
}

bool data_transformer::is_in_place() const
{
return true;
}

void data_transformer::reset()
{
}
}
52 changes: 52 additions & 0 deletions nnforge/data_transformer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2011-2013 Maxim Milakov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include "layer_configuration_specific.h"
#include "neuron_data_type.h"

#include <memory>

namespace nnforge
{
class data_transformer
{
public:
virtual ~data_transformer();

virtual void transform(
const void * input_data,
void * output_data,
neuron_data_type::input_type type,
const layer_configuration_specific& original_config) = 0;

virtual layer_configuration_specific get_transformed_configuration(const layer_configuration_specific& original_config) const;

virtual bool is_in_place() const;

virtual void reset();

protected:
data_transformer();

private:
data_transformer(const data_transformer&);
data_transformer& operator =(const data_transformer&);
};

typedef std::tr1::shared_ptr<data_transformer> data_transformer_smart_ptr;
}
91 changes: 91 additions & 0 deletions nnforge/data_transformer_util.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright 2011-2013 Maxim Milakov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "data_transformer_util.h"

#include <opencv2/imgproc/imgproc.hpp>

namespace nnforge
{
void data_transformer_util::rotate_scale_shift(
cv::Mat image,
cv::Point2f rotation_center,
float angle_in_degrees,
float scale,
float shift_x,
float shift_y)
{
if ((angle_in_degrees != 0.0F) || (scale != 1.0F) || (shift_x != 0.0F) || (shift_y != 0.0F))
{
cv::Mat rot_mat = cv::getRotationMatrix2D(
rotation_center,
static_cast<double>(angle_in_degrees),
static_cast<double>(scale));

rot_mat.at<double>(0, 2) += static_cast<double>(shift_x);
rot_mat.at<double>(1, 2) += static_cast<double>(shift_y);

cv::Mat copy = image.clone();
cv::warpAffine(
copy,
image,
rot_mat,
image.size(),
cv::INTER_LINEAR,
cv::BORDER_CONSTANT,
128);
}
}

void data_transformer_util::change_brightness_and_contrast(
cv::Mat image,
float contrast,
float brightness)
{
if ((contrast != 1.0F) || (brightness != 0.0F))
{
image.convertTo(
image,
-1,
static_cast<double>(contrast),
static_cast<double>(brightness));
}
}

void data_transformer_util::flip(
cv::Mat image,
bool flip_around_x_axis,
bool flip_around_y_axis)
{
int flip_code;
if (flip_around_x_axis)
{
if (flip_around_y_axis)
flip_code = -1;
else
flip_code = 0;
}
else
{
if (flip_around_y_axis)
flip_code = 1;
else
return;
}

cv::flip(image, image, flip_code);
}
}
50 changes: 50 additions & 0 deletions nnforge/data_transformer_util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2011-2013 Maxim Milakov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <opencv2/core/core.hpp>

namespace nnforge
{
class data_transformer_util
{
public:
static void rotate_scale_shift(
cv::Mat image,
cv::Point2f rotation_center,
float angle_in_degrees,
float scale,
float shift_x,
float shift_y);

// contrast: relative multiplication, about 1.0
// brightness: change in luminocity for the middle lightness
static void change_brightness_and_contrast(
cv::Mat image,
float contrast,
float brightness);

static void flip(
cv::Mat image,
bool flip_around_x_axis,
bool flip_around_y_axis);

private:
data_transformer_util();
~data_transformer_util();
};
}
106 changes: 106 additions & 0 deletions nnforge/distort_2d_data_transformer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright 2011-2013 Maxim Milakov
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "distort_2d_data_transformer.h"

#include "neural_network_exception.h"
#include "data_transformer_util.h"

#include <opencv2/core/core.hpp>
#include <boost/format.hpp>

namespace nnforge
{
distort_2d_data_transformer::distort_2d_data_transformer(
bool is_deterministic,
float max_absolute_rotation_angle_in_degrees,
float max_scale_factor,
float max_absolute_shift_x,
float max_absolute_shift_y,
float max_contrast_factor,
float max_absolute_brightness_shift,
bool flip_around_x_axis_allowed,
bool flip_around_y_axis_allowed)
: is_same_sequence_from_reset(is_same_sequence_from_reset)
{
if (!is_same_sequence_from_reset)
generator = rnd::get_random_generator();

rotate_angle_distribution = std::tr1::uniform_real<float>(-max_absolute_rotation_angle_in_degrees, max_absolute_rotation_angle_in_degrees);
scale_distribution = std::tr1::uniform_real<float>(1.0F / max_scale_factor, max_scale_factor);
shift_x_distribution = std::tr1::uniform_real<float>(-max_absolute_shift_x, max_absolute_shift_x);
shift_y_distribution = std::tr1::uniform_real<float>(-max_absolute_shift_x, max_absolute_shift_x);
contrast_distribution = std::tr1::uniform_real<float>(1.0F / max_contrast_factor, max_contrast_factor);
brightness_shift_distribution = std::tr1::uniform_real<float>(-max_absolute_brightness_shift, max_absolute_brightness_shift);
flip_around_x_distribution = std::tr1::uniform_int<int>(0, flip_around_x_axis_allowed ? 1 : 0);
flip_around_y_distribution = std::tr1::uniform_int<int>(0, flip_around_y_axis_allowed ? 1 : 0);
}

distort_2d_data_transformer::~distort_2d_data_transformer()
{
}

void distort_2d_data_transformer::reset()
{
if (is_same_sequence_from_reset)
generator = rnd::get_random_generator(48576435);
}

void distort_2d_data_transformer::transform(
const void * input_data,
void * output_data,
neuron_data_type::input_type type,
const layer_configuration_specific& original_config)
{
if (type != neuron_data_type::type_byte)
throw neural_network_exception("distort_2d_data_transformer is implemented for data stored as bytes only");

if (original_config.dimension_sizes.size() != 2)
throw neural_network_exception((boost::format("distort_2d_data_transformer is processing 2d data only, data is passed with number of dimensions %1%") % original_config.dimension_sizes.size()).str());

if (original_config.feature_map_count != 1)
throw neural_network_exception("distort_2d_data_transformer is implemented for 1 feature map data only");

cv::Mat1b image(static_cast<int>(original_config.dimension_sizes[1]), static_cast<int>(original_config.dimension_sizes[0]), static_cast<unsigned char *>(output_data));

float rotation_angle = rotate_angle_distribution(generator);
float scale = scale_distribution(generator);
float shift_x = shift_x_distribution(generator);
float shift_y = shift_y_distribution(generator);
float contrast = contrast_distribution(generator);
float brightness_shift = brightness_shift_distribution(generator) * 255.0F;
bool flip_around_x_axis = (flip_around_x_distribution(generator) == 1);
bool flip_around_y_axis = (flip_around_y_distribution(generator) == 1);

data_transformer_util::change_brightness_and_contrast(
image,
contrast,
brightness_shift);

data_transformer_util::rotate_scale_shift(
image,
cv::Point2f(static_cast<float>(image.cols) * 0.5F, static_cast<float>(image.rows) * 0.5F),
rotation_angle,
scale,
shift_x,
shift_y);

data_transformer_util::flip(
image,
flip_around_x_axis,
flip_around_y_axis);
}
}
Loading

0 comments on commit 33c6124

Please sign in to comment.