Commit fa2499d8 authored by Davis King's avatar Davis King

Added a file that defines a new generic image interface for images in dlib.

This is the dlib/image_processing/generic_image.h file.  Then I changed all the
image processing functions so that they use this interface.  All the changes
are very minor, but there are just a lot of them.

Any user code that was using array2d objects to represent images will still
work.  However, this change makes it so that users can use their own custom
image objects with dlib by simply implementing a few global functions for their
image object.
parent dc0fd24d
......@@ -6,6 +6,7 @@
#include "array2d/array2d_kernel.h"
#include "array2d/serialize_pixel_overloads.h"
#include "array2d/array2d_generic_image.h"
#endif // DLIB_ARRAY2d_
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ARRAY2D_GENERIC_iMAGE_H__
#define DLIB_ARRAY2D_GENERIC_iMAGE_H__
#include "array2d_kernel.h"
#include "../image_processing/generic_image.h"
namespace dlib
{
template <typename T, typename mm>
struct image_traits<array2d<T,mm> >
{
typedef T pixel_type;
};
template <typename T, typename mm>
inline long num_rows( const array2d<T,mm>& img) { return img.nr(); }
template <typename T, typename mm>
inline long num_columns( const array2d<T,mm>& img) { return img.nc(); }
template <typename T, typename mm>
inline void set_image_size(
array2d<T,mm>& img,
long rows,
long cols
) { img.set_size(rows,cols); }
template <typename T, typename mm>
inline void* image_data(
array2d<T,mm>& img
)
{
if (img.size() != 0)
return &img[0][0];
else
return 0;
}
template <typename T, typename mm>
inline const void* image_data(
const array2d<T,mm>& img
)
{
if (img.size() != 0)
return &img[0][0];
else
return 0;
}
template <typename T, typename mm>
inline long width_step(
const array2d<T,mm>& img
)
{
return img.width_step();
}
}
#endif // DLIB_ARRAY2D_GENERIC_iMAGE_H__
......@@ -9,6 +9,7 @@
#include <iostream>
#include "../serialize.h"
#include "vector.h"
#include "../image_processing/generic_image.h"
namespace dlib
{
......@@ -645,7 +646,7 @@ namespace dlib
const T& m
)
{
return rectangle(0, 0, m.nc()-1, m.nr()-1);
return rectangle(0, 0, num_columns(m)-1, num_rows(m)-1);
}
// ----------------------------------------------------------------------------------------
......
......@@ -715,9 +715,12 @@ namespace dlib
);
/*!
requires
- T has nr() and nc() functions that return longs
- It must be possible to determine the number of "rows" and "columns" in m.
Either by calling num_rows(m) and num_columns(m) or by calling m.nr() and
m.nc() to obtain the number of rows and columns respectively. Moreover,
these routines should return longs.
ensures
- returns rectangle(0, 0, m.nc()-1, m.nr()-1)
- returns rectangle(0, 0, num_columns(m)-1, num_rows(m)-1)
(i.e. assuming T represents some kind of rectangular grid, such as
the dlib::matrix or dlib::array2d objects, this function returns the
bounding rectangle for that gridded object.)
......
......@@ -3253,12 +3253,12 @@ namespace dlib
// if the new image has a different size when compared to the previous image
// then we should readjust the total rectangle size.
if (new_img.nr() != img.nr() || new_img.nc() != img.nc())
if (num_rows(new_img) != img.nr() || num_columns(new_img) != img.nc())
{
if (zoom_in_scale != 1)
set_total_rect_size(new_img.nc()*zoom_in_scale, new_img.nr()*zoom_in_scale);
set_total_rect_size(num_columns(new_img)*zoom_in_scale, num_rows(new_img)*zoom_in_scale);
else
set_total_rect_size(new_img.nc()/zoom_out_scale, new_img.nr()/zoom_out_scale);
set_total_rect_size(num_columns(new_img)/zoom_out_scale, num_rows(new_img)/zoom_out_scale);
}
else
{
......
......@@ -66,7 +66,7 @@ namespace dlib
const image_type& img
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false );
load_impl(mat(img));
}
......
......@@ -103,7 +103,7 @@ namespace dlib
requires
- image_type is a dlib::matrix or something convertible to a matrix
via mat()
- pixel_traits<typename image_type::type>::has_alpha == false
- pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false
ensures
- if (img.nr() < min_size || img.nc() < min_size) then
- the image is too small so we don't compute anything on it
......
......@@ -309,7 +309,7 @@ namespace dlib
// use the inverse frequency as the scale for each feature. We also scale
// these counts so that they are invariant to the size of the image (we scale
// them so they all look like they come from a 500x400 images).
const double scale = img.size()/(500.0*400.0);
const double scale = image_size(img)/(500.0*400.0);
for (unsigned long i = 0; i < feat_counts.size(); ++i)
{
feat_counts[i] = scale/feat_counts[i];
......
......@@ -82,7 +82,7 @@ namespace dlib
const image_type& img
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false );
load_impl(mat(img));
}
......
......@@ -158,8 +158,8 @@ namespace dlib
/*!
requires
- image_type is a dlib::matrix or something convertible to a matrix
via mat()
- pixel_traits<typename image_type::type>::has_alpha == false
via mat().
- pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false
ensures
- if (img.nr() < min_size || img.nc() < min_size) then
- the image is too small so we don't compute anything on it
......
......@@ -138,7 +138,7 @@ namespace dlib
const image_type& img
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false );
poly_coef.resize(get_num_dimensions());
des.set_size(get_num_dimensions());
......
......@@ -166,8 +166,9 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type>::has_alpha == false
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false
ensures
- Performs the feature extraction described in the WHAT THIS OBJECT REPRESENTS
section above. This means after load() finishes you can call (*this)(row,col)
......
......@@ -248,7 +248,7 @@ namespace dlib
);
// Figure out the proper scalar type we should use to work with these pixels.
typedef typename pixel_traits<typename image_type::type>::basic_pixel_type bp_type;
typedef typename pixel_traits<typename image_traits<image_type>::pixel_type>::basic_pixel_type bp_type;
typedef typename promote<bp_type>::type working_pixel_type;
// make an integral image first
......
......@@ -133,8 +133,10 @@ namespace dlib
requires
- max_points > 0
- detection_threshold >= 0
- image_type == a type that implements the array2d/array2d_kernel_abstract.h interface
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- Let P denote the type of pixel in img, then we require:
- pixel_traits<P>::has_alpha == false
ensures
- This function runs the complete SURF algorithm on the given input image and
returns the points it found.
......
......@@ -31,10 +31,11 @@ namespace dlib
typename image_type
>
void load_bmp (
image_type& image,
image_type& image_,
std::istream& in_
)
{
image_view<image_type> image(image_);
try
{
unsigned long bytes_read_so_far = 0;
......@@ -550,10 +551,11 @@ namespace dlib
typename image_type
>
void load_dng (
image_type& image,
image_type& image_,
std::istream& in
)
{
image_view<image_type> image(image_);
using namespace dng_helpers_namespace;
try
{
......@@ -788,7 +790,7 @@ namespace dlib
// Only use long double precision if the target image contains long
// doubles because it's slower to use those.
if (!is_same_type<typename image_type::type,long double>::value)
if (!is_same_type<typename image_traits<image_type>::pixel_type,long double>::value)
{
double temp = cur;
assign_pixel(image[r][c],temp);
......
......@@ -29,8 +29,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- #image == the image of the MS Windows BMP file that was available
in the input stream in.
......@@ -61,8 +61,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- opens the file indicated by file_name with an input file stream named fin
and performs:
......@@ -87,8 +87,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- #image == the image of the dlib dng file that was available
in the input stream in.
......@@ -119,8 +119,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- opens the file indicated by file_name with an input file stream named fin
and performs:
......
......@@ -25,7 +25,7 @@ namespace dlib
bool is_rgb() const;
template<typename T>
void get_image( T& t) const
void get_image( T& t_) const
{
#ifndef DLIB_JPEG_SUPPORT
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
......@@ -36,6 +36,7 @@ namespace dlib
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
COMPILE_TIME_ASSERT(sizeof(T) == 0);
#endif
image_view<T> t(t_);
t.set_size( height_, width_ );
for ( unsigned n = 0; n < height_;n++ )
......
......@@ -99,8 +99,8 @@ namespace dlib
) const;
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- loads the JPEG image stored in this object into img
!*/
......@@ -118,8 +118,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- performs: jpeg_loader(file_name).get_image(image);
!*/
......
......@@ -15,8 +15,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- let EXT == the extension of the file given by file_name converted
to lower case (i.e. the part of the file after the '.')
......
......@@ -30,7 +30,7 @@ namespace dlib
unsigned int bit_depth () const { return bit_depth_; }
template<typename T>
void get_image( T& t) const
void get_image( T& t_) const
{
#ifndef DLIB_PNG_SUPPORT
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
......@@ -42,7 +42,8 @@ namespace dlib
COMPILE_TIME_ASSERT(sizeof(T) == 0);
#endif
typedef typename T::type pixel_type;
typedef typename image_traits<T>::pixel_type pixel_type;
image_view<T> t(t_);
t.set_size( height_, width_ );
......@@ -148,7 +149,7 @@ namespace dlib
}
else if (is_rgba() && bit_depth_ == 8)
{
if (!pixel_traits<typename T::type>::has_alpha)
if (!pixel_traits<pixel_type>::has_alpha)
assign_all_pixels(t,0);
for ( unsigned n = 0; n < height_;n++ )
......@@ -167,7 +168,7 @@ namespace dlib
}
else if (is_rgba() && bit_depth_ == 16)
{
if (!pixel_traits<typename T::type>::has_alpha)
if (!pixel_traits<pixel_type>::has_alpha)
assign_all_pixels(t,0);
for ( unsigned n = 0; n < height_;n++ )
......
......@@ -127,8 +127,8 @@ namespace dlib
) const;
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- loads the PNG image stored in this object into img
!*/
......@@ -146,8 +146,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- performs: png_loader(file_name).get_image(image);
!*/
......
This diff is collapsed.
......@@ -589,8 +589,6 @@ namespace dlib
feats.set_size(levels);
typedef typename image_type::type pixel_type;
typedef typename image_type::mem_manager_type mem_manager_type;
// build our feature pyramid
fe(img, feats[0], cell_size,filter_rows_padding,filter_cols_padding);
......@@ -600,7 +598,7 @@ namespace dlib
if (feats.size() > 1)
{
array2d<pixel_type,mem_manager_type> temp1, temp2;
image_type temp1, temp2;
pyr(img, temp1);
fe(temp1, feats[1], cell_size,filter_rows_padding,filter_cols_padding);
swap(temp1,temp2);
......
......@@ -56,8 +56,8 @@ namespace dlib
for (unsigned long i = 0; i < images.size(); ++i)
{
if (images[0].nr() != images[i].nr() ||
images[0].nc() != images[i].nc())
if (num_rows(images[0]) != num_rows(images[i]) ||
num_columns(images[0]) != num_columns(images[i]))
return false;
}
......@@ -93,7 +93,7 @@ namespace dlib
#endif
typedef typename image_array_type::type::type pixel_type;
typedef typename image_traits<typename image_array_type::type>::pixel_type pixel_type;
typedef typename promote<pixel_type>::type ptype;
ptype temp = 0;
......@@ -151,7 +151,7 @@ namespace dlib
);
}
#endif
typedef typename image_array_type::type::type pixel_type;
typedef typename image_traits<typename image_array_type::type>::pixel_type pixel_type;
typedef typename promote<pixel_type>::type ptype;
ptype temp = 0;
......@@ -190,12 +190,13 @@ namespace dlib
>
void find_points_above_thresh (
std::vector<std::pair<double, point> >& dets,
const image_type& img,
const image_type& img_,
const double thresh,
const unsigned long max_dets
)
{
typedef typename image_type::type ptype;
const_image_view<image_type> img(img_);
typedef typename image_traits<image_type>::pixel_type ptype;
dets.clear();
if (max_dets == 0)
......@@ -269,7 +270,7 @@ namespace dlib
typedef typename image_array_type::type::type pixel_type;
typedef typename image_traits<typename image_array_type::type>::pixel_type pixel_type;
typedef typename promote<pixel_type>::type ptype;
array2d<ptype> accum(images[0].nr(), images[0].nc());
......@@ -338,7 +339,7 @@ namespace dlib
if (movable_rects.size() == 0 && fixed_rects.size() == 0)
return;
typedef typename image_array_type::type::type pixel_type;
typedef typename image_traits<typename image_array_type::type>::pixel_type pixel_type;
typedef typename promote<pixel_type>::type ptype;
array2d<ptype> accum(images[0].nr(), images[0].nc());
......
......@@ -21,7 +21,8 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h
ensures
- if (all elements of images have the same dimensions (i.e.
for all i and j: get_rect(images[i]) == get_rect(images[j]))) then
......@@ -43,8 +44,9 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h. Moreover, these objects must
contain a scalar pixel type (e.g. int rather than rgb_pixel)
- all_images_same_size(images) == true
- for all valid i: rects[i].first < images.size()
(i.e. all the rectangles must reference valid elements of images)
......@@ -70,8 +72,9 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h. Moreover, these objects must
contain a scalar pixel type (e.g. int rather than rgb_pixel)
- all_images_same_size(images) == true
- center(window) == point(0,0)
- for all valid i:
......@@ -109,8 +112,9 @@ namespace dlib
);
/*!
requires
- image_type == an implementation of array2d/array2d_kernel_abstract.h
- image_type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h. Moreover, these it must contain a
scalar pixel type (e.g. int rather than rgb_pixel)
ensures
- #dets == a list of points from img which had pixel values >= thresh.
- Specifically, we have:
......@@ -142,8 +146,9 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h. Moreover, these objects must
contain a scalar pixel type (e.g. int rather than rgb_pixel)
- images.size() > 0
- rects.size() > 0
- all_images_same_size(images) == true
......@@ -179,8 +184,9 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h. Moreover, these objects must
contain a scalar pixel type (e.g. int rather than rgb_pixel)
- images.size() > 0
- all_images_same_size(images) == true
- center(window) == point(0,0)
......
......@@ -10,6 +10,7 @@
#include "../array2d.h"
#include <vector>
#include "full_object_detection.h"
#include "../image_processing/generic_image.h"
namespace dlib
{
......
......@@ -127,9 +127,9 @@ namespace dlib
- image_type must be a type with the following properties:
- image_type is default constructable.
- image_type is swappable by the global swap() function.
- image_type logically represents some kind of image and therefore
has .nr() and .nc() member functions. .nr() should return the
number of rows while .nc() returns the number of columns.
- image_type logically represents some kind of image and therefore its
number of rows and columns can be queried via num_rows(img) and
num_columns(img) respectively.
- image_type objects can be loaded into Feature_extractor_type
objects via Feature_extractor_type::load().
- image_type objects can be used with Pyramid_type. That is,
......
......@@ -33,7 +33,7 @@ namespace dlib
template <
typename image_type,
bool grayscale = pixel_traits<typename image_type::type>::grayscale
bool grayscale = pixel_traits<typename image_traits<image_type>::pixel_type>::grayscale
>
struct save_bmp_helper;
......@@ -42,10 +42,11 @@ namespace dlib
struct save_bmp_helper<image_type,false>
{
static void save_bmp (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
// we are going to write out a 24bit color image.
byte_orderer::kernel_1a bo;
......@@ -133,10 +134,11 @@ namespace dlib
struct save_bmp_helper<image_type,true>
{
static void save_bmp (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
// we are going to write out an 8bit color image.
byte_orderer::kernel_1a bo;
......@@ -256,20 +258,9 @@ namespace dlib
namespace dng_helpers_namespace
{
template <
typename image_type,
int pixel_type = static_switch <
pixel_traits<typename image_type::type>::grayscale && sizeof(typename image_type::type) == 1,
pixel_traits<typename image_type::type>::rgb,
pixel_traits<typename image_type::type>::hsi,
false,
pixel_traits<typename image_type::type>::rgb_alpha,
false,
pixel_traits<typename image_type::type>::grayscale && sizeof(typename image_type::type) != 1 &&
!is_float_type<typename image_type::type>::value,
is_float_type<typename image_type::type>::value
>::value
typename enabled = void
>
struct save_dng_helper;
......@@ -279,13 +270,14 @@ namespace dlib
typedef entropy_encoder_model<256,encoder_type>::kernel_4a eem_exp_type;
template <typename image_type >
struct save_dng_helper<image_type, grayscale_float>
struct save_dng_helper<image_type, typename enable_if<is_float_type<typename image_traits<image_type>::pixel_type> >::type >
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -334,14 +326,24 @@ namespace dlib
};
template <typename image_type>
struct is_non_float_non8bit_grayscale
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::grayscale &&
sizeof(pixel_type) != 1 &&
!is_float_type<pixel_type>::value;
};
template <typename image_type >
struct save_dng_helper<image_type, grayscale_16bit>
struct save_dng_helper<image_type, typename enable_if<is_non_float_non8bit_grayscale<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -375,15 +377,22 @@ namespace dlib
}
};
template <typename image_type>
struct is_8bit_grayscale
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::grayscale && sizeof(pixel_type) == 1;
};
template <typename image_type>
struct save_dng_helper<image_type, grayscale>
struct save_dng_helper<image_type, typename enable_if<is_8bit_grayscale<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -415,13 +424,21 @@ namespace dlib
};
template <typename image_type>
struct save_dng_helper<image_type,rgb>
struct is_rgb_image
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::rgb;
};
template <typename image_type>
struct save_dng_helper<image_type,typename enable_if<is_rgb_image<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -480,13 +497,21 @@ namespace dlib
};
template <typename image_type>
struct save_dng_helper<image_type,rgb_alpha>
struct is_rgb_alpha_image
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::rgb_alpha;
};
template <typename image_type>
struct save_dng_helper<image_type,typename enable_if<is_rgb_alpha_image<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -547,13 +572,21 @@ namespace dlib
};
template <typename image_type>
struct save_dng_helper<image_type,hsi>
struct is_hsi_image
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::hsi;
};
template <typename image_type>
struct save_dng_helper<image_type,typename enable_if<is_hsi_image<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......
......@@ -29,9 +29,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any kind of matrix expression.
ensures
- writes the image to the out stream in the Microsoft Windows BMP format.
- image[0][0] will be in the upper left corner of the image.
......@@ -58,9 +57,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any kind of matrix expression.
ensures
- opens the file indicated by file_name with an output file stream named fout
and performs:
......@@ -85,9 +83,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any kind of matrix expression.
ensures
- writes the image to the out stream in the dlib dng format.
- image[0][0] will be in the upper left corner of the image.
......@@ -114,9 +111,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any kind of matrix expression.
ensures
- opens the file indicated by file_name with an output file stream named fout
and performs:
......
......@@ -41,10 +41,12 @@ namespace dlib
typename image_type
>
typename disable_if<is_matrix<image_type> >::type save_png(
const image_type& img,
const image_type& img_,
const std::string& file_name
)
{
const_image_view<image_type> img(img_);
// make sure requires clause is not broken
DLIB_CASSERT(img.size() != 0,
"\t save_png()"
......@@ -62,7 +64,7 @@ namespace dlib
COMPILE_TIME_ASSERT(sizeof(image_type) == 0);
#else
std::vector<unsigned char*> row_pointers(img.nr());
typedef typename image_type::type pixel_type;
typedef typename image_traits<image_type>::pixel_type pixel_type;
if (is_same_type<rgb_pixel,pixel_type>::value)
{
......@@ -82,7 +84,7 @@ namespace dlib
{
// convert from HSI to RGB (Or potentially RGB pixels that aren't laid out as R G B)
array2d<rgb_pixel> temp_img;
assign_image(temp_img, img);
assign_image(temp_img, img_);
for (unsigned long i = 0; i < row_pointers.size(); ++i)
row_pointers[i] = (unsigned char*)(&temp_img[i][0]);
......@@ -92,7 +94,7 @@ namespace dlib
{
// convert from RGBA pixels that aren't laid out as R G B A
array2d<rgb_alpha_pixel> temp_img;
assign_image(temp_img, img);
assign_image(temp_img, img_);
for (unsigned long i = 0; i < row_pointers.size(); ++i)
row_pointers[i] = (unsigned char*)(&temp_img[i][0]);
......@@ -120,7 +122,7 @@ namespace dlib
{
// convert from whatever this is to 16bit grayscale
array2d<dlib::uint16> temp_img;
assign_image(temp_img, img);
assign_image(temp_img, img_);
for (unsigned long i = 0; i < row_pointers.size(); ++i)
row_pointers[i] = (unsigned char*)(&temp_img[i][0]);
......
......@@ -19,9 +19,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or a matrix expression
- image.size() != 0
ensures
- writes the image to the file indicated by file_name in the PNG (Portable Network Graphics)
......
......@@ -10,36 +10,6 @@
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename dest_image_type,
typename src_pixel_type
>
typename enable_if<is_matrix<dest_image_type> >::type impl_assign_single_pixel (
dest_image_type& img,
long r,
long c,
const src_pixel_type& pix
)
{
assign_pixel(img(r,c), pix);
}
template <
typename dest_image_type,
typename src_pixel_type
>
typename disable_if<is_matrix<dest_image_type> >::type impl_assign_single_pixel (
dest_image_type& img,
long r,
long c,
const src_pixel_type& pix
)
{
assign_pixel(img[r][c], pix);
}
// ----------------------------------------------------------------------------------------
template <
......@@ -47,21 +17,33 @@ namespace dlib
typename src_image_type
>
void impl_assign_image (
dest_image_type& dest,
image_view<dest_image_type>& dest,
const src_image_type& src
)
{
dest.set_size(src.nr(),src.nc());
for (long r = 0; r < src.nr(); ++r)
{
for (long c = 0; c < src.nc(); ++c)
{
impl_assign_single_pixel(dest,r,c, src(r,c));
assign_pixel(dest[r][c], src(r,c));
}
}
}
template <
typename dest_image_type,
typename src_image_type
>
void impl_assign_image (
dest_image_type& dest_,
const src_image_type& src
)
{
image_view<dest_image_type> dest(dest_);
impl_assign_image(dest, src);
}
template <
typename dest_image_type,
typename src_image_type
......@@ -85,9 +67,9 @@ namespace dlib
typename src_image_type
>
void impl_assign_image_scaled (
dest_image_type& dest,
image_view<dest_image_type>& dest,
const src_image_type& src,
const double thresh = 4
const double thresh
)
{
DLIB_ASSERT( thresh > 0,
......@@ -96,12 +78,15 @@ namespace dlib
<< "\n\t thresh: " << thresh
);
typedef typename image_traits<dest_image_type>::pixel_type dest_pixel;
// If the destination has a dynamic range big enough to contain the source image data then just do a
// regular assign_image()
if (pixel_traits<typename dest_image_type::type>::max() >= pixel_traits<typename src_image_type::type>::max() &&
pixel_traits<typename dest_image_type::type>::min() <= pixel_traits<typename src_image_type::type>::min() )
if (pixel_traits<dest_pixel>::max() >= pixel_traits<typename src_image_type::type>::max() &&
pixel_traits<dest_pixel>::min() <= pixel_traits<typename src_image_type::type>::min() )
{
assign_image(dest, src);
impl_assign_image(dest, src);
return;
}
......@@ -112,7 +97,7 @@ namespace dlib
if (src.size() == 1)
{
impl_assign_single_pixel(dest,0,0, src(0,0));
impl_assign_image(dest, src);
return;
}
......@@ -131,8 +116,8 @@ namespace dlib
{
// If the destination has a dynamic range big enough to contain the source image data then just do a
// regular assign_image()
if (pixel_traits<typename dest_image_type::type>::max() >= rs.max() &&
pixel_traits<typename dest_image_type::type>::min() <= rs.min() )
if (pixel_traits<dest_pixel>::max() >= rs.max() &&
pixel_traits<dest_pixel>::min() <= rs.min() )
{
impl_assign_image(dest, src);
return;
......@@ -145,8 +130,8 @@ namespace dlib
const double lower = std::max(rs.mean() - thresh*rs.stddev(), rs.min());
const double dest_min = pixel_traits<typename dest_image_type::type>::min();
const double dest_max = pixel_traits<typename dest_image_type::type>::max();
const double dest_min = pixel_traits<dest_pixel>::min();
const double dest_max = pixel_traits<dest_pixel>::max();
const double scale = (upper!=lower)? ((dest_max - dest_min) / (upper - lower)) : 0;
......@@ -156,11 +141,25 @@ namespace dlib
{
const double val = get_pixel_intensity(src(r,c)) - lower;
impl_assign_single_pixel(dest,r,c, scale*val + dest_min);
assign_pixel(dest[r][c], scale*val + dest_min);
}
}
}
template <
typename dest_image_type,
typename src_image_type
>
void impl_assign_image_scaled (
dest_image_type& dest_,
const src_image_type& src,
const double thresh
)
{
image_view<dest_image_type> dest(dest_);
impl_assign_image_scaled(dest, src, thresh);
}
template <
typename dest_image_type,
typename src_image_type
......@@ -185,7 +184,7 @@ namespace dlib
typename src_pixel_type
>
void assign_all_pixels (
dest_image_type& dest_img,
image_view<dest_image_type>& dest_img,
const src_pixel_type& src_pixel
)
{
......@@ -198,16 +197,31 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template <
typename dest_image_type,
typename src_pixel_type
>
void assign_all_pixels (
dest_image_type& dest_img_,
const src_pixel_type& src_pixel
)
{
image_view<dest_image_type> dest_img(dest_img_);
assign_all_pixels(dest_img, src_pixel);
}
// ----------------------------------------------------------------------------------------
template <
typename image_type
>
void assign_border_pixels (
image_type& img,
image_view<image_type>& img,
long x_border_size,
long y_border_size,
const typename image_type::type& p
const typename image_traits<image_type>::pixel_type& p
)
{
DLIB_ASSERT( x_border_size >= 0 && y_border_size >= 0,
......@@ -251,6 +265,20 @@ namespace dlib
}
}
template <
typename image_type
>
void assign_border_pixels (
image_type& img_,
long x_border_size,
long y_border_size,
const typename image_traits<image_type>::pixel_type& p
)
{
image_view<image_type> img(img_);
assign_border_pixels(img, x_border_size, y_border_size, p);
}
// ----------------------------------------------------------------------------------------
template <
......@@ -269,7 +297,7 @@ namespace dlib
<< "\n\ty_border_size: " << y_border_size
);
typename image_type::type zero_pixel;
typename image_traits<image_type>::pixel_type zero_pixel;
assign_pixel_intensity(zero_pixel, 0);
assign_border_pixels(img, x_border_size, y_border_size, zero_pixel);
}
......@@ -280,7 +308,30 @@ namespace dlib
typename image_type
>
void zero_border_pixels (
image_type& img,
image_view<image_type>& img,
long x_border_size,
long y_border_size
)
{
DLIB_ASSERT( x_border_size >= 0 && y_border_size >= 0,
"\tvoid zero_border_pixels(img, p, border_size)"
<< "\n\tYou have given an invalid border_size"
<< "\n\tx_border_size: " << x_border_size
<< "\n\ty_border_size: " << y_border_size
);
typename image_traits<image_type>::pixel_type zero_pixel;
assign_pixel_intensity(zero_pixel, 0);
assign_border_pixels(img, x_border_size, y_border_size, zero_pixel);
}
// ----------------------------------------------------------------------------------------
template <
typename image_type
>
void zero_border_pixels (
image_view<image_type>& img,
rectangle inside
)
{
......@@ -307,6 +358,20 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template <
typename image_type
>
void zero_border_pixels (
image_type& img_,
const rectangle& inside
)
{
image_view<image_type> img(img_);
zero_border_pixels(img, inside);
}
// ----------------------------------------------------------------------------------------
}
......
......@@ -20,12 +20,11 @@ namespace dlib
);
/*!
requires
- src_image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix or something convertible to a matrix via mat()
- dest_image_type == is an implementation of array2d/array2d_kernel_abstract.h or
is a dlib::matrix.
- pixel_traits<typename src_image_type::type> is defined
- pixel_traits<typename dest_image_type::type> is defined
- src_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any object convertible to a matrix
via mat().
- dest_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view.
ensures
- #dest_img.nc() == src_img.nc()
- #dest_img.nr() == src_img.nr()
......@@ -47,12 +46,11 @@ namespace dlib
);
/*!
requires
- src_image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix or something convertible to a matrix via mat()
- dest_image_type == is an implementation of array2d/array2d_kernel_abstract.h or
is a dlib::matrix.
- pixel_traits<typename src_image_type::type> is defined
- pixel_traits<typename dest_image_type::type> is defined
- src_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any object convertible to a matrix
via mat().
- dest_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view.
- thresh > 0
ensures
- #dest_img.nc() == src_img.nc()
......@@ -77,8 +75,8 @@ namespace dlib
the following mapping:
let SRC_UPPER = min(M + thresh*D, max(mat(src_img)))
let SRC_LOWER = max(M - thresh*D, min(mat(src_img)))
let DEST_UPPER = pixel_traits<dest_image_type::type>::max()
let DEST_LOWER = pixel_traits<dest_image_type::type>::min()
let DEST_UPPER = pixel_traits<image_traits<dest_image_type>::pixel_type>::max()
let DEST_LOWER = pixel_traits<image_traits<dest_image_type>::pixel_type>::min()
MAPPING: [SRC_LOWER, SRC_UPPER] -> [DEST_LOWER, DEST_UPPER]
......@@ -101,8 +99,8 @@ namespace dlib
);
/*!
requires
- dest_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename dest_image_type::type> is defined
- dest_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view.
- pixel_traits<src_pixel_type> is defined
ensures
- #dest_img.nc() == dest_img.nc()
......@@ -122,11 +120,12 @@ namespace dlib
image_type& img,
long x_border_size,
long y_border_size,
const typename image_type::type& p
const typename image_traits<image_type>::pixel_type& p
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view
- x_border_size >= 0
- y_border_size >= 0
ensures
......@@ -151,10 +150,10 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view
- x_border_size >= 0
- y_border_size >= 0
- pixel_traits<typename image_type::type> is defined
ensures
- #img.nc() == img.nc()
- #img.nr() == img.nr()
......@@ -176,8 +175,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view
ensures
- #img.nc() == img.nc()
- #img.nr() == img.nr()
......
......@@ -25,7 +25,7 @@ namespace dlib
const static long NC = 0;
typedef rgb_pixel type;
typedef const rgb_pixel const_ret_type;
typedef typename T::mem_manager_type mem_manager_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const
......@@ -47,8 +47,8 @@ namespace dlib
}
}
long nr () const { return img.nr(); }
long nc () const { return img.nc(); }
long nr () const { return num_rows(img); }
long nc () const { return num_columns(img); }
};
template <
......@@ -84,7 +84,7 @@ namespace dlib
const static long NC = 0;
typedef rgb_pixel type;
typedef const rgb_pixel const_ret_type;
typedef typename T::mem_manager_type mem_manager_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const
......@@ -107,8 +107,8 @@ namespace dlib
return pix;
}
long nr () const { return img.nr(); }
long nc () const { return img.nc(); }
long nr () const { return num_rows(img); }
long nc () const { return num_columns(img); }
};
template <
......@@ -158,7 +158,7 @@ namespace dlib
const static long NC = 0;
typedef rgb_pixel type;
typedef const rgb_pixel const_ret_type;
typedef typename T::mem_manager_type mem_manager_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const
......@@ -203,8 +203,8 @@ namespace dlib
return pix;
}
long nr () const { return img.nr(); }
long nc () const { return img.nc(); }
long nr () const { return num_rows(img); }
long nc () const { return num_columns(img); }
};
template <
......
......@@ -21,9 +21,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- randomly generates a mapping from gray level pixel values
to the RGB pixel space and then uses this mapping to create
......@@ -46,9 +46,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- Interprets img as a grayscale image and returns a new matrix
which represents a colored version of img. In particular, the
......@@ -68,9 +68,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- returns heatmap(img, max(mat(img)), min(mat(img)))
!*/
......@@ -88,9 +88,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- Interprets img as a grayscale image and returns a new matrix which represents
a colored version of img. In particular, the colors will depict img using a
......@@ -110,9 +110,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- returns jet(img, max(mat(img)), min(mat(img)))
!*/
......
......@@ -23,10 +23,11 @@ namespace dlib
long y1,
long x2,
long y2,
image_type& c,
image_type& c_,
const pixel_type& val
)
{
image_view<image_type> c(c_);
if (x1 == x2)
{
// make sure y1 comes before y2
......@@ -214,11 +215,12 @@ namespace dlib
typename pixel_type
>
void fill_rect (
image_type& img,
image_type& img_,
const rectangle& rect,
const pixel_type& pixel
)
{
image_view<image_type> img(img_);
rectangle area = rect.intersect(get_rect(img));
for (long r = area.top(); r <= area.bottom(); ++r)
......@@ -235,11 +237,11 @@ namespace dlib
template <
typename image_array_type
>
matrix<typename image_array_type::value_type::type> tile_images (
matrix<typename image_traits<typename image_array_type::value_type>::pixel_type> tile_images (
const image_array_type& images
)
{
typedef typename image_array_type::value_type::type T;
typedef typename image_traits<typename image_array_type::value_type>::pixel_type T;
if (images.size() == 0)
return matrix<T>();
......@@ -252,8 +254,8 @@ namespace dlib
long nc = 0;
for (unsigned long i = 0; i < images.size(); ++i)
{
nr = std::max(images[i].nr(), nr);
nc = std::max(images[i].nc(), nc);
nr = std::max(num_rows(images[i]), nr);
nc = std::max(num_columns(images[i]), nc);
}
matrix<T> temp(size_nr*nr, size_nc*nc);
......
......@@ -22,8 +22,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<pixel_type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- #img.nr() == img.nr() && #img.nc() == img.nc()
(i.e. the dimensions of the input image are not changed)
......@@ -48,8 +48,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<pixel_type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- performs draw_line(img, point(x1,y1), point(x2,y2), val)
!*/
......@@ -68,12 +68,13 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- pixel_traits<pixel_type> is defined
ensures
- Draws the given rectangle onto the image img. It does this by calling
draw_line() four times to draw the four sides of the rectangle.
- The rectancle is drawn with the color given by val.
- The rectangle is drawn with the color given by val.
- The drawn rectangle will have edges that are thickness pixels wide.
!*/
......@@ -90,6 +91,8 @@ namespace dlib
);
/*!
requires
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- pixel_traits<pixel_type> is defined
ensures
- fills the area defined by rect in the given image with the given pixel value.
......@@ -100,13 +103,13 @@ namespace dlib
template <
typename image_array_type
>
matrix<typename image_array_type::value_type::type> tile_images (
matrix<typename image_traits<typename image_array_type::value_type>::pixel_type> tile_images (
const image_array_type& images
);
/*!
requires
- image_array_type is a dlib::array of array2d objects, each containing pixels
with a pixel_traits definition or any type with a compatible interface.
- image_array_type is a dlib::array of image objects where each image object
implements the interface defined in dlib/image_processing/generic_image.h
ensures
- This function takes the given images and tiles them into a single large
square image and returns this new big tiled image. Therefore, it is a useful
......
......@@ -101,19 +101,20 @@ namespace dlib
typename out_image_type
>
void sobel_edge_detector (
const in_image_type& in_img,
out_image_type& horz,
out_image_type& vert
const in_image_type& in_img_,
out_image_type& horz_,
out_image_type& vert_
)
{
COMPILE_TIME_ASSERT(pixel_traits<typename out_image_type::type>::is_unsigned == false);
DLIB_ASSERT( !is_same_object(in_img,horz) && !is_same_object(in_img,vert) &&
!is_same_object(horz,vert),
"\tvoid sobel_edge_detector(in_img, horz, vert)"
typedef typename image_traits<out_image_type>::pixel_type pixel_type;
COMPILE_TIME_ASSERT(pixel_traits<pixel_type>::is_unsigned == false);
DLIB_ASSERT( !is_same_object(in_img_,horz_) && !is_same_object(in_img_,vert_) &&
!is_same_object(horz_,vert_),
"\tvoid sobel_edge_detector(in_img_, horz_, vert_)"
<< "\n\t You can't give the same image as more than one argument"
<< "\n\t is_same_object(in_img,horz): " << is_same_object(in_img,horz)
<< "\n\t is_same_object(in_img,vert): " << is_same_object(in_img,vert)
<< "\n\t is_same_object(horz,vert): " << is_same_object(horz,vert)
<< "\n\t is_same_object(in_img_,horz_): " << is_same_object(in_img_,horz_)
<< "\n\t is_same_object(in_img_,vert_): " << is_same_object(in_img_,vert_)
<< "\n\t is_same_object(horz_,vert_): " << is_same_object(horz_,vert_)
);
......@@ -127,6 +128,11 @@ namespace dlib
const long M = 3;
const long N = 3;
const_image_view<in_image_type> in_img(in_img_);
image_view<out_image_type> horz(horz_);
image_view<out_image_type> vert(vert_);
horz.set_size(in_img.nr(),in_img.nc());
vert.set_size(in_img.nr(),in_img.nc());
......@@ -145,7 +151,7 @@ namespace dlib
{
for (long c = first_col; c < last_col; ++c)
{
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type;
typedef typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type bp_type;
typename promote<bp_type>::type p, horz_temp, vert_temp;
horz_temp = 0;
......@@ -185,12 +191,16 @@ namespace dlib
typename out_image_type
>
void suppress_non_maximum_edges (
const in_image_type& horz,
const in_image_type& vert,
out_image_type& out_img
const in_image_type& horz_,
const in_image_type& vert_,
out_image_type& out_img_
)
{
COMPILE_TIME_ASSERT(is_signed_type<typename in_image_type::type>::value);
const_image_view<in_image_type> horz(horz_);
const_image_view<in_image_type> vert(vert_);
image_view<out_image_type> out_img(out_img_);
COMPILE_TIME_ASSERT(is_signed_type<typename image_traits<in_image_type>::pixel_type>::value);
DLIB_ASSERT( horz.nr() == vert.nr() && horz.nc() == vert.nc(),
"\tvoid suppress_non_maximum_edges(horz, vert, out_img)"
<< "\n\tYou have to give horz and vert gradient images that are the same size"
......@@ -199,11 +209,11 @@ namespace dlib
<< "\n\tvert.nr(): " << vert.nr()
<< "\n\tvert.nc(): " << vert.nc()
);
DLIB_ASSERT( !is_same_object(out_img,horz) && !is_same_object(out_img,vert),
"\tvoid suppress_non_maximum_edges(horz, vert, out_img)"
DLIB_ASSERT( !is_same_object(out_img_,horz_) && !is_same_object(out_img_,vert_),
"\tvoid suppress_non_maximum_edges(horz_, vert_, out_img_)"
<< "\n\t out_img can't be the same as one of the input images."
<< "\n\t is_same_object(out_img,horz): " << is_same_object(out_img,horz)
<< "\n\t is_same_object(out_img,vert): " << is_same_object(out_img,vert)
<< "\n\t is_same_object(out_img_,horz_): " << is_same_object(out_img_,horz_)
<< "\n\t is_same_object(out_img_,vert_): " << is_same_object(out_img_,vert_)
);
using std::min;
......@@ -237,7 +247,7 @@ namespace dlib
{
for (long c = first_col; c < last_col; ++c)
{
typedef typename promote<typename in_image_type::type>::type T;
typedef typename promote<typename image_traits<in_image_type>::pixel_type>::type T;
const T y = horz[r][c];
const T x = vert[r][c];
......
......@@ -45,10 +45,11 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type> must be defined
- pixel_traits<typename out_image_type::type>::is_unsigned == false
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type must use signed grayscale pixels
- is_same_object(in_img,horz) == false
- is_same_object(in_img,vert) == false
- is_same_object(horz,vert) == false
......@@ -79,14 +80,15 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename out_image_type::type> must be defined
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- horz.nr() == vert.nr()
- horz.nc() == vert.nc()
- is_same_object(out_img, horz) == false
- is_same_object(out_img, vert) == false
- in_image_type::type == A signed scalar type (e.g. int, double, etc.)
- image_traits<in_image_type>::pixel_type == A signed scalar type (e.g. int, double, etc.)
ensures
- #out_img.nr() = horz.nr()
- #out_img.nc() = horz.nc()
......
......@@ -21,24 +21,26 @@ namespace dlib
typename MM
>
void get_histogram (
const in_image_type& in_img,
const in_image_type& in_img_,
matrix<unsigned long,R,C,MM>& hist
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::is_unsigned == true );
typedef typename image_traits<in_image_type>::pixel_type pixel_type;
COMPILE_TIME_ASSERT( pixel_traits<pixel_type>::is_unsigned == true );
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type in_image_basic_pixel_type;
typedef typename pixel_traits<pixel_type>::basic_pixel_type in_image_basic_pixel_type;
COMPILE_TIME_ASSERT( sizeof(in_image_basic_pixel_type) <= 2);
// make sure hist is the right size
if (R == 1)
hist.set_size(1,pixel_traits<typename in_image_type::type>::max()+1);
hist.set_size(1,pixel_traits<pixel_type>::max()+1);
else
hist.set_size(pixel_traits<typename in_image_type::type>::max()+1,1);
hist.set_size(pixel_traits<pixel_type>::max()+1,1);
set_all_elements(hist,0);
const_image_view<in_image_type> in_img(in_img_);
// compute the histogram
for (long r = 0; r < in_img.nr(); ++r)
{
......@@ -57,20 +59,25 @@ namespace dlib
typename out_image_type
>
void equalize_histogram (
const in_image_type& in_img,
out_image_type& out_img
const in_image_type& in_img_,
out_image_type& out_img_
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
const_image_view<in_image_type> in_img(in_img_);
image_view<out_image_type> out_img(out_img_);
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::is_unsigned == true );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::is_unsigned == true );
typedef typename image_traits<in_image_type>::pixel_type in_pixel_type;
typedef typename image_traits<out_image_type>::pixel_type out_pixel_type;
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type in_image_basic_pixel_type;
COMPILE_TIME_ASSERT( pixel_traits<in_pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<out_pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<in_pixel_type>::is_unsigned == true );
COMPILE_TIME_ASSERT( pixel_traits<out_pixel_type>::is_unsigned == true );
typedef typename pixel_traits<in_pixel_type>::basic_pixel_type in_image_basic_pixel_type;
COMPILE_TIME_ASSERT( sizeof(in_image_basic_pixel_type) <= 2);
typedef typename out_image_type::type out_pixel_type;
// if there isn't any input image then don't do anything
if (in_img.size() == 0)
......@@ -83,8 +90,9 @@ namespace dlib
unsigned long p;
matrix<unsigned long,1,0,typename in_image_type::mem_manager_type> histogram;
get_histogram(in_img, histogram);
matrix<unsigned long,1,0> histogram;
get_histogram(in_img_, histogram);
in_img = in_img_;
double scale = pixel_traits<out_pixel_type>::max();
if (in_img.size() > histogram(0))
......
......@@ -21,13 +21,16 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- pixel_traits<typename in_image_type::type>::is_unsigned == true
- pixel_traits<typename out_image_type::type>::is_unsigned == true
- pixel_traits<typename in_image_type::type>::max() <= 65535
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- Let pixel_type be the type of pixel in either input or output images, then we
must have:
- pixel_traits<pixel_type>::has_alpha == false
- pixel_traits<pixel_type>::is_unsigned == true
- For the input image pixel type, we have the additional requirement that:
- pixel_traits<pixel_type>::max() <= 65535
ensures
- #out_img == the histogram equalized version of in_img
- #out_img.nc() == in_img.nc()
......@@ -61,9 +64,11 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::is_unsigned == true
- pixel_traits<typename in_image_type::type>::max() <= 65535
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- Let pixel_type denote the type of pixel in in_img, then we must have:
- pixel_traits<pixel_type>::is_unsigned == true
- pixel_traits<pixel_type>::max() <= 65535
- hist must be capable of representing a column vector of length
pixel_traits<typename in_image_type>::max(). I.e. if R and C are nonzero
then they must be values that don't conflict with the previous sentence.
......
......@@ -22,7 +22,7 @@ namespace dlib
namespace impl_fhog
{
template <typename image_type>
inline typename dlib::enable_if_c<pixel_traits<typename image_type::type>::rgb>::type get_gradient (
inline typename dlib::enable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient (
const int r,
const int c,
const image_type& img,
......@@ -60,7 +60,7 @@ namespace dlib
}
template <typename image_type>
inline typename dlib::enable_if_c<pixel_traits<typename image_type::type>::rgb>::type get_gradient (
inline typename dlib::enable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient (
const int r,
const int c,
const image_type& img,
......@@ -145,7 +145,7 @@ namespace dlib
// ------------------------------------------------------------------------------------
template <typename image_type>
inline typename dlib::disable_if_c<pixel_traits<typename image_type::type>::rgb>::type get_gradient (
inline typename dlib::disable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient (
const int r,
const int c,
const image_type& img,
......@@ -159,7 +159,7 @@ namespace dlib
}
template <typename image_type>
inline typename dlib::disable_if_c<pixel_traits<typename image_type::type>::rgb>::type get_gradient (
inline typename dlib::disable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient (
int r,
int c,
const image_type& img,
......@@ -275,13 +275,14 @@ namespace dlib
typename out_type
>
void impl_extract_fhog_features(
const image_type& img,
const image_type& img_,
out_type& hog,
int cell_size,
int filter_rows_padding,
int filter_cols_padding
)
{
const_image_view<image_type> img(img_);
// make sure requires clause is not broken
DLIB_ASSERT( cell_size > 0 &&
filter_rows_padding > 0 &&
......
......@@ -29,9 +29,8 @@ namespace dlib
- cell_size > 0
- filter_rows_padding > 0
- filter_cols_padding > 0
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- img contains some kind of pixel type.
(i.e. pixel_traits<typename image_type::type> is defined)
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- T should be float or double
ensures
- This function implements the HOG feature extraction method described in
......@@ -89,9 +88,8 @@ namespace dlib
- cell_size > 0
- filter_rows_padding > 0
- filter_cols_padding > 0
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- img contains some kind of pixel type.
(i.e. pixel_traits<typename image_type::type> is defined)
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- T should be float or double
ensures
- This function is identical to the above extract_fhog_features() routine
......@@ -124,9 +122,8 @@ namespace dlib
- cell_size > 0
- filter_rows_padding > 0
- filter_cols_padding > 0
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- img contains some kind of pixel type.
(i.e. pixel_traits<typename image_type::type> is defined)
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- This function calls the above extract_fhog_features() routine and simply
packages the entire output into a dlib::matrix. The matrix is constructed
......@@ -158,9 +155,8 @@ namespace dlib
- cell_size > 0
- filter_rows_padding > 0
- filter_cols_padding > 0
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- img contains some kind of pixel type.
(i.e. pixel_traits<typename image_type::type> is defined)
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- T is float, double, or long double
ensures
- This function is identical to the above version of extract_fhog_features()
......
This diff is collapsed.
......@@ -47,10 +47,12 @@ namespace dlib
/*!
requires
- is_same_object(original, down) == false
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- for both pixel types P in the input and output images, we require:
- pixel_traits<P>::has_alpha == false
ensures
- #down will contain an image that is roughly (N-1)/N times the size of the
original image.
......
......@@ -31,9 +31,10 @@ namespace dlib
template <typename image_type>
void load (
const image_type& img
const image_type& img_
)
{
const_image_view<image_type> img(img_);
T pixel;
int_img.set_size(img.nr(), img.nc());
......
......@@ -59,8 +59,10 @@ namespace dlib
);
/*!
requires
- image_type == a type that implements the array2d/array2d_kernel_abstract.h interface
- pixel_traits<typename image_type::type>::has_alpha == false
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- Let P denote the type of pixel in img, then we require:
- pixel_traits<P>::has_alpha == false
ensures
- #nr() == img.nr()
- #nc() == img.nc()
......
This diff is collapsed.
......@@ -113,19 +113,21 @@ namespace dlib
typename connected_functor_type
>
unsigned long label_connected_blobs (
const image_type& img,
const image_type& img_,
const background_functor_type& is_background,
const neighbors_functor_type& get_neighbors,
const connected_functor_type& is_connected,
label_image_type& label_img
label_image_type& label_img_
)
{
// make sure requires clause is not broken
DLIB_ASSERT(is_same_object(img, label_img) == false,
DLIB_ASSERT(is_same_object(img_, label_img_) == false,
"\t unsigned long label_connected_blobs()"
<< "\n\t The input image and output label image can't be the same object."
);
const_image_view<image_type> img(img_);
image_view<label_image_type> label_img(label_img_);
std::stack<point> neighbors;
label_img.set_size(img.nr(), img.nc());
......
......@@ -58,9 +58,9 @@ namespace dlib
with the label_connected_blobs() routine defined below.
!*/
template <typename image_type>
template <typename image_view_type>
bool operator() (
const image_type& img,
const image_view_type& img,
const point& a,
const point& b
) const
......@@ -77,9 +77,9 @@ namespace dlib
with the label_connected_blobs() routine defined below.
!*/
template <typename image_type>
template <typename image_view_type>
bool operator() (
const image_type& img,
const image_view_type& img,
const point& a,
const point& b
) const
......@@ -98,9 +98,9 @@ namespace dlib
with the label_connected_blobs() routine defined below.
!*/
template <typename image_type>
template <typename image_view_type>
bool operator() (
const image_type& img,
const image_view_type& img,
const point& p
) const
{
......@@ -117,9 +117,9 @@ namespace dlib
with the label_connected_blobs() routine defined below.
!*/
template <typename image_type>
template <typename image_view_type>
bool operator() (
const image_type&,
const image_view_type&,
const point&
) const
{
......@@ -146,9 +146,10 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- label_image_type == is an implementation of array2d/array2d_kernel_abstract.h
and it must contain integers.
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- label_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h and it must contain integer pixels.
- is_background(img, point(c,r)) is a legal expression that evaluates to a bool.
- is_connected(img, point(c,r), point(c2,r2)) is a legal expression that
evaluates to a bool.
......
......@@ -24,11 +24,11 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::grayscale == true
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type and out_image_type are image objects that implement the
interface defined in dlib/image_processing/generic_image.h
- in_img must contain a grayscale pixel type.
- both in_img and out_img must contain pixels with no alpha channel.
(i.e. pixel_traits::has_alpha==false for their pixels)
- is_same_object(in_img,out_img) == false
- M % 2 == 1 (i.e. M must be odd)
- N % 2 == 1 (i.e. N must be odd)
......@@ -58,11 +58,11 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::grayscale == true
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type and out_image_type are image objects that implement the
interface defined in dlib/image_processing/generic_image.h
- in_img must contain a grayscale pixel type.
- both in_img and out_img must contain pixels with no alpha channel.
(i.e. pixel_traits::has_alpha==false for their pixels)
- is_same_object(in_img,out_img) == false
- M % 2 == 1 (i.e. M must be odd)
- N % 2 == 1 (i.e. N must be odd)
......@@ -93,11 +93,11 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::grayscale == true
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type and out_image_type are image objects that implement the
interface defined in dlib/image_processing/generic_image.h
- in_img must contain a grayscale pixel type.
- both in_img and out_img must contain pixels with no alpha channel.
(i.e. pixel_traits::has_alpha==false for their pixels)
- is_same_object(in_img,out_img) == false
- M % 2 == 1 (i.e. M must be odd)
- N % 2 == 1 (i.e. N must be odd)
......@@ -129,11 +129,11 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::grayscale == true
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type and out_image_type are image objects that implement the
interface defined in dlib/image_processing/generic_image.h
- in_img must contain a grayscale pixel type.
- both in_img and out_img must contain pixels with no alpha channel.
(i.e. pixel_traits::has_alpha==false for their pixels)
- is_same_object(in_img,out_img) == false
- M % 2 == 1 (i.e. M must be odd)
- N % 2 == 1 (i.e. N must be odd)
......@@ -163,14 +163,11 @@ namespace dlib
);
/*!
requires
- in_image_type1 == is an implementation of array2d/array2d_kernel_abstract.h
- in_image_type2 == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type1::type>::grayscale == true
- pixel_traits<typename in_image_type2::type>::grayscale == true
- pixel_traits<typename in_image_type1::type>::has_alpha == false
- pixel_traits<typename in_image_type2::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type1, in_image_type2, and out_image_type are image objects that
implement the interface defined in dlib/image_processing/generic_image.h
- in_img1 and in_img2 must contain grayscale pixel types.
- in_img1, in_img2, and out_img must contain pixels with no alpha channel.
(i.e. pixel_traits::has_alpha==false for their pixels)
- all pixels in in_img1 and in_img2 are set to either on_pixel or off_pixel
(i.e. they must be binary images)
- in_img1.nc() == in_img2.nc()
......@@ -197,14 +194,11 @@ namespace dlib
);
/*!
requires
- in_image_type1 == is an implementation of array2d/array2d_kernel_abstract.h
- in_image_type2 == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type1::type>::grayscale == true
- pixel_traits<typename in_image_type2::type>::grayscale == true
- pixel_traits<typename in_image_type1::type>::has_alpha == false
- pixel_traits<typename in_image_type2::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type1, in_image_type2, and out_image_type are image objects that
implement the interface defined in dlib/image_processing/generic_image.h
- in_img1 and in_img2 must contain grayscale pixel types.
- in_img1, in_img2, and out_img must contain pixels with no alpha channel.
(i.e. pixel_traits::has_alpha==false for their pixels)
- all pixels in in_img1 and in_img2 are set to either on_pixel or off_pixel
(i.e. they must be binary images)
- in_img1.nc() == in_img2.nc()
......@@ -231,14 +225,11 @@ namespace dlib
);
/*!
requires
- in_image_type1 == is an implementation of array2d/array2d_kernel_abstract.h
- in_image_type2 == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type1::type>::grayscale == true
- pixel_traits<typename in_image_type2::type>::grayscale == true
- pixel_traits<typename in_image_type1::type>::has_alpha == false
- pixel_traits<typename in_image_type2::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type1, in_image_type2, and out_image_type are image objects that
implement the interface defined in dlib/image_processing/generic_image.h
- in_img1 and in_img2 must contain grayscale pixel types.
- in_img1, in_img2, and out_img must contain pixels with no alpha channel.
(i.e. pixel_traits::has_alpha==false for their pixels)
- all pixels in in_img1 and in_img2 are set to either on_pixel or off_pixel
(i.e. they must be binary images)
- in_img1.nc() == in_img2.nc()
......@@ -263,11 +254,11 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::grayscale == true
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- in_image_type and out_image_type are image objects that implement the
interface defined in dlib/image_processing/generic_image.h
- in_img must contain a grayscale pixel type.
- both in_img and out_img must contain pixels with no alpha channel.
(i.e. pixel_traits::has_alpha==false for their pixels)
- all pixels in in_img are set to either on_pixel or off_pixel
(i.e. it must be a binary image)
ensures
......
......@@ -125,18 +125,28 @@ namespace dlib
// ------------------------------------------------------------------------------------
namespace impl
{
template <typename image_view_type>
struct uint8_or_uint16_pixels
{
typedef typename image_view_type::pixel_type pixel_type;
const static bool value = is_same_type<pixel_type,uint8>::value ||
is_same_type<pixel_type,uint16>::value;
};
}
// This is an overload of get_pixel_edges() that is optimized to segment images
// with 8bit or 16bit pixels very quickly. We do this by using a radix sort
// instead of quicksort.
template <typename in_image_type, typename T>
typename enable_if_c<is_same_type<typename in_image_type::type,uint8>::value ||
is_same_type<typename in_image_type::type,uint16>::value>::type
typename enable_if<impl::uint8_or_uint16_pixels<in_image_type> >::type
get_pixel_edges (
const in_image_type& in_img,
std::vector<segment_image_edge_data_T<T> >& sorted_edges
)
{
typedef typename in_image_type::type ptype;
typedef typename in_image_type::pixel_type ptype;
typedef T diff_type;
std::vector<unsigned long> counts(std::numeric_limits<ptype>::max()+1, 0);
......@@ -243,8 +253,7 @@ namespace dlib
// This is the general purpose version of get_pixel_edges(). It handles all pixel types.
template <typename in_image_type, typename T>
typename disable_if_c<is_same_type<typename in_image_type::type,uint8>::value ||
is_same_type<typename in_image_type::type,uint16>::value>::type
typename disable_if<impl::uint8_or_uint16_pixels<in_image_type> >::type
get_pixel_edges (
const in_image_type& in_img,
std::vector<segment_image_edge_data_T<T> >& sorted_edges
......@@ -253,7 +262,7 @@ namespace dlib
const rectangle area = get_rect(in_img);
sorted_edges.reserve(area.area()*4);
typedef typename in_image_type::type ptype;
typedef typename in_image_type::pixel_type ptype;
edge_diff_funct<ptype> edge_diff;
typedef T diff_type;
typedef segment_image_edge_data_T<T> segment_image_edge_data;
......@@ -327,23 +336,26 @@ namespace dlib
typename out_image_type
>
void segment_image (
const in_image_type& in_img,
out_image_type& out_img,
const in_image_type& in_img_,
out_image_type& out_img_,
const double k = 200,
const unsigned long min_size = 10
)
{
using namespace dlib::impl;
typedef typename in_image_type::type ptype;
typedef typename image_traits<in_image_type>::pixel_type ptype;
typedef typename edge_diff_funct<ptype>::diff_type diff_type;
// make sure requires clause is not broken
DLIB_ASSERT(is_same_object(in_img, out_img) == false,
DLIB_ASSERT(is_same_object(in_img_, out_img_) == false,
"\t void segment_image()"
<< "\n\t The input images can't be the same object."
);
COMPILE_TIME_ASSERT(is_unsigned_type<typename out_image_type::type>::value);
COMPILE_TIME_ASSERT(is_unsigned_type<typename image_traits<out_image_type>::pixel_type>::value);
const_image_view<in_image_type> in_img(in_img_);
image_view<out_image_type> out_img(out_img_);
out_img.set_size(in_img.nr(), in_img.nc());
// don't bother doing anything if the image is too small
......@@ -610,7 +622,7 @@ namespace dlib
typename EXP
>
void find_candidate_object_locations (
const in_image_type& in_img,
const in_image_type& in_img_,
std::vector<rectangle>& rects,
const matrix_exp<EXP>& kvals,
const unsigned long min_size = 20,
......@@ -629,9 +641,10 @@ namespace dlib
typedef dlib::set<rectangle, mm_type>::kernel_1a set_of_rects;
using namespace dlib::impl;
typedef typename in_image_type::type ptype;
typedef typename image_traits<in_image_type>::pixel_type ptype;
typedef typename edge_diff_funct<ptype>::diff_type diff_type;
const_image_view<in_image_type> in_img(in_img_);
// don't bother doing anything if the image is too small
if (in_img.nr() < 2 || in_img.nc() < 2)
......
......@@ -23,11 +23,13 @@ namespace dlib
);
/*!
requires
- in_image_type == an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == an implementation of array2d/array2d_kernel_abstract.h
- in_image_type::type == Any pixel type with a pixel_traits specialization or a
dlib matrix object representing a row or column vector.
- out_image_type::type == unsigned integer type
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- in_image_type can contain any pixel type with a pixel_traits specialization
or a dlib matrix object representing a row or column vector.
- out_image_type must contain an unsigned integer pixel type.
- is_same_object(in_img, out_img) == false
ensures
- Attempts to segment in_img into regions which have some visual consistency to
......@@ -65,6 +67,8 @@ namespace dlib
);
/*!
requires
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- is_vector(kvals) == true
- kvals.size() > 0
ensures
......
This diff is collapsed.
......@@ -22,15 +22,18 @@ namespace dlib
typename out_image_type
>
void threshold_image (
const in_image_type& in_img,
out_image_type& out_img,
typename pixel_traits<typename in_image_type::type>::basic_pixel_type thresh
const in_image_type& in_img_,
out_image_type& out_img_,
typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type thresh
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT(pixel_traits<typename out_image_type::type>::grayscale);
COMPILE_TIME_ASSERT(pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale);
const_image_view<in_image_type> in_img(in_img_);
image_view<out_image_type> out_img(out_img_);
// if there isn't any input image then don't do anything
if (in_img.size() == 0)
......@@ -60,7 +63,7 @@ namespace dlib
>
void threshold_image (
image_type& img,
typename pixel_traits<typename image_type::type>::basic_pixel_type thresh
typename pixel_traits<typename image_traits<image_type>::pixel_type>::basic_pixel_type thresh
)
{
threshold_image(img,img,thresh);
......@@ -73,16 +76,19 @@ namespace dlib
typename out_image_type
>
void auto_threshold_image (
const in_image_type& in_img,
out_image_type& out_img
const in_image_type& in_img_,
out_image_type& out_img_
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::is_unsigned == true );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::is_unsigned == true );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<in_image_type>::pixel_type>::is_unsigned == true );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<out_image_type>::pixel_type>::is_unsigned == true );
COMPILE_TIME_ASSERT(pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale);
COMPILE_TIME_ASSERT(pixel_traits<typename out_image_type::type>::grayscale);
const_image_view<in_image_type> in_img(in_img_);
image_view<out_image_type> out_img(out_img_);
// if there isn't any input image then don't do anything
if (in_img.size() == 0)
......@@ -171,7 +177,7 @@ namespace dlib
thresh = (a + b)/2;
// now actually apply the threshold
threshold_image(in_img,out_img,thresh);
threshold_image(in_img_,out_img_,thresh);
}
template <
......@@ -191,25 +197,28 @@ namespace dlib
typename out_image_type
>
void hysteresis_threshold (
const in_image_type& in_img,
out_image_type& out_img,
typename pixel_traits<typename in_image_type::type>::basic_pixel_type lower_thresh,
typename pixel_traits<typename in_image_type::type>::basic_pixel_type upper_thresh
const in_image_type& in_img_,
out_image_type& out_img_,
typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type lower_thresh,
typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type upper_thresh
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT(pixel_traits<typename out_image_type::type>::grayscale);
COMPILE_TIME_ASSERT(pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale);
DLIB_ASSERT( lower_thresh <= upper_thresh && is_same_object(in_img, out_img) == false,
"\tvoid hysteresis_threshold(in_img, out_img, lower_thresh, upper_thresh)"
DLIB_ASSERT( lower_thresh <= upper_thresh && is_same_object(in_img_, out_img_) == false,
"\tvoid hysteresis_threshold(in_img_, out_img_, lower_thresh, upper_thresh)"
<< "\n\tYou can't use an upper_thresh that is less than your lower_thresh"
<< "\n\tlower_thresh: " << lower_thresh
<< "\n\tupper_thresh: " << upper_thresh
<< "\n\tis_same_object(in_img,out_img): " << is_same_object(in_img,out_img)
<< "\n\tis_same_object(in_img_,out_img_): " << is_same_object(in_img_,out_img_)
);
const_image_view<in_image_type> in_img(in_img_);
image_view<out_image_type> out_img(out_img_);
// if there isn't any input image then don't do anything
if (in_img.size() == 0)
{
......@@ -229,7 +238,7 @@ namespace dlib
{
for (long c = 0; c < in_img.nc(); ++c)
{
typename pixel_traits<typename in_image_type::type>::basic_pixel_type p;
typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type p;
assign_pixel(p,in_img[r][c]);
if (p >= upper_thresh)
{
......
......@@ -22,15 +22,15 @@ namespace dlib
void threshold_image (
const in_image_type& in_img,
out_image_type& out_img,
typename pixel_traits<typename in_image_type::type>::basic_pixel_type thresh
typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type thresh
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename out_image_type::type>::grayscale == true
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale == true
- pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false
- pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false
ensures
- #out_img == the thresholded version of in_img (in_img is converted to a grayscale
intensity image if it is color). Pixels in in_img with grayscale values >= thresh
......@@ -44,7 +44,7 @@ namespace dlib
>
void threshold_image (
image_type& img,
typename pixel_traits<typename image_type::type>::basic_pixel_type thresh
typename pixel_traits<typename image_traits<image_type>::pixel_type>::basic_pixel_type thresh
);
/*!
requires
......@@ -67,12 +67,12 @@ namespace dlib
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::max() <= 65535
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename in_image_type::type>::is_unsigned == true
- pixel_traits<typename out_image_type::type>::grayscale == true
- pixel_traits<typename out_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::is_unsigned == true
- pixel_traits<typename image_traits<in_image_type>::pixel_type>::max() <= 65535
- pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false
- pixel_traits<typename image_traits<in_image_type>::pixel_type>::is_unsigned == true
- pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale == true
- pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false
- pixel_traits<typename image_traits<out_image_type>::pixel_type>::is_unsigned == true
ensures
- #out_img == the thresholded version of in_img (in_img is converted to a grayscale
intensity image if it is color). Pixels in in_img with grayscale values >= thresh
......@@ -106,16 +106,16 @@ namespace dlib
void hysteresis_threshold (
const in_image_type& in_img,
out_image_type& out_img,
typename pixel_traits<typename in_image_type::type>::basic_pixel_type lower_thresh,
typename pixel_traits<typename in_image_type::type>::basic_pixel_type upper_thresh
typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type lower_thresh,
typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type upper_thresh
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename out_image_type::type>::grayscale == true
- pixel_traits<typename in_image_type::type>::has_alpha == false
- pixel_traits<typename out_image_type::type>::has_alpha == false
- pixel_traits<typename image_traits<out_image_type>::pixel_type>::grayscale == true
- pixel_traits<typename image_traits<in_image_type>::pixel_type>::has_alpha == false
- pixel_traits<typename image_traits<out_image_type>::pixel_type>::has_alpha == false
- lower_thresh <= upper_thresh
- is_same_object(in_img, out_img) == false
ensures
......
......@@ -13,6 +13,7 @@
#include "matrix/matrix_conv.h"
#include "matrix/matrix_read_from_istream.h"
#include "matrix/matrix_fft.h"
#include "matrix/matrix_generic_image.h"
#ifdef DLIB_USE_BLAS
#include "matrix/matrix_blas_bindings.h"
......
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATRIX_GENERIC_iMAGE_H__
#define DLIB_MATRIX_GENERIC_iMAGE_H__
#include "matrix.h"
#include "../image_processing/generic_image.h"
namespace dlib
{
template <
typename T,
long NR,
long NC,
typename MM
>
struct image_traits<matrix<T,NR,NC,MM> >
{
typedef T pixel_type;
};
template <
typename T,
long NR,
long NC,
typename MM
>
inline long num_rows( const matrix<T,NR,NC,MM>& img) { return img.nr(); }
template <
typename T,
long NR,
long NC,
typename MM
>
inline long num_columns( const matrix<T,NR,NC,MM>& img) { return img.nc(); }
template <
typename T,
long NR,
long NC,
typename MM
>
inline void set_image_size(
matrix<T,NR,NC,MM>& img,
long rows,
long cols
) { img.set_size(rows,cols); }
template <
typename T,
long NR,
long NC,
typename MM
>
inline void* image_data(
matrix<T,NR,NC,MM>& img
)
{
if (img.size() != 0)
return &img(0,0);
else
return 0;
}
template <
typename T,
long NR,
long NC,
typename MM
>
inline const void* image_data(
const matrix<T,NR,NC,MM>& img
)
{
if (img.size() != 0)
return &img(0,0);
else
return 0;
}
template <
typename T,
long NR,
long NC,
typename MM
>
inline long width_step(
const matrix<T,NR,NC,MM>& img
)
{
return img.nc()*sizeof(T);
}
}
#endif // DLIB_MATRIX_GENERIC_iMAGE_H__
......@@ -9,6 +9,7 @@
#include "matrix_op.h"
#include "../array2d.h"
#include "../array.h"
#include "../image_processing/generic_image.h"
namespace dlib
......@@ -28,39 +29,112 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <typename T>
struct op_array2d_to_mat : does_not_alias
template <typename image_type, typename pixel_type>
struct op_image_to_mat : does_not_alias
{
op_array2d_to_mat( const T& array_) : array(array_){}
op_image_to_mat( const image_type& img) : imgview(img){}
const T& array;
const_image_view<image_type> imgview;
const static long cost = 1;
const static long NR = 0;
const static long NC = 0;
typedef typename T::type type;
typedef const typename T::type& const_ret_type;
typedef typename T::mem_manager_type mem_manager_type;
typedef pixel_type type;
typedef const pixel_type& const_ret_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const { return array[r][c]; }
const_ret_type apply (long r, long c ) const { return imgview[r][c]; }
long nr () const { return array.nr(); }
long nc () const { return array.nc(); }
long nr () const { return imgview.nr(); }
long nc () const { return imgview.nc(); }
};
// ----------------------------------------------------------------------------------------
template <
typename T,
typename MM
>
const matrix_op<op_array2d_to_mat<array2d<T,MM> > > mat (
const array2d<T,MM>& array
typename image_type
> // The reason we disable this if it is a matrix is because this matrix_op claims
// to not alias any matrix. But obviously that would be a problem if we let it
// take a matrix.
const typename disable_if<is_matrix<image_type>,matrix_op<op_image_to_mat<image_type, typename image_traits<image_type>::pixel_type> > >::type mat (
const image_type& img
)
{
typedef op_array2d_to_mat<array2d<T,MM> > op;
return matrix_op<op>(op(array));
typedef op_image_to_mat<image_type, typename image_traits<image_type>::pixel_type> op;
return matrix_op<op>(op(img));
}
// ----------------------------------------------------------------------------------------
template <typename image_type>
struct op_image_view_to_mat : does_not_alias
{
op_image_view_to_mat( const image_view<image_type>& img) : imgview(img){}
typedef typename image_traits<image_type>::pixel_type pixel_type;
const image_view<image_type>& imgview;
const static long cost = 1;
const static long NR = 0;
const static long NC = 0;
typedef pixel_type type;
typedef const pixel_type& const_ret_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const { return imgview[r][c]; }
long nr () const { return imgview.nr(); }
long nc () const { return imgview.nc(); }
};
template <
typename image_type
>
const matrix_op<op_image_view_to_mat<image_type> > mat (
const image_view<image_type>& img
)
{
typedef op_image_view_to_mat<image_type> op;
return matrix_op<op>(op(img));
}
// ----------------------------------------------------------------------------------------
template <typename image_type>
struct op_const_image_view_to_mat : does_not_alias
{
op_const_image_view_to_mat( const const_image_view<image_type>& img) : imgview(img){}
typedef typename image_traits<image_type>::pixel_type pixel_type;
const const_image_view<image_type>& imgview;
const static long cost = 1;
const static long NR = 0;
const static long NC = 0;
typedef pixel_type type;
typedef const pixel_type& const_ret_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const { return imgview[r][c]; }
long nr () const { return imgview.nr(); }
long nc () const { return imgview.nc(); }
};
template <
typename image_type
>
const matrix_op<op_const_image_view_to_mat<image_type> > mat (
const const_image_view<image_type>& img
)
{
typedef op_const_image_view_to_mat<image_type> op;
return matrix_op<op>(op(img));
}
// ----------------------------------------------------------------------------------------
......@@ -418,6 +492,42 @@ namespace dlib
return array;
}
// ----------------------------------------------------------------------------------------
template <typename T>
struct op_array2d_to_mat : does_not_alias
{
op_array2d_to_mat( const T& array_) : array(array_){}
const T& array;
const static long cost = 1;
const static long NR = 0;
const static long NC = 0;
typedef typename T::type type;
typedef const typename T::type& const_ret_type;
typedef typename T::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const { return array[r][c]; }
long nr () const { return array.nr(); }
long nc () const { return array.nc(); }
};
// Note that we have this version of mat() because it's slightly faster executing
// than the general one that handles any generic image. This is because it avoids
// calling image_data() which for array2d involves a single if statement but this
// version here has no if statement in its construction.
template < typename T, typename MM >
const matrix_op<op_array2d_to_mat<array2d<T,MM> > > mat (
const array2d<T,MM>& array
)
{
typedef op_array2d_to_mat<array2d<T,MM> > op;
return matrix_op<op>(op(array));
}
template <
typename array_type
>
......
......@@ -28,14 +28,20 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <
typename T,
typename MM
typename image_type
>
const matrix_exp mat (
const array2d<T,MM>& array
const image_type& img
);
/*!
requires
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or image_type is a image_view or
const_image_view object.
ensures
- This function converts any kind of generic image object into a dlib::matrix
expression. Therefore, it is capable of converting objects like dlib::array2d
of dlib::cv_image.
- returns a matrix R such that:
- R.nr() == array.nr()
- R.nc() == array.nc()
......
......@@ -7,6 +7,7 @@
#include "../algs.h"
#include "../pixel.h"
#include "../matrix/matrix_mat.h"
#include "../image_processing/generic_image.h"
namespace dlib
{
......@@ -139,6 +140,51 @@ namespace dlib
// ----------------------------------------------------------------------------------------
// Define the global functions that make cv_image a proper "generic image" according to
// ../image_processing/generic_image.h
template <typename T>
struct image_traits<cv_image<T> >
{
typedef T pixel_type;
};
template <typename T>
inline long num_rows( const cv_image<T>& img) { return img.nr(); }
template <typename T>
inline long num_columns( const cv_image<T>& img) { return img.nc(); }
template <typename T>
inline void* image_data(
cv_image<T>& img
)
{
if (img.size() != 0)
return &img[0][0];
else
return 0;
}
template <typename T>
inline const void* image_data(
const cv_image<T>& img
)
{
if (img.size() != 0)
return &img[0][0];
else
return 0;
}
template <typename T>
inline long width_step(
const cv_image<T>& img
)
{
return img.width_step();
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_CvIMAGE_H_
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment