diff --git a/dlib/array2d.h b/dlib/array2d.h index 06e106aa1..f5325e4a2 100644 --- a/dlib/array2d.h +++ b/dlib/array2d.h @@ -6,6 +6,7 @@ #include "array2d/array2d_kernel.h" #include "array2d/serialize_pixel_overloads.h" +#include "array2d/array2d_generic_image.h" #endif // DLIB_ARRAY2d_ diff --git a/dlib/array2d/array2d_generic_image.h b/dlib/array2d/array2d_generic_image.h new file mode 100644 index 000000000..fa724110a --- /dev/null +++ b/dlib/array2d/array2d_generic_image.h @@ -0,0 +1,62 @@ +// 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 + struct image_traits > + { + typedef T pixel_type; + }; + + template + inline long num_rows( const array2d& img) { return img.nr(); } + template + inline long num_columns( const array2d& img) { return img.nc(); } + + template + inline void set_image_size( + array2d& img, + long rows, + long cols + ) { img.set_size(rows,cols); } + + template + inline void* image_data( + array2d& img + ) + { + if (img.size() != 0) + return &img[0][0]; + else + return 0; + } + + template + inline const void* image_data( + const array2d& img + ) + { + if (img.size() != 0) + return &img[0][0]; + else + return 0; + } + + template + inline long width_step( + const array2d& img + ) + { + return img.width_step(); + } + +} + +#endif // DLIB_ARRAY2D_GENERIC_iMAGE_H__ + diff --git a/dlib/geometry/rectangle.h b/dlib/geometry/rectangle.h index 4938e7bc2..6d8e97936 100644 --- a/dlib/geometry/rectangle.h +++ b/dlib/geometry/rectangle.h @@ -9,6 +9,7 @@ #include #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); } // ---------------------------------------------------------------------------------------- diff --git a/dlib/geometry/rectangle_abstract.h b/dlib/geometry/rectangle_abstract.h index 5499762b8..118ccd42e 100644 --- a/dlib/geometry/rectangle_abstract.h +++ b/dlib/geometry/rectangle_abstract.h @@ -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.) diff --git a/dlib/gui_widgets/widgets.h b/dlib/gui_widgets/widgets.h index e376631af..bd29278a5 100644 --- a/dlib/gui_widgets/widgets.h +++ b/dlib/gui_widgets/widgets.h @@ -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 { diff --git a/dlib/image_keypoint/fine_hog_image.h b/dlib/image_keypoint/fine_hog_image.h index ee814d1f9..a95d29fe0 100644 --- a/dlib/image_keypoint/fine_hog_image.h +++ b/dlib/image_keypoint/fine_hog_image.h @@ -66,7 +66,7 @@ namespace dlib const image_type& img ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); load_impl(mat(img)); } diff --git a/dlib/image_keypoint/fine_hog_image_abstract.h b/dlib/image_keypoint/fine_hog_image_abstract.h index 24da59c72..2615f519e 100644 --- a/dlib/image_keypoint/fine_hog_image_abstract.h +++ b/dlib/image_keypoint/fine_hog_image_abstract.h @@ -103,7 +103,7 @@ namespace dlib requires - image_type is a dlib::matrix or something convertible to a matrix via mat() - - pixel_traits::has_alpha == false + - pixel_traits::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 diff --git a/dlib/image_keypoint/hashed_feature_image.h b/dlib/image_keypoint/hashed_feature_image.h index a4e4cdbe3..a5b1de685 100644 --- a/dlib/image_keypoint/hashed_feature_image.h +++ b/dlib/image_keypoint/hashed_feature_image.h @@ -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]; diff --git a/dlib/image_keypoint/hog.h b/dlib/image_keypoint/hog.h index 52cdbc8e4..5b7c233f1 100644 --- a/dlib/image_keypoint/hog.h +++ b/dlib/image_keypoint/hog.h @@ -82,7 +82,7 @@ namespace dlib const image_type& img ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); load_impl(mat(img)); } diff --git a/dlib/image_keypoint/hog_abstract.h b/dlib/image_keypoint/hog_abstract.h index 1cb275ff4..d7a6c111a 100644 --- a/dlib/image_keypoint/hog_abstract.h +++ b/dlib/image_keypoint/hog_abstract.h @@ -158,8 +158,8 @@ namespace dlib /*! requires - image_type is a dlib::matrix or something convertible to a matrix - via mat() - - pixel_traits::has_alpha == false + via mat(). + - pixel_traits::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 diff --git a/dlib/image_keypoint/poly_image.h b/dlib/image_keypoint/poly_image.h index 20c62afcc..53662d003 100644 --- a/dlib/image_keypoint/poly_image.h +++ b/dlib/image_keypoint/poly_image.h @@ -138,7 +138,7 @@ namespace dlib const image_type& img ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); poly_coef.resize(get_num_dimensions()); des.set_size(get_num_dimensions()); diff --git a/dlib/image_keypoint/poly_image_abstract.h b/dlib/image_keypoint/poly_image_abstract.h index b982ae474..2b304bc8d 100644 --- a/dlib/image_keypoint/poly_image_abstract.h +++ b/dlib/image_keypoint/poly_image_abstract.h @@ -166,8 +166,9 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits::has_alpha == false + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - pixel_traits::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) diff --git a/dlib/image_keypoint/surf.h b/dlib/image_keypoint/surf.h index f4fccd997..d12b30840 100644 --- a/dlib/image_keypoint/surf.h +++ b/dlib/image_keypoint/surf.h @@ -248,7 +248,7 @@ namespace dlib ); // Figure out the proper scalar type we should use to work with these pixels. - typedef typename pixel_traits::basic_pixel_type bp_type; + typedef typename pixel_traits::pixel_type>::basic_pixel_type bp_type; typedef typename promote::type working_pixel_type; // make an integral image first diff --git a/dlib/image_keypoint/surf_abstract.h b/dlib/image_keypoint/surf_abstract.h index a46f0c77a..12f66475c 100644 --- a/dlib/image_keypoint/surf_abstract.h +++ b/dlib/image_keypoint/surf_abstract.h @@ -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 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

::has_alpha == false ensures - This function runs the complete SURF algorithm on the given input image and returns the points it found. diff --git a/dlib/image_loader/image_loader.h b/dlib/image_loader/image_loader.h index 323fe045b..4fa29dab2 100644 --- a/dlib/image_loader/image_loader.h +++ b/dlib/image_loader/image_loader.h @@ -31,10 +31,11 @@ namespace dlib typename image_type > void load_bmp ( - image_type& image, + image_type& image_, std::istream& in_ ) { + image_view 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(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::value) + if (!is_same_type::pixel_type,long double>::value) { double temp = cur; assign_pixel(image[r][c],temp); diff --git a/dlib/image_loader/image_loader_abstract.h b/dlib/image_loader/image_loader_abstract.h index 8bb911700..5072706c2 100644 --- a/dlib/image_loader/image_loader_abstract.h +++ b/dlib/image_loader/image_loader_abstract.h @@ -29,8 +29,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits 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 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 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 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: diff --git a/dlib/image_loader/jpeg_loader.h b/dlib/image_loader/jpeg_loader.h index 91e241706..966cdc6e7 100644 --- a/dlib/image_loader/jpeg_loader.h +++ b/dlib/image_loader/jpeg_loader.h @@ -25,7 +25,7 @@ namespace dlib bool is_rgb() const; template - 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.set_size( height_, width_ ); for ( unsigned n = 0; n < height_;n++ ) diff --git a/dlib/image_loader/jpeg_loader_abstract.h b/dlib/image_loader/jpeg_loader_abstract.h index 0e570041c..cc09220e8 100644 --- a/dlib/image_loader/jpeg_loader_abstract.h +++ b/dlib/image_loader/jpeg_loader_abstract.h @@ -99,8 +99,8 @@ namespace dlib ) const; /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits 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 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); !*/ diff --git a/dlib/image_loader/load_image_abstract.h b/dlib/image_loader/load_image_abstract.h index 689507e7e..6e11389c4 100644 --- a/dlib/image_loader/load_image_abstract.h +++ b/dlib/image_loader/load_image_abstract.h @@ -15,8 +15,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits 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 '.') diff --git a/dlib/image_loader/png_loader.h b/dlib/image_loader/png_loader.h index 555a8a837..9067c33b9 100644 --- a/dlib/image_loader/png_loader.h +++ b/dlib/image_loader/png_loader.h @@ -30,7 +30,7 @@ namespace dlib unsigned int bit_depth () const { return bit_depth_; } template - 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::pixel_type pixel_type; + image_view t(t_); t.set_size( height_, width_ ); @@ -148,7 +149,7 @@ namespace dlib } else if (is_rgba() && bit_depth_ == 8) { - if (!pixel_traits::has_alpha) + if (!pixel_traits::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::has_alpha) + if (!pixel_traits::has_alpha) assign_all_pixels(t,0); for ( unsigned n = 0; n < height_;n++ ) diff --git a/dlib/image_loader/png_loader_abstract.h b/dlib/image_loader/png_loader_abstract.h index 6067b16b9..94ef2e067 100644 --- a/dlib/image_loader/png_loader_abstract.h +++ b/dlib/image_loader/png_loader_abstract.h @@ -127,8 +127,8 @@ namespace dlib ) const; /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits 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 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); !*/ diff --git a/dlib/image_processing/generic_image.h b/dlib/image_processing/generic_image.h new file mode 100644 index 000000000..83a9c6d35 --- /dev/null +++ b/dlib/image_processing/generic_image.h @@ -0,0 +1,348 @@ +// Copyright (C) 2014 Davis E. King (davis@dlib.net) +// License: Boost Software License See LICENSE.txt for the full license. +#ifndef DLIB_GeNERIC_IMAGE_H__ +#define DLIB_GeNERIC_IMAGE_H__ + +namespace dlib +{ + + /*! + In dlib, an "image" is any object that implements the generic image interface. In + particular, this simply means that an image type (let's refer to it as image_type + from here on) implements the following seven global functions: + - long num_rows (const image_type& img) + - long num_columns (const image_type& img) + - void set_image_size( image_type& img, long rows, long cols) + - void* image_data ( image_type& img) + - const void* image_data (const image_type& img) + - long width_step (const image_type& img) + - void swap ( image_type& a, image_type& b) + And also provides a specialization of the image_traits template that looks like: + namespace dlib + { + template <> + struct image_traits + { + typedef the_type_of_pixel_used_in_image_type pixel_type; + }; + } + + Additionally, an image object must be default constructable. This means that + expressions of the form: + image_type img; + Must be legal. + + Finally, the type of pixel in image_type must have a pixel_traits specialization. + That is, pixel_traits::pixel_type> must be one of + the specializations of pixel_traits. + + + To be very precise, the seven functions defined above are defined thusly: + + long num_rows( + const image_type& img + ); + /!* + ensures + - returns the number of rows in the given image + *!/ + + long num_columns( + const image_type& img + ); + /!* + ensures + - returns the number of columns in the given image + *!/ + + void set_image_size( + image_type& img, + long rows, + long cols + ); + /!* + requires + - rows >= 0 && cols >= 0 + ensures + - num_rows(#img) == rows + - num_columns(#img) == cols + *!/ + + void* image_data( + image_type& img + ); + /!* + ensures + - returns a non-const pointer to the pixel at row and column position 0,0 + in the given image. Or if the image has zero rows or columns in it + then this function returns NULL. + - The image lays pixels down in row major order. However, there might + be padding at the end of each row. The amount of padding is given by + width_step(img). + *!/ + + const void* image_data( + const image_type& img + ); + /!* + ensures + - returns a const pointer to the pixel at row and column position 0,0 in + the given image. Or if the image has zero rows or columns in it then + this function returns NULL. + - The image lays pixels down in row major order. However, there might + be padding at the end of each row. The amount of padding is given by + width_step(img). + *!/ + + long width_step( + const image_type& img + ); + /!* + ensures + - returns the size of one row of the image, in bytes. More precisely, + return a number N such that: (char*)image_data(img) + N*R == a + pointer to the first pixel in the R-th row of the image. This means + that the image must lay its pixels down in row major order. + *!/ + + void swap( + image_type& a, + image_type& b + ); + /!* + ensures + - swaps the state of a and b + *!/ + !*/ + +// ---------------------------------------------------------------------------------------- + + template + struct image_traits; + /*! + WHAT THIS OBJECT REPRESENTS + This is a traits class for generic image objects. You can use it to find out + the pixel type contained within an image via an expression of the form: + image_traits::pixel_type + !*/ + +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- +// UTILITIES TO MAKE ACCESSING IMAGE PIXELS SIMPLER +// ---------------------------------------------------------------------------------------- +// ---------------------------------------------------------------------------------------- + + template < + typename image_type + > + class image_view + { + /*! + REQUIREMENTS ON image_type + image_type must be an image object as defined at the top of this file. + + WHAT THIS OBJECT REPRESENTS + This object takes an image object and wraps it with an interface that makes + it look like a dlib::array2d. That is, it makes it look similar to a + regular 2-dimensional C style array, making code which operates on the + pixels simple to read. + + Note that an image_view instance is valid until the image given to its + constructor is modified through an interface other than the image_view + instance. This is because, for example, someone might cause the underlying + image object to reallocate its memory, thus invalidating the pointer to its + pixel data stored in the image_view. + + As an side, there reason why this object stores a pointer to the image + object's data and uses that pointer instead of calling image_data() each + time a pixel is accessed is to allow for image objects to implement + complex, and possibly slow, image_data() functions. For example, an image + object might perform some kind of synchronization between a GPU and the + host memory during a call to image_data(). Therefore, we call image_data() + only in image_view's constructor to avoid the performance penalty of + calling it for each pixel access. + !*/ + + public: + typedef typename image_traits::pixel_type pixel_type; + + image_view( + image_type& img + ) : + _data((char*)image_data(img)), + _width_step(width_step(img)), + _nr(num_rows(img)), + _nc(num_columns(img)), + _img(&img) + {} + + long nr() const { return _nr; } + /*! + ensures + - returns the number of rows in this image. + !*/ + + long nc() const { return _nc; } + /*! + ensures + - returns the number of columns in this image. + !*/ + + unsigned long size() const { return static_cast(nr()*nc()); } + /*! + ensures + - returns the number of pixels in this image. + !*/ + + pixel_type* operator[] (long row) { return (pixel_type*)(_data+_width_step*row); } + /*! + requires + - 0 <= row < nr() + ensures + - returns a pointer to the first pixel in the row-th row. Therefore, the + pixel at row and column position r,c can be accessed via (*this)[r][c]. + !*/ + + const pixel_type* operator[] (long row) const { return (const pixel_type*)(_data+_width_step*row); } + /*! + requires + - 0 <= row < nr() + ensures + - returns a const pointer to the first pixel in the row-th row. Therefore, + the pixel at row and column position r,c can be accessed via + (*this)[r][c]. + !*/ + + void set_size(long rows, long cols) { set_image_size(*_img, rows, cols); *this = *_img; } + /*! + requires + - rows >= 0 && cols >= 0 + ensures + - Tells the underlying image to resize itself to have the given number of + rows and columns. + - #nr() == rows + - #nc() == cols + !*/ + + void clear() { set_size(0,0); } + /*! + ensures + - sets the image to have 0 pixels in it. + !*/ + + private: + + char* _data; + long _width_step; + long _nr; + long _nc; + image_type* _img; + }; + +// ---------------------------------------------------------------------------------------- + + template + class const_image_view + { + /*! + REQUIREMENTS ON image_type + image_type must be an image object as defined at the top of this file. + + WHAT THIS OBJECT REPRESENTS + This object is just like the image_view except that it provides a "const" + view into an image. That is, it has the same interface as image_view + except that you can't modify the image through a const_image_view. + !*/ + + public: + typedef typename image_traits::pixel_type pixel_type; + + const_image_view( + const image_type& img + ) : + _data((char*)image_data(img)), + _width_step(width_step(img)), + _nr(num_rows(img)), + _nc(num_columns(img)) + {} + + long nr() const { return _nr; } + long nc() const { return _nc; } + unsigned long size() const { return static_cast(nr()*nc()); } + const pixel_type* operator[] (long row) const { return (const pixel_type*)(_data+_width_step*row); } + + private: + const char* _data; + long _width_step; + long _nr; + long _nc; + }; + +// ---------------------------------------------------------------------------------------- + + template + image_view make_image_view ( image_type& img) + { return image_view(img); } + /*! + requires + - image_type == an image object that implements the interface defined at the + top of this file. + ensures + - constructs an image_view from an image object + !*/ + + template + const_image_view make_image_view (const image_type& img) + { return const_image_view(img); } + /*! + requires + - image_type == an image object that implements the interface defined at the + top of this file. + ensures + - constructs a const_image_view from an image object + !*/ + +// ---------------------------------------------------------------------------------------- + + template + inline unsigned long image_size( + const image_type& img + ) { return num_columns(img)*num_rows(img); } + /*! + requires + - image_type == an image object that implements the interface defined at the + top of this file. + ensures + - returns the number of pixels in the given image. + !*/ + +// ---------------------------------------------------------------------------------------- + + template + inline long num_rows( + const image_type& img + ) { return img.nr(); } + /*! + ensures + - By default, try to use the member function .nr() to determine the number + of rows in an image. However, as stated at the top of this file, image + objects should provide their own overload of num_rows() if needed. + !*/ + + template + inline long num_columns( + const image_type& img + ) { return img.nc(); } + /*! + ensures + - By default, try to use the member function .nc() to determine the number + of columns in an image. However, as stated at the top of this file, image + objects should provide their own overload of num_rows() if needed. + !*/ + +// ---------------------------------------------------------------------------------------- + +} + +#endif // DLIB_GeNERIC_IMAGE_H__ + diff --git a/dlib/image_processing/scan_fhog_pyramid.h b/dlib/image_processing/scan_fhog_pyramid.h index c422ba8cc..4b50139a2 100644 --- a/dlib/image_processing/scan_fhog_pyramid.h +++ b/dlib/image_processing/scan_fhog_pyramid.h @@ -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 temp1, temp2; + image_type temp1, temp2; pyr(img, temp1); fe(temp1, feats[1], cell_size,filter_rows_padding,filter_cols_padding); swap(temp1,temp2); diff --git a/dlib/image_processing/scan_image.h b/dlib/image_processing/scan_image.h index 7dd42e80d..9d0b9ef3a 100644 --- a/dlib/image_processing/scan_image.h +++ b/dlib/image_processing/scan_image.h @@ -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::pixel_type pixel_type; typedef typename promote::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::pixel_type pixel_type; typedef typename promote::type ptype; ptype temp = 0; @@ -190,12 +190,13 @@ namespace dlib > void find_points_above_thresh ( std::vector >& 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 img(img_); + typedef typename image_traits::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::pixel_type pixel_type; typedef typename promote::type ptype; array2d 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::pixel_type pixel_type; typedef typename promote::type ptype; array2d accum(images[0].nr(), images[0].nc()); diff --git a/dlib/image_processing/scan_image_abstract.h b/dlib/image_processing/scan_image_abstract.h index 08f2c8cb5..086f20513 100644 --- a/dlib/image_processing/scan_image_abstract.h +++ b/dlib/image_processing/scan_image_abstract.h @@ -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) diff --git a/dlib/image_processing/scan_image_pyramid.h b/dlib/image_processing/scan_image_pyramid.h index 391ec56c5..042457f0c 100644 --- a/dlib/image_processing/scan_image_pyramid.h +++ b/dlib/image_processing/scan_image_pyramid.h @@ -10,6 +10,7 @@ #include "../array2d.h" #include #include "full_object_detection.h" +#include "../image_processing/generic_image.h" namespace dlib { diff --git a/dlib/image_processing/scan_image_pyramid_abstract.h b/dlib/image_processing/scan_image_pyramid_abstract.h index a938956a3..44e5aca25 100644 --- a/dlib/image_processing/scan_image_pyramid_abstract.h +++ b/dlib/image_processing/scan_image_pyramid_abstract.h @@ -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, diff --git a/dlib/image_saver/image_saver.h b/dlib/image_saver/image_saver.h index 7bee85bde..43a2717af 100644 --- a/dlib/image_saver/image_saver.h +++ b/dlib/image_saver/image_saver.h @@ -33,7 +33,7 @@ namespace dlib template < typename image_type, - bool grayscale = pixel_traits::grayscale + bool grayscale = pixel_traits::pixel_type>::grayscale > struct save_bmp_helper; @@ -42,10 +42,11 @@ namespace dlib struct save_bmp_helper { static void save_bmp ( - const image_type& image, + const image_type& image_, std::ostream& out ) { + const_image_view 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 { static void save_bmp ( - const image_type& image, + const image_type& image_, std::ostream& out ) { + const_image_view 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::grayscale && sizeof(typename image_type::type) == 1, - pixel_traits::rgb, - pixel_traits::hsi, - false, - pixel_traits::rgb_alpha, - false, - pixel_traits::grayscale && sizeof(typename image_type::type) != 1 && - !is_float_type::value, - is_float_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 - struct save_dng_helper + struct save_dng_helper::pixel_type> >::type > { static void save_dng ( - const image_type& image, + const image_type& image_, std::ostream& out ) { + const_image_view image(image_); out.write("DNG",3); unsigned long version = 1; serialize(version,out); @@ -334,14 +326,24 @@ namespace dlib }; + template + struct is_non_float_non8bit_grayscale + { + typedef typename image_traits::pixel_type pixel_type; + const static bool value = pixel_traits::grayscale && + sizeof(pixel_type) != 1 && + !is_float_type::value; + }; + template - struct save_dng_helper + struct save_dng_helper >::type> { static void save_dng ( - const image_type& image, + const image_type& image_, std::ostream& out ) { + const_image_view image(image_); out.write("DNG",3); unsigned long version = 1; serialize(version,out); @@ -375,15 +377,22 @@ namespace dlib } }; + template + struct is_8bit_grayscale + { + typedef typename image_traits::pixel_type pixel_type; + const static bool value = pixel_traits::grayscale && sizeof(pixel_type) == 1; + }; template - struct save_dng_helper + struct save_dng_helper >::type> { static void save_dng ( - const image_type& image, + const image_type& image_, std::ostream& out ) { + const_image_view image(image_); out.write("DNG",3); unsigned long version = 1; serialize(version,out); @@ -415,13 +424,21 @@ namespace dlib }; template - struct save_dng_helper + struct is_rgb_image + { + typedef typename image_traits::pixel_type pixel_type; + const static bool value = pixel_traits::rgb; + }; + + template + struct save_dng_helper >::type> { static void save_dng ( - const image_type& image, + const image_type& image_, std::ostream& out ) { + const_image_view image(image_); out.write("DNG",3); unsigned long version = 1; serialize(version,out); @@ -480,13 +497,21 @@ namespace dlib }; template - struct save_dng_helper + struct is_rgb_alpha_image + { + typedef typename image_traits::pixel_type pixel_type; + const static bool value = pixel_traits::rgb_alpha; + }; + + template + struct save_dng_helper >::type> { static void save_dng ( - const image_type& image, + const image_type& image_, std::ostream& out ) { + const_image_view image(image_); out.write("DNG",3); unsigned long version = 1; serialize(version,out); @@ -547,13 +572,21 @@ namespace dlib }; template - struct save_dng_helper + struct is_hsi_image + { + typedef typename image_traits::pixel_type pixel_type; + const static bool value = pixel_traits::hsi; + }; + + template + struct save_dng_helper >::type> { static void save_dng ( - const image_type& image, + const image_type& image_, std::ostream& out ) { + const_image_view image(image_); out.write("DNG",3); unsigned long version = 1; serialize(version,out); diff --git a/dlib/image_saver/image_saver_abstract.h b/dlib/image_saver/image_saver_abstract.h index 327d1c915..ae05fedbc 100644 --- a/dlib/image_saver/image_saver_abstract.h +++ b/dlib/image_saver/image_saver_abstract.h @@ -29,9 +29,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h or - a dlib::matrix - - pixel_traits 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 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 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 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: diff --git a/dlib/image_saver/save_png.h b/dlib/image_saver/save_png.h index fcebf1c15..02133242f 100644 --- a/dlib/image_saver/save_png.h +++ b/dlib/image_saver/save_png.h @@ -41,10 +41,12 @@ namespace dlib typename image_type > typename disable_if >::type save_png( - const image_type& img, + const image_type& img_, const std::string& file_name ) { + const_image_view 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 row_pointers(img.nr()); - typedef typename image_type::type pixel_type; + typedef typename image_traits::pixel_type pixel_type; if (is_same_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 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 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 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]); diff --git a/dlib/image_saver/save_png_abstract.h b/dlib/image_saver/save_png_abstract.h index 5efee234b..18823fae9 100644 --- a/dlib/image_saver/save_png_abstract.h +++ b/dlib/image_saver/save_png_abstract.h @@ -19,9 +19,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h or - a dlib::matrix - - pixel_traits 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) diff --git a/dlib/image_transforms/assign_image.h b/dlib/image_transforms/assign_image.h index 159750b1f..30f0751d5 100644 --- a/dlib/image_transforms/assign_image.h +++ b/dlib/image_transforms/assign_image.h @@ -14,52 +14,34 @@ namespace dlib template < typename dest_image_type, - typename src_pixel_type + typename src_image_type > - typename enable_if >::type impl_assign_single_pixel ( - dest_image_type& img, - long r, - long c, - const src_pixel_type& pix + void impl_assign_image ( + image_view& dest, + const src_image_type& src ) { - assign_pixel(img(r,c), pix); + dest.set_size(src.nr(),src.nc()); + for (long r = 0; r < src.nr(); ++r) + { + for (long c = 0; c < src.nc(); ++c) + { + assign_pixel(dest[r][c], src(r,c)); + } + } } - template < - typename dest_image_type, - typename src_pixel_type - > - typename disable_if >::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_image_type > void impl_assign_image ( - dest_image_type& dest, + 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)); - } - } + image_view dest(dest_); + impl_assign_image(dest, src); } template < @@ -85,9 +67,9 @@ namespace dlib typename src_image_type > void impl_assign_image_scaled ( - dest_image_type& dest, + image_view& 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::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::max() >= pixel_traits::max() && - pixel_traits::min() <= pixel_traits::min() ) + if (pixel_traits::max() >= pixel_traits::max() && + pixel_traits::min() <= pixel_traits::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::max() >= rs.max() && - pixel_traits::min() <= rs.min() ) + if (pixel_traits::max() >= rs.max() && + pixel_traits::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::min(); - const double dest_max = pixel_traits::max(); + const double dest_min = pixel_traits::min(); + const double dest_max = pixel_traits::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(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_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_img(dest_img_); + assign_all_pixels(dest_img, src_pixel); + } + // ---------------------------------------------------------------------------------------- template < typename image_type > void assign_border_pixels ( - image_type& img, + image_view& img, long x_border_size, long y_border_size, - const typename image_type::type& p + const typename image_traits::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::pixel_type& p + ) + { + image_view 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::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& 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::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& 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 img(img_); + zero_border_pixels(img, inside); + } + // ---------------------------------------------------------------------------------------- } diff --git a/dlib/image_transforms/assign_image_abstract.h b/dlib/image_transforms/assign_image_abstract.h index f14411fbf..cc9aba3f1 100644 --- a/dlib/image_transforms/assign_image_abstract.h +++ b/dlib/image_transforms/assign_image_abstract.h @@ -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 is defined - - pixel_traits 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 is defined - - pixel_traits 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::max() - let DEST_LOWER = pixel_traits::min() + let DEST_UPPER = pixel_traits::pixel_type>::max() + let DEST_LOWER = pixel_traits::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 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 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::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 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 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() diff --git a/dlib/image_transforms/colormaps.h b/dlib/image_transforms/colormaps.h index d9ffab8d5..4eb2fa05c 100644 --- a/dlib/image_transforms/colormaps.h +++ b/dlib/image_transforms/colormaps.h @@ -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 < diff --git a/dlib/image_transforms/colormaps_abstract.h b/dlib/image_transforms/colormaps_abstract.h index 72992a06e..f256de810 100644 --- a/dlib/image_transforms/colormaps_abstract.h +++ b/dlib/image_transforms/colormaps_abstract.h @@ -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 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 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 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 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 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))) !*/ diff --git a/dlib/image_transforms/draw.h b/dlib/image_transforms/draw.h index f70ecf88d..53b28f9ee 100644 --- a/dlib/image_transforms/draw.h +++ b/dlib/image_transforms/draw.h @@ -23,10 +23,11 @@ namespace dlib long y1, long x2, long y2, - image_type& c, + image_type& c_, const pixel_type& val ) { + image_view 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 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 tile_images ( + matrix::pixel_type> tile_images ( const image_array_type& images ) { - typedef typename image_array_type::value_type::type T; + typedef typename image_traits::pixel_type T; if (images.size() == 0) return matrix(); @@ -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 temp(size_nr*nr, size_nc*nc); diff --git a/dlib/image_transforms/draw_abstract.h b/dlib/image_transforms/draw_abstract.h index 2dc7fe4f9..49d46a2b5 100644 --- a/dlib/image_transforms/draw_abstract.h +++ b/dlib/image_transforms/draw_abstract.h @@ -22,8 +22,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits 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 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 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 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 tile_images ( + matrix::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 diff --git a/dlib/image_transforms/edge_detector.h b/dlib/image_transforms/edge_detector.h index 6766ec73d..2fa898fed 100644 --- a/dlib/image_transforms/edge_detector.h +++ b/dlib/image_transforms/edge_detector.h @@ -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::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::pixel_type pixel_type; + COMPILE_TIME_ASSERT(pixel_traits::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_img(in_img_); + image_view horz(horz_); + image_view 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::basic_pixel_type bp_type; + typedef typename pixel_traits::pixel_type>::basic_pixel_type bp_type; typename promote::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::value); + const_image_view horz(horz_); + const_image_view vert(vert_); + image_view out_img(out_img_); + + COMPILE_TIME_ASSERT(is_signed_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::type T; + typedef typename promote::pixel_type>::type T; const T y = horz[r][c]; const T x = vert[r][c]; diff --git a/dlib/image_transforms/edge_detector_abstract.h b/dlib/image_transforms/edge_detector_abstract.h index e4e276b3e..a341197e3 100644 --- a/dlib/image_transforms/edge_detector_abstract.h +++ b/dlib/image_transforms/edge_detector_abstract.h @@ -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 must be defined - - pixel_traits::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 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::pixel_type == A signed scalar type (e.g. int, double, etc.) ensures - #out_img.nr() = horz.nr() - #out_img.nc() = horz.nc() diff --git a/dlib/image_transforms/equalize_histogram.h b/dlib/image_transforms/equalize_histogram.h index ec826d951..dd048759a 100644 --- a/dlib/image_transforms/equalize_histogram.h +++ b/dlib/image_transforms/equalize_histogram.h @@ -21,24 +21,26 @@ namespace dlib typename MM > void get_histogram ( - const in_image_type& in_img, + const in_image_type& in_img_, matrix& hist ) { - COMPILE_TIME_ASSERT( pixel_traits::is_unsigned == true ); + typedef typename image_traits::pixel_type pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::is_unsigned == true ); - typedef typename pixel_traits::basic_pixel_type in_image_basic_pixel_type; + typedef typename pixel_traits::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::max()+1); + hist.set_size(1,pixel_traits::max()+1); else - hist.set_size(pixel_traits::max()+1,1); + hist.set_size(pixel_traits::max()+1,1); set_all_elements(hist,0); + const_image_view 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::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); - COMPILE_TIME_ASSERT( pixel_traits::is_unsigned == true ); - COMPILE_TIME_ASSERT( pixel_traits::is_unsigned == true ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; - typedef typename pixel_traits::basic_pixel_type in_image_basic_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + COMPILE_TIME_ASSERT( pixel_traits::is_unsigned == true ); + COMPILE_TIME_ASSERT( pixel_traits::is_unsigned == true ); + + typedef typename pixel_traits::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 histogram; - get_histogram(in_img, histogram); + matrix histogram; + get_histogram(in_img_, histogram); + in_img = in_img_; double scale = pixel_traits::max(); if (in_img.size() > histogram(0)) diff --git a/dlib/image_transforms/equalize_histogram_abstract.h b/dlib/image_transforms/equalize_histogram_abstract.h index e91711668..a25076b19 100644 --- a/dlib/image_transforms/equalize_histogram_abstract.h +++ b/dlib/image_transforms/equalize_histogram_abstract.h @@ -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::has_alpha == false - - pixel_traits::has_alpha == false - - pixel_traits::is_unsigned == true - - pixel_traits::is_unsigned == true - - pixel_traits::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::has_alpha == false + - pixel_traits::is_unsigned == true + - For the input image pixel type, we have the additional requirement that: + - pixel_traits::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::is_unsigned == true - - pixel_traits::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::is_unsigned == true + - pixel_traits::max() <= 65535 - hist must be capable of representing a column vector of length pixel_traits::max(). I.e. if R and C are nonzero then they must be values that don't conflict with the previous sentence. diff --git a/dlib/image_transforms/fhog.h b/dlib/image_transforms/fhog.h index 242d0aec3..c26d47647 100644 --- a/dlib/image_transforms/fhog.h +++ b/dlib/image_transforms/fhog.h @@ -22,7 +22,7 @@ namespace dlib namespace impl_fhog { template - inline typename dlib::enable_if_c::rgb>::type get_gradient ( + inline typename dlib::enable_if_c::rgb>::type get_gradient ( const int r, const int c, const image_type& img, @@ -60,7 +60,7 @@ namespace dlib } template - inline typename dlib::enable_if_c::rgb>::type get_gradient ( + inline typename dlib::enable_if_c::rgb>::type get_gradient ( const int r, const int c, const image_type& img, @@ -145,7 +145,7 @@ namespace dlib // ------------------------------------------------------------------------------------ template - inline typename dlib::disable_if_c::rgb>::type get_gradient ( + inline typename dlib::disable_if_c::rgb>::type get_gradient ( const int r, const int c, const image_type& img, @@ -159,7 +159,7 @@ namespace dlib } template - inline typename dlib::disable_if_c::rgb>::type get_gradient ( + inline typename dlib::disable_if_c::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 img(img_); // make sure requires clause is not broken DLIB_ASSERT( cell_size > 0 && filter_rows_padding > 0 && diff --git a/dlib/image_transforms/fhog_abstract.h b/dlib/image_transforms/fhog_abstract.h index ac1d23dd5..b3c70c84e 100644 --- a/dlib/image_transforms/fhog_abstract.h +++ b/dlib/image_transforms/fhog_abstract.h @@ -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 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 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 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 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() diff --git a/dlib/image_transforms/image_pyramid.h b/dlib/image_transforms/image_pyramid.h index 7ffcc409c..e7becb585 100644 --- a/dlib/image_transforms/image_pyramid.h +++ b/dlib/image_transforms/image_pyramid.h @@ -119,8 +119,10 @@ namespace dlib << "\n\t this: " << this ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); down.clear(); } @@ -220,8 +222,9 @@ namespace dlib template struct both_images_rgb { - const static bool value = pixel_traits::rgb && - pixel_traits::rgb; + typedef typename image_traits::pixel_type T_pix; + typedef typename image_traits::pixel_type U_pix; + const static bool value = pixel_traits::rgb && pixel_traits::rgb; }; public: @@ -230,19 +233,24 @@ namespace dlib typename out_image_type > typename disable_if >::type operator() ( - const in_image_type& original, - out_image_type& down + const in_image_type& original_, + out_image_type& down_ ) const { // make sure requires clause is not broken - DLIB_ASSERT( is_same_object(original, down) == false, + DLIB_ASSERT( is_same_object(original_, down_) == false, "\t void pyramid_down_2_1::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) + << "\n\t is_same_object(original_, down_): " << is_same_object(original_, down_) << "\n\t this: " << this ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + const_image_view original(original_); + image_view down(down_); if (original.nr() <= 8 || original.nc() <= 8) { @@ -250,7 +258,7 @@ namespace dlib return; } - typedef typename pixel_traits::basic_pixel_type bp_type; + typedef typename pixel_traits::basic_pixel_type bp_type; typedef typename promote::type ptype; array2d temp_img; temp_img.set_size(original.nr(), (original.nc()-3)/2); @@ -326,19 +334,24 @@ namespace dlib typename out_image_type > typename enable_if >::type operator() ( - const in_image_type& original, - out_image_type& down + const in_image_type& original_, + out_image_type& down_ ) const { // make sure requires clause is not broken - DLIB_ASSERT( is_same_object(original, down) == false, + DLIB_ASSERT( is_same_object(original_, down_) == false, "\t void pyramid_down_2_1::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) + << "\n\t is_same_object(original_, down_): " << is_same_object(original_, down_) << "\n\t this: " << this ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + const_image_view original(original_); + image_view down(down_); if (original.nr() <= 8 || original.nc() <= 8) { @@ -539,8 +552,9 @@ namespace dlib template struct both_images_rgb { - const static bool value = pixel_traits::rgb && - pixel_traits::rgb; + typedef typename image_traits::pixel_type T_pix; + typedef typename image_traits::pixel_type U_pix; + const static bool value = pixel_traits::rgb && pixel_traits::rgb; }; public: @@ -549,19 +563,24 @@ namespace dlib typename out_image_type > typename disable_if >::type operator() ( - const in_image_type& original, - out_image_type& down + const in_image_type& original_, + out_image_type& down_ ) const { // make sure requires clause is not broken - DLIB_ASSERT(is_same_object(original, down) == false, + DLIB_ASSERT(is_same_object(original_, down_) == false, "\t void pyramid_down_3_2::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) + << "\n\t is_same_object(original_, down_): " << is_same_object(original_, down_) << "\n\t this: " << this ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + const_image_view original(original_); + image_view down(down_); if (original.nr() <= 8 || original.nc() <= 8) { @@ -572,7 +591,7 @@ namespace dlib const long size_in = 3; const long size_out = 2; - typedef typename pixel_traits::basic_pixel_type bp_type; + typedef typename pixel_traits::basic_pixel_type bp_type; typedef typename promote::type ptype; const long full_nr = size_out*((original.nr()-2)/size_in); const long part_nr = (size_out*(original.nr()-2))/size_in; @@ -590,7 +609,7 @@ namespace dlib for (c = 0; c < full_nc; c+=size_out) { ptype block[size_in][size_in]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); + separable_3x3_filter_block_grayscale(block, original_, rr, cc, 2, 12, 2); // bi-linearly interpolate block assign_pixel(down[r][c] , (block[0][0]*9 + block[1][0]*3 + block[0][1]*3 + block[1][1])/(16*256)); @@ -603,7 +622,7 @@ namespace dlib if (part_nc - full_nc == 1) { ptype block[size_in][2]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); + separable_3x3_filter_block_grayscale(block, original_, rr, cc, 2, 12, 2); // bi-linearly interpolate partial block assign_pixel(down[r][c] , (block[0][0]*9 + block[1][0]*3 + block[0][1]*3 + block[1][1])/(16*256)); @@ -618,7 +637,7 @@ namespace dlib for (c = 0; c < full_nc; c+=size_out) { ptype block[2][size_in]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); + separable_3x3_filter_block_grayscale(block, original_, rr, cc, 2, 12, 2); // bi-linearly interpolate partial block assign_pixel(down[r][c] , (block[0][0]*9 + block[1][0]*3 + block[0][1]*3 + block[1][1])/(16*256)); @@ -629,7 +648,7 @@ namespace dlib if (part_nc - full_nc == 1) { ptype block[2][2]; - separable_3x3_filter_block_grayscale(block, original, rr, cc, 2, 12, 2); + separable_3x3_filter_block_grayscale(block, original_, rr, cc, 2, 12, 2); // bi-linearly interpolate partial block assign_pixel(down[r][c] , (block[0][0]*9 + block[1][0]*3 + block[0][1]*3 + block[1][1])/(16*256)); @@ -655,19 +674,24 @@ namespace dlib typename out_image_type > typename enable_if >::type operator() ( - const in_image_type& original, - out_image_type& down + const in_image_type& original_, + out_image_type& down_ ) const { // make sure requires clause is not broken - DLIB_ASSERT( is_same_object(original, down) == false, + DLIB_ASSERT( is_same_object(original_, down_) == false, "\t void pyramid_down_3_2::operator()" - << "\n\t is_same_object(original, down): " << is_same_object(original, down) + << "\n\t is_same_object(original_, down_): " << is_same_object(original_, down_) << "\n\t this: " << this ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + + const_image_view original(original_); + image_view down(down_); if (original.nr() <= 8 || original.nc() <= 8) { @@ -694,7 +718,7 @@ namespace dlib for (c = 0; c < full_nc; c+=size_out) { rgbptype block[size_in][size_in]; - separable_3x3_filter_block_rgb(block, original, rr, cc, 2, 12, 2); + separable_3x3_filter_block_rgb(block, original_, rr, cc, 2, 12, 2); // bi-linearly interpolate block down[r][c].red = (block[0][0].red*9 + block[1][0].red*3 + block[0][1].red*3 + block[1][1].red)/(16*256); @@ -718,7 +742,7 @@ namespace dlib if (part_nc - full_nc == 1) { rgbptype block[size_in][2]; - separable_3x3_filter_block_rgb(block, original, rr, cc, 2, 12, 2); + separable_3x3_filter_block_rgb(block, original_, rr, cc, 2, 12, 2); // bi-linearly interpolate partial block down[r][c].red = (block[0][0].red*9 + block[1][0].red*3 + block[0][1].red*3 + block[1][1].red)/(16*256); @@ -738,7 +762,7 @@ namespace dlib for (c = 0; c < full_nc; c+=size_out) { rgbptype block[2][size_in]; - separable_3x3_filter_block_rgb(block, original, rr, cc, 2, 12, 2); + separable_3x3_filter_block_rgb(block, original_, rr, cc, 2, 12, 2); // bi-linearly interpolate partial block down[r][c].red = (block[0][0].red*9 + block[1][0].red*3 + block[0][1].red*3 + block[1][1].red)/(16*256); @@ -754,7 +778,7 @@ namespace dlib if (part_nc - full_nc == 1) { rgbptype block[2][2]; - separable_3x3_filter_block_rgb(block, original, rr, cc, 2, 12, 2); + separable_3x3_filter_block_rgb(block, original_, rr, cc, 2, 12, 2); // bi-linearly interpolate partial block down[r][c].red = (block[0][0].red*9 + block[1][0].red*3 + block[0][1].red*3 + block[1][1].red)/(16*256); @@ -878,12 +902,13 @@ namespace dlib << "\n\t this: " << this ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - down.set_size(((N-1)*original.nr())/N, - ((N-1)*original.nc())/N); + set_image_size(down, ((N-1)*num_rows(original))/N, ((N-1)*num_columns(original))/N); resize_image(original, down); } }; diff --git a/dlib/image_transforms/image_pyramid_abstract.h b/dlib/image_transforms/image_pyramid_abstract.h index 3e4c2dce7..cdaa5171b 100644 --- a/dlib/image_transforms/image_pyramid_abstract.h +++ b/dlib/image_transforms/image_pyramid_abstract.h @@ -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::has_alpha == false - - pixel_traits::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

::has_alpha == false ensures - #down will contain an image that is roughly (N-1)/N times the size of the original image. diff --git a/dlib/image_transforms/integral_image.h b/dlib/image_transforms/integral_image.h index ae0027b91..2ae47d921 100644 --- a/dlib/image_transforms/integral_image.h +++ b/dlib/image_transforms/integral_image.h @@ -31,9 +31,10 @@ namespace dlib template void load ( - const image_type& img + const image_type& img_ ) { + const_image_view img(img_); T pixel; int_img.set_size(img.nr(), img.nc()); diff --git a/dlib/image_transforms/integral_image_abstract.h b/dlib/image_transforms/integral_image_abstract.h index b635d406a..95c80aff8 100644 --- a/dlib/image_transforms/integral_image_abstract.h +++ b/dlib/image_transforms/integral_image_abstract.h @@ -59,8 +59,10 @@ namespace dlib ); /*! requires - - image_type == a type that implements the array2d/array2d_kernel_abstract.h interface - - pixel_traits::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

::has_alpha == false ensures - #nr() == img.nr() - #nc() == img.nc() diff --git a/dlib/image_transforms/interpolation.h b/dlib/image_transforms/interpolation.h index 4c4840b4a..33b1a7beb 100644 --- a/dlib/image_transforms/interpolation.h +++ b/dlib/image_transforms/interpolation.h @@ -20,14 +20,14 @@ namespace dlib { public: - template + template bool operator() ( - const image_type& img, + const image_view_type& img, const dlib::point& p, pixel_type& result ) const { - COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); + COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); if (get_rect(img).contains(p)) { @@ -49,19 +49,19 @@ namespace dlib template struct is_rgb_image { - const static bool value = pixel_traits::rgb; + const static bool value = pixel_traits::rgb; }; public: - template - typename disable_if,bool>::type operator() ( - const image_type& img, + template + typename disable_if,bool>::type operator() ( + const image_view_type& img, const dlib::vector& p, pixel_type& result ) const { - COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); + COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); const long left = static_cast(std::floor(p.x())); const long top = static_cast(std::floor(p.y())); @@ -90,14 +90,14 @@ namespace dlib return true; } - template - typename enable_if,bool>::type operator() ( - const image_type& img, + template + typename enable_if,bool>::type operator() ( + const image_view_type& img, const dlib::vector& p, pixel_type& result ) const { - COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); + COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); const long left = static_cast(std::floor(p.x())); const long top = static_cast(std::floor(p.y())); @@ -151,19 +151,19 @@ namespace dlib template struct is_rgb_image { - const static bool value = pixel_traits::rgb; + const static bool value = pixel_traits::rgb; }; public: - template - typename disable_if,bool>::type operator() ( - const image_type& img, + template + typename disable_if,bool>::type operator() ( + const image_view_type& img, const dlib::vector& p, pixel_type& result ) const { - COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); + COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); const point pp(p); @@ -189,14 +189,14 @@ namespace dlib return true; } - template - typename enable_if,bool>::type operator() ( - const image_type& img, + template + typename enable_if,bool>::type operator() ( + const image_view_type& img, const dlib::vector& p, pixel_type& result ) const { - COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); + COMPILE_TIME_ASSERT(pixel_traits::has_alpha == false); const point pp(p); @@ -342,13 +342,15 @@ namespace dlib << "\n\t is_same_object(in_img, out_img): " << is_same_object(in_img, out_img) ); + const_image_view imgv(in_img); + image_view out_imgv(out_img); for (long r = area.top(); r <= area.bottom(); ++r) { for (long c = area.left(); c <= area.right(); ++c) { - if (!interp(in_img, map_point(dlib::vector(c,r)), out_img[r][c])) - set_background(out_img[r][c]); + if (!interp(imgv, map_point(dlib::vector(c,r)), out_imgv[r][c])) + set_background(out_imgv[r][c]); } } } @@ -522,9 +524,9 @@ namespace dlib // ---------------------------------------------------------------------------------------- template - struct is_rgb_image { const static bool value = pixel_traits::rgb; }; + struct is_rgb_image { const static bool value = pixel_traits::pixel_type>::rgb; }; template - struct is_grayscale_image { const static bool value = pixel_traits::grayscale; }; + struct is_grayscale_image { const static bool value = pixel_traits::pixel_type>::grayscale; }; // This is an optimized version of resize_image for the case where bilinear // interpolation is used. @@ -535,17 +537,21 @@ namespace dlib typename disable_if_c<(is_rgb_image::value&&is_rgb_image::value) || (is_grayscale_image::value&&is_grayscale_image::value)>::type resize_image ( - const image_type1& in_img, - image_type2& out_img, + const image_type1& in_img_, + image_type2& out_img_, interpolate_bilinear ) { // 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 resize_image()" << "\n\t Invalid inputs were given to this function." - << "\n\t is_same_object(in_img, out_img): " << is_same_object(in_img, out_img) + << "\n\t is_same_object(in_img_, out_img_): " << is_same_object(in_img_, out_img_) ); + + const_image_view in_img(in_img_); + image_view out_img(out_img_); + if (out_img.nr() <= 1 || out_img.nc() <= 1) { assign_all_pixels(out_img, 0); @@ -553,8 +559,8 @@ namespace dlib } - typedef typename image_type1::type T; - typedef typename image_type2::type U; + typedef typename image_traits::pixel_type T; + typedef typename image_traits::pixel_type U; const double x_scale = (in_img.nc()-1)/(double)std::max((out_img.nc()-1),1); const double y_scale = (in_img.nr()-1)/(double)std::max((out_img.nr()-1),1); double y = -y_scale; @@ -618,24 +624,28 @@ namespace dlib typename image_type > typename enable_if >::type resize_image ( - const image_type& in_img, - image_type& out_img, + const image_type& in_img_, + image_type& out_img_, interpolate_bilinear ) { // 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 resize_image()" << "\n\t Invalid inputs were given to this function." - << "\n\t is_same_object(in_img, out_img): " << is_same_object(in_img, out_img) + << "\n\t is_same_object(in_img_, out_img_): " << is_same_object(in_img_, out_img_) ); + + const_image_view in_img(in_img_); + image_view out_img(out_img_); + if (out_img.nr() <= 1 || out_img.nc() <= 1) { assign_all_pixels(out_img, 0); return; } - typedef typename image_type::type T; + typedef typename image_traits::pixel_type T; const double x_scale = (in_img.nc()-1)/(double)std::max((out_img.nc()-1),1); const double y_scale = (in_img.nr()-1)/(double)std::max((out_img.nr()-1),1); double y = -y_scale; @@ -716,17 +726,21 @@ namespace dlib typename image_type > typename enable_if >::type resize_image ( - const image_type& in_img, - image_type& out_img, + const image_type& in_img_, + image_type& out_img_, interpolate_bilinear ) { // 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 resize_image()" << "\n\t Invalid inputs were given to this function." - << "\n\t is_same_object(in_img, out_img): " << is_same_object(in_img, out_img) + << "\n\t is_same_object(in_img_, out_img_): " << is_same_object(in_img_, out_img_) ); + + const_image_view in_img(in_img_); + image_view out_img(out_img_); + if (out_img.nr() <= 1 || out_img.nc() <= 1) { assign_all_pixels(out_img, 0); @@ -734,7 +748,7 @@ namespace dlib } - typedef typename image_type::type T; + typedef typename image_traits::pixel_type T; const double x_scale = (in_img.nc()-1)/(double)std::max((out_img.nc()-1),1); const double y_scale = (in_img.nr()-1)/(double)std::max((out_img.nr()-1),1); double y = -y_scale; @@ -1046,7 +1060,7 @@ namespace dlib for (unsigned long i = 0; i < images.size(); ++i) { flip_image_left_right(images[i], temp); - temp.swap(images[i]); + swap(temp,images[i]); for (unsigned long j = 0; j < objects[i].size(); ++j) { objects[i][j] = impl::flip_rect_left_right(objects[i][j], get_rect(images[i])); @@ -1077,7 +1091,7 @@ namespace dlib for (unsigned long i = 0; i < images.size(); ++i) { flip_image_left_right(images[i], temp); - temp.swap(images[i]); + swap(temp, images[i]); for (unsigned long j = 0; j < objects[i].size(); ++j) { objects[i][j] = impl::flip_rect_left_right(objects[i][j], get_rect(images[i])); @@ -1113,7 +1127,7 @@ namespace dlib for (unsigned long i = 0; i < images.size(); ++i) { pyramid_up(images[i], temp, pyr); - temp.swap(images[i]); + swap(temp, images[i]); for (unsigned long j = 0; j < objects[i].size(); ++j) { objects[i][j] = pyr.rect_up(objects[i][j]); @@ -1146,7 +1160,7 @@ namespace dlib for (unsigned long i = 0; i < images.size(); ++i) { pyramid_up(images[i], temp, pyr); - temp.swap(images[i]); + swap(temp, images[i]); for (unsigned long j = 0; j < objects[i].size(); ++j) { objects[i][j] = pyr.rect_up(objects[i][j]); @@ -1179,7 +1193,7 @@ namespace dlib for (unsigned long i = 0; i < images.size(); ++i) { const point_transform_affine tran = rotate_image(images[i], temp, angle); - temp.swap(images[i]); + swap(temp, images[i]); for (unsigned long j = 0; j < objects[i].size(); ++j) { const rectangle rect = objects[i][j]; @@ -1210,7 +1224,7 @@ namespace dlib for (unsigned long i = 0; i < images.size(); ++i) { const point_transform_affine tran = rotate_image(images[i], temp, angle); - temp.swap(images[i]); + swap(temp, images[i]); for (unsigned long j = 0; j < objects[i].size(); ++j) { const rectangle rect = objects[i][j]; @@ -1325,9 +1339,9 @@ namespace dlib << "\n\t is_same_object(in_img, out_img): " << is_same_object(in_img, out_img) ); - if (in_img.size() == 0) + if (image_size(in_img) == 0) { - out_img.clear(); + set_image_size(out_img, 0, 0); return; } @@ -1335,10 +1349,10 @@ namespace dlib rectangle uprect = pyr.rect_up(rect); if (uprect.is_empty()) { - out_img.clear(); + set_image_size(out_img, 0, 0); return; } - out_img.set_size(uprect.bottom()+1, uprect.right()+1); + set_image_size(out_img, uprect.bottom()+1, uprect.right()+1); resize_image(in_img, out_img, interp); } @@ -1379,7 +1393,7 @@ namespace dlib { image_type temp; pyramid_up(img, temp, pyr); - temp.swap(img); + swap(temp, img); } // ---------------------------------------------------------------------------------------- @@ -1502,7 +1516,7 @@ namespace dlib chips.resize(chip_locations.size()); for (unsigned long i = 0; i < chips.size(); ++i) { - chips[i].set_size(chip_locations[i].rows, chip_locations[i].cols); + set_image_size(chips[i], chip_locations[i].rows, chip_locations[i].cols); // figure out which level in the pyramid to use to extract the chip int level = -1; @@ -1545,7 +1559,7 @@ namespace dlib std::vector chip_locations(1,location); dlib::array chips; extract_image_chips(img, chip_locations, chips); - chips[0].swap(chip); + swap(chips[0], chip); } // ---------------------------------------------------------------------------------------- diff --git a/dlib/image_transforms/interpolation_abstract.h b/dlib/image_transforms/interpolation_abstract.h index 034af3798..d64c5386a 100644 --- a/dlib/image_transforms/interpolation_abstract.h +++ b/dlib/image_transforms/interpolation_abstract.h @@ -22,18 +22,18 @@ namespace dlib public: template < - typename image_type, + typename image_view_type, typename pixel_type > bool operator() ( - const image_type& img, + const image_view_type& img, const dlib::point& p, pixel_type& result ) const; /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits::has_alpha == false + - image_view_type == an image_view or const_image_view object. + - pixel_traits::has_alpha == false - pixel_traits is defined ensures - if (p is located inside img) then @@ -63,18 +63,18 @@ namespace dlib template < typename T, - typename image_type, + typename image_view_type, typename pixel_type > bool operator() ( - const image_type& img, + const image_view_type& img, const dlib::vector& p, pixel_type& result ) const; /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits::has_alpha == false + - image_view_type == an image_view or const_image_view object + - pixel_traits::has_alpha == false - pixel_traits is defined ensures - if (there is an interpolatable image location at point p in img) then @@ -104,18 +104,18 @@ namespace dlib template < typename T, - typename image_type, + typename image_view_type, typename pixel_type > bool operator() ( - const image_type& img, + const image_view_type& img, const dlib::vector& p, pixel_type& result ) const; /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits::has_alpha == false + - image_view_type == an image_view or const_image_view object. + - pixel_traits::has_alpha == false - pixel_traits is defined ensures - if (there is an interpolatable image location at point p in img) then @@ -197,15 +197,17 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - interpolation_type == interpolate_nearest_neighbor, interpolate_bilinear, interpolate_quadratic, or a type with a compatible interface. - map_point should be a function which takes dlib::vector objects and returns dlib::vector objects. An example is point_transform_affine. - set_background should be a function which can take a single argument of - type image_type2::type. Examples are black_background, white_background, - and no_background. + type image_traits::pixel_type. Examples are black_background, + white_background, and no_background. - get_rect(out_img).contains(area) == true - is_same_object(in_img, out_img) == false ensures @@ -241,14 +243,16 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - interpolation_type == interpolate_nearest_neighbor, interpolate_bilinear, interpolate_quadratic, or a type with a compatible interface. - map_point should be a function which takes dlib::vector objects and returns dlib::vector objects. An example is point_transform_affine. - set_background should be a function which can take a single argument of - type image_type2::type. Examples are black_background, white_background, + type image_traits::pixel_type. Examples are black_background, white_background, and no_background. - is_same_object(in_img, out_img) == false ensures @@ -273,8 +277,10 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - interpolation_type == interpolate_nearest_neighbor, interpolate_bilinear, interpolate_quadratic, or a type with a compatible interface. - map_point should be a function which takes dlib::vector objects and @@ -302,8 +308,10 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - interpolation_type == interpolate_nearest_neighbor, interpolate_bilinear, interpolate_quadratic, or a type with a compatible interface. - is_same_object(in_img, out_img) == false @@ -331,10 +339,11 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits::has_alpha == false - - pixel_traits is defined + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - pixel_traits::pixel_type>::has_alpha == false - is_same_object(in_img, out_img) == false ensures - #out_img == a copy of in_img which has been rotated angle radians counter clockwise. @@ -359,8 +368,10 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - interpolation_type == interpolate_nearest_neighbor, interpolate_bilinear, interpolate_quadratic, or a type with a compatible interface. - is_same_object(in_img, out_img) == false @@ -387,10 +398,11 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits::has_alpha == false - - pixel_traits is defined + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - pixel_traits::pixel_type>::has_alpha == false - is_same_object(in_img, out_img) == false ensures - #out_img == A copy of in_img which has been stretched so that it @@ -413,10 +425,10 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined - - pixel_traits is defined + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - is_same_object(in_img, out_img) == false ensures - #out_img.nr() == in_img.nr() @@ -439,8 +451,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - T == rectangle or full_object_detection - images.size() == objects.size() ensures @@ -470,8 +482,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - images.size() == objects.size() - images.size() == objects2.size() - T == rectangle or full_object_detection @@ -507,10 +519,10 @@ namespace dlib ); /*! requires + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - is_vector(angles) == true - angles.size() > 0 - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined - images.size() == objects.size() - images.size() == objects2.size() - T == rectangle or full_object_detection @@ -545,10 +557,10 @@ namespace dlib ); /*! requires + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - is_vector(angles) == true - angles.size() > 0 - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined - images.size() == objects.size() - T == rectangle or full_object_detection ensures @@ -567,8 +579,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - images.size() == objects.size() ensures - This function replaces each image in images with the left/right flipped @@ -593,8 +605,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - images.size() == objects.size() - images.size() == objects2.size() ensures @@ -623,8 +635,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - images.size() == objects.size() ensures - This function replaces each image in images with an upsampled version of that @@ -651,8 +663,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - images.size() == objects.size() - images.size() == objects2.size() ensures @@ -680,8 +692,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - images.size() == objects.size() ensures - This function replaces each image in images with a rotated version of that @@ -711,8 +723,8 @@ namespace dlib ); /*! requires - - image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - images.size() == objects.size() - images.size() == objects2.size() ensures @@ -747,10 +759,10 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits is defined - - pixel_traits is defined + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - is_same_object(in_img, out_img) == false ensures - #out_img.nr() == in_img.nr() @@ -774,8 +786,10 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - pyramid_type == a type compatible with the image pyramid objects defined in dlib/image_transforms/image_pyramid_abstract.h - interpolation_type == interpolate_nearest_neighbor, interpolate_bilinear, @@ -810,8 +824,10 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - pyramid_type == a type compatible with the image pyramid objects defined in dlib/image_transforms/image_pyramid_abstract.h - is_same_object(in_img, out_img) == false @@ -831,7 +847,8 @@ 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 - pyramid_type == a type compatible with the image pyramid objects defined in dlib/image_transforms/image_pyramid_abstract.h ensures @@ -851,7 +868,8 @@ 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 ensures - performs: pyramid_up(img, pyramid_down<2>()); (i.e. it upsamples the given image and doubles it in size.) @@ -998,10 +1016,11 @@ namespace dlib ); /*! requires - - image_type1 == is an implementation of array2d/array2d_kernel_abstract.h - - image_type2 == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits::has_alpha == false - - pixel_traits is defined + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - pixel_traits::pixel_type>::has_alpha == false - for all valid i: - chip_locations[i].rect.is_empty() == false - chip_locations[i].size != 0 diff --git a/dlib/image_transforms/label_connected_blobs.h b/dlib/image_transforms/label_connected_blobs.h index 0fbade6a4..c25346c76 100644 --- a/dlib/image_transforms/label_connected_blobs.h +++ b/dlib/image_transforms/label_connected_blobs.h @@ -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 img(img_); + image_view label_img(label_img_); std::stack neighbors; label_img.set_size(img.nr(), img.nc()); diff --git a/dlib/image_transforms/label_connected_blobs_abstract.h b/dlib/image_transforms/label_connected_blobs_abstract.h index 52b4d0d21..770b59b3a 100644 --- a/dlib/image_transforms/label_connected_blobs_abstract.h +++ b/dlib/image_transforms/label_connected_blobs_abstract.h @@ -58,9 +58,9 @@ namespace dlib with the label_connected_blobs() routine defined below. !*/ - template + template 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 + template 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 + template 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 + template 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. diff --git a/dlib/image_transforms/morphological_operations.h b/dlib/image_transforms/morphological_operations.h index c2b6f6a48..6679c0fde 100644 --- a/dlib/image_transforms/morphological_operations.h +++ b/dlib/image_transforms/morphological_operations.h @@ -16,14 +16,15 @@ namespace dlib { template bool is_binary_image ( - const image_type& img + const image_type& img_ ) /*! ensures - - returns true if img contains only on_pixel and off_pixel values. + - returns true if img_ contains only on_pixel and off_pixel values. - returns false otherwise !*/ { + const_image_view img(img_); for (long r = 0; r < img.nr(); ++r) { for (long c = 0; c < img.nc(); ++c) @@ -75,23 +76,25 @@ namespace dlib long N > void binary_dilation ( - const in_image_type& in_img, - out_image_type& out_img, + const in_image_type& in_img_, + out_image_type& out_img_, const unsigned char (&structuring_element)[M][N] ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); using namespace morphological_operations_helpers; COMPILE_TIME_ASSERT(M%2 == 1); COMPILE_TIME_ASSERT(N%2 == 1); - DLIB_ASSERT(is_same_object(in_img,out_img) == false, + DLIB_ASSERT(is_same_object(in_img_,out_img_) == false, "\tvoid binary_dilation()" << "\n\tYou must give two different image objects" ); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - DLIB_ASSERT(is_binary_image(in_img) , + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + DLIB_ASSERT(is_binary_image(in_img_) , "\tvoid binary_dilation()" << "\n\tin_img must be a binary image" ); @@ -101,6 +104,8 @@ namespace dlib ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) @@ -147,23 +152,25 @@ namespace dlib long N > void binary_erosion ( - const in_image_type& in_img, - out_image_type& out_img, + const in_image_type& in_img_, + out_image_type& out_img_, const unsigned char (&structuring_element)[M][N] ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); using namespace morphological_operations_helpers; COMPILE_TIME_ASSERT(M%2 == 1); COMPILE_TIME_ASSERT(N%2 == 1); - DLIB_ASSERT(is_same_object(in_img,out_img) == false, + DLIB_ASSERT(is_same_object(in_img_,out_img_) == false, "\tvoid binary_erosion()" << "\n\tYou must give two different image objects" ); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - DLIB_ASSERT(is_binary_image(in_img) , + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + DLIB_ASSERT(is_binary_image(in_img_) , "\tvoid binary_erosion()" << "\n\tin_img must be a binary image" ); @@ -172,6 +179,8 @@ namespace dlib << "\n\tthe structuring_element must be a binary image" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything @@ -229,8 +238,10 @@ namespace dlib const unsigned long iter = 1 ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); using namespace morphological_operations_helpers; COMPILE_TIME_ASSERT(M%2 == 1); @@ -239,7 +250,7 @@ namespace dlib "\tvoid binary_open()" << "\n\tYou must give two different image objects" ); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); + COMPILE_TIME_ASSERT(pixel_traits::grayscale); DLIB_ASSERT(is_binary_image(in_img) , "\tvoid binary_open()" << "\n\tin_img must be a binary image" @@ -251,13 +262,13 @@ namespace dlib // if there isn't any input image then don't do anything - if (in_img.size() == 0) + if (num_rows(in_img)*num_columns(in_img) == 0) { - out_img.clear(); + set_image_size(out_img, 0,0); return; } - out_img.set_size(in_img.nr(),in_img.nc()); + set_image_size(out_img, num_rows(in_img), num_columns(in_img)); if (iter == 0) { @@ -278,14 +289,14 @@ namespace dlib // do the extra erosions for (unsigned long i = 1; i < iter; ++i) { - temp1.swap(temp2); + swap(temp1, temp2); binary_erosion(temp2,temp1,structuring_element); } // do the extra dilations for (unsigned long i = 1; i < iter; ++i) { - temp1.swap(temp2); + swap(temp1, temp2); binary_dilation(temp2,temp1,structuring_element); } @@ -308,8 +319,11 @@ namespace dlib const unsigned long iter = 1 ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + using namespace morphological_operations_helpers; COMPILE_TIME_ASSERT(M%2 == 1); @@ -318,7 +332,7 @@ namespace dlib "\tvoid binary_close()" << "\n\tYou must give two different image objects" ); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); + COMPILE_TIME_ASSERT(pixel_traits::grayscale); DLIB_ASSERT(is_binary_image(in_img) , "\tvoid binary_close()" << "\n\tin_img must be a binary image" @@ -330,13 +344,13 @@ namespace dlib // if there isn't any input image then don't do anything - if (in_img.size() == 0) + if (num_rows(in_img)*num_columns(in_img) == 0) { - out_img.clear(); + set_image_size(out_img, 0,0); return; } - out_img.set_size(in_img.nr(),in_img.nc()); + set_image_size(out_img, num_rows(in_img), num_columns(in_img)); if (iter == 0) { @@ -357,14 +371,14 @@ namespace dlib // do the extra dilations for (unsigned long i = 1; i < iter; ++i) { - temp1.swap(temp2); + swap(temp1, temp2); binary_dilation(temp2,temp1,structuring_element); } // do the extra erosions for (unsigned long i = 1; i < iter; ++i) { - temp1.swap(temp2); + swap(temp1, temp2); binary_erosion(temp2,temp1,structuring_element); } @@ -380,26 +394,34 @@ namespace dlib typename out_image_type > void binary_intersection ( - const in_image_type1& in_img1, - const in_image_type2& in_img2, - out_image_type& out_img + const in_image_type1& in_img1_, + const in_image_type2& in_img2_, + out_image_type& out_img_ ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type1; + typedef typename image_traits::pixel_type in_pixel_type2; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); using namespace morphological_operations_helpers; - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - DLIB_ASSERT(is_binary_image(in_img1) , + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + DLIB_ASSERT(is_binary_image(in_img1_) , "\tvoid binary_intersection()" << "\n\tin_img1 must be a binary image" ); - DLIB_ASSERT(is_binary_image(in_img2) , + DLIB_ASSERT(is_binary_image(in_img2_) , "\tvoid binary_intersection()" << "\n\tin_img2 must be a binary image" ); + + const_image_view in_img1(in_img1_); + const_image_view in_img2(in_img2_); + image_view out_img(out_img_); + DLIB_ASSERT(in_img1.nc() == in_img2.nc(), "\tvoid binary_intersection()" << "\n\tin_img1 and in_img2 must have the same ncs." @@ -444,26 +466,35 @@ namespace dlib typename out_image_type > void binary_union ( - const in_image_type1& in_img1, - const in_image_type2& in_img2, - out_image_type& out_img + const in_image_type1& in_img1_, + const in_image_type2& in_img2_, + out_image_type& out_img_ ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type1; + typedef typename image_traits::pixel_type in_pixel_type2; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + using namespace morphological_operations_helpers; - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - DLIB_ASSERT(is_binary_image(in_img1) , + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + DLIB_ASSERT(is_binary_image(in_img1_) , "\tvoid binary_intersection()" << "\n\tin_img1 must be a binary image" ); - DLIB_ASSERT(is_binary_image(in_img2) , + DLIB_ASSERT(is_binary_image(in_img2_) , "\tvoid binary_intersection()" << "\n\tin_img2 must be a binary image" ); + + const_image_view in_img1(in_img1_); + const_image_view in_img2(in_img2_); + image_view out_img(out_img_); + DLIB_ASSERT(in_img1.nc() == in_img2.nc(), "\tvoid binary_intersection()" << "\n\tin_img1 and in_img2 must have the same ncs." @@ -508,26 +539,34 @@ namespace dlib typename out_image_type > void binary_difference ( - const in_image_type1& in_img1, - const in_image_type2& in_img2, - out_image_type& out_img + const in_image_type1& in_img1_, + const in_image_type2& in_img2_, + out_image_type& out_img_ ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type1; + typedef typename image_traits::pixel_type in_pixel_type2; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); using namespace morphological_operations_helpers; - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - DLIB_ASSERT(is_binary_image(in_img1) , + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + DLIB_ASSERT(is_binary_image(in_img1_) , "\tvoid binary_difference()" << "\n\tin_img1 must be a binary image" ); - DLIB_ASSERT(is_binary_image(in_img2) , + DLIB_ASSERT(is_binary_image(in_img2_) , "\tvoid binary_difference()" << "\n\tin_img2 must be a binary image" ); + + const_image_view in_img1(in_img1_); + const_image_view in_img2(in_img2_); + image_view out_img(out_img_); + DLIB_ASSERT(in_img1.nc() == in_img2.nc(), "\tvoid binary_difference()" << "\n\tin_img1 and in_img2 must have the same ncs." @@ -571,20 +610,25 @@ namespace dlib typename out_image_type > void binary_complement ( - 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::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + typedef typename image_traits::pixel_type in_pixel_type; + typedef typename image_traits::pixel_type out_pixel_type; + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + using namespace morphological_operations_helpers; - COMPILE_TIME_ASSERT(pixel_traits::grayscale); - DLIB_ASSERT(is_binary_image(in_img) , + COMPILE_TIME_ASSERT(pixel_traits::grayscale); + DLIB_ASSERT(is_binary_image(in_img_) , "\tvoid binary_complement()" << "\n\tin_img must be a binary image" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) diff --git a/dlib/image_transforms/morphological_operations_abstract.h b/dlib/image_transforms/morphological_operations_abstract.h index add2aefbb..7f0da49b0 100644 --- a/dlib/image_transforms/morphological_operations_abstract.h +++ b/dlib/image_transforms/morphological_operations_abstract.h @@ -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::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::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::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::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::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::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::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::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::grayscale == true - - pixel_traits::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::has_alpha == false - - pixel_traits::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::grayscale == true - - pixel_traits::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::has_alpha == false - - pixel_traits::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::grayscale == true - - pixel_traits::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::has_alpha == false - - pixel_traits::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::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::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 diff --git a/dlib/image_transforms/segment_image.h b/dlib/image_transforms/segment_image.h index 5ba374ac5..02d9f8eb6 100644 --- a/dlib/image_transforms/segment_image.h +++ b/dlib/image_transforms/segment_image.h @@ -125,18 +125,28 @@ namespace dlib // ------------------------------------------------------------------------------------ + namespace impl + { + template + struct uint8_or_uint16_pixels + { + typedef typename image_view_type::pixel_type pixel_type; + const static bool value = is_same_type::value || + is_same_type::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 enable_if_c::value || - is_same_type::value>::type + typename enable_if >::type get_pixel_edges ( const in_image_type& in_img, std::vector >& sorted_edges ) { - typedef typename in_image_type::type ptype; + typedef typename in_image_type::pixel_type ptype; typedef T diff_type; std::vector counts(std::numeric_limits::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 disable_if_c::value || - is_same_type::value>::type + typename disable_if >::type get_pixel_edges ( const in_image_type& in_img, std::vector >& 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 edge_diff; typedef T diff_type; typedef segment_image_edge_data_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::pixel_type ptype; typedef typename edge_diff_funct::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::value); + COMPILE_TIME_ASSERT(is_unsigned_type::pixel_type>::value); + + const_image_view in_img(in_img_); + image_view 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& rects, const matrix_exp& kvals, const unsigned long min_size = 20, @@ -629,9 +641,10 @@ namespace dlib typedef dlib::set::kernel_1a set_of_rects; using namespace dlib::impl; - typedef typename in_image_type::type ptype; + typedef typename image_traits::pixel_type ptype; typedef typename edge_diff_funct::diff_type diff_type; + const_image_view in_img(in_img_); // don't bother doing anything if the image is too small if (in_img.nr() < 2 || in_img.nc() < 2) diff --git a/dlib/image_transforms/segment_image_abstract.h b/dlib/image_transforms/segment_image_abstract.h index 21355698f..f3380c0ac 100644 --- a/dlib/image_transforms/segment_image_abstract.h +++ b/dlib/image_transforms/segment_image_abstract.h @@ -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 diff --git a/dlib/image_transforms/spatial_filtering.h b/dlib/image_transforms/spatial_filtering.h index f30374156..4f197a9a5 100644 --- a/dlib/image_transforms/spatial_filtering.h +++ b/dlib/image_transforms/spatial_filtering.h @@ -27,17 +27,17 @@ namespace dlib typename T > rectangle grayscale_spatially_filter_image ( - const in_image_type& in_img, - out_image_type& out_img, - const matrix_exp& _filter, + const in_image_type& in_img_, + out_image_type& out_img_, + const matrix_exp& filter_, T scale, bool use_abs, bool add_to ) { - const_temp_matrix filter(_filter); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + const_temp_matrix filter(filter_); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); DLIB_ASSERT(scale != 0 && filter.size() != 0, "\trectangle spatially_filter_image()" @@ -46,12 +46,14 @@ namespace dlib << "\n\t filter.nr(): "<< filter.nr() << "\n\t filter.nc(): "<< filter.nc() ); - DLIB_ASSERT(is_same_object(in_img, out_img) == false, + DLIB_ASSERT(is_same_object(in_img_, out_img_) == false, "\trectangle spatially_filter_image()" << "\n\tYou must give two different image objects" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) @@ -71,7 +73,7 @@ namespace dlib const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1); if (!add_to) - zero_border_pixels(out_img, non_border); + zero_border_pixels(out_img_, non_border); // apply the filter to the image for (long r = first_row; r < last_row; ++r) @@ -121,26 +123,28 @@ namespace dlib typename EXP > rectangle float_spatially_filter_image ( - const in_image_type& in_img, - out_image_type& out_img, - const matrix_exp& _filter, + const in_image_type& in_img_, + out_image_type& out_img_, + const matrix_exp& filter_, bool add_to ) { - const_temp_matrix filter(_filter); + const_temp_matrix filter(filter_); DLIB_ASSERT(filter.size() != 0, "\trectangle spatially_filter_image()" << "\n\t You can't give an empty filter." << "\n\t filter.nr(): "<< filter.nr() << "\n\t filter.nc(): "<< filter.nc() ); - DLIB_ASSERT(is_same_object(in_img, out_img) == false, + DLIB_ASSERT(is_same_object(in_img_, out_img_) == false, "\trectangle spatially_filter_image()" << "\n\tYou must give two different image objects" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) @@ -160,7 +164,7 @@ namespace dlib const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1); if (!add_to) - zero_border_pixels(out_img, non_border); + zero_border_pixels(out_img_, non_border); // apply the filter to the image for (long r = first_row; r < last_row; ++r) @@ -243,8 +247,8 @@ namespace dlib > struct is_float_filtering2 { - const static bool value = is_same_type::value && - is_same_type::value && + const static bool value = is_same_type::pixel_type,float>::value && + is_same_type::pixel_type,float>::value && is_same_type::value; }; @@ -256,7 +260,7 @@ namespace dlib typename EXP, typename T > - typename enable_if_c::grayscale && + typename enable_if_c::pixel_type>::grayscale && is_float_filtering2::value,rectangle>::type spatially_filter_image ( const in_image_type& in_img, @@ -288,7 +292,7 @@ namespace dlib typename EXP, typename T > - typename enable_if_c::grayscale && + typename enable_if_c::pixel_type>::grayscale && !is_float_filtering2::value,rectangle>::type spatially_filter_image ( const in_image_type& in_img, @@ -310,17 +314,17 @@ namespace dlib typename EXP, typename T > - typename disable_if_c::grayscale,rectangle>::type + typename disable_if_c::pixel_type>::grayscale,rectangle>::type spatially_filter_image ( - const in_image_type& in_img, - out_image_type& out_img, - const matrix_exp& _filter, + const in_image_type& in_img_, + out_image_type& out_img_, + const matrix_exp& filter_, T scale ) { - const_temp_matrix filter(_filter); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + const_temp_matrix filter(filter_); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); DLIB_ASSERT(scale != 0 && filter.size() != 0, "\trectangle spatially_filter_image()" @@ -329,12 +333,14 @@ namespace dlib << "\n\t filter.nr(): "<< filter.nr() << "\n\t filter.nc(): "<< filter.nc() ); - DLIB_ASSERT(is_same_object(in_img, out_img) == false, + DLIB_ASSERT(is_same_object(in_img_, out_img_) == false, "\trectangle spatially_filter_image()" << "\n\tYou must give two different image objects" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) @@ -360,7 +366,8 @@ namespace dlib { for (long c = first_col; c < last_col; ++c) { - typedef matrix::num,1> ptype; + typedef typename image_traits::pixel_type pixel_type; + typedef matrix::num,1> ptype; ptype p; ptype temp; temp = 0; @@ -376,7 +383,7 @@ namespace dlib temp /= scale; - typename in_image_type::type pp; + pixel_type pp; vector_to_pixel(pp, temp); assign_pixel(out_img[r][c], pp); } @@ -415,8 +422,8 @@ namespace dlib typename T > rectangle grayscale_spatially_filter_image_separable ( - const in_image_type& in_img, - out_image_type& out_img, + const in_image_type& in_img_, + out_image_type& out_img_, const matrix_exp& _row_filter, const matrix_exp& _col_filter, T scale, @@ -426,8 +433,8 @@ namespace dlib { const_temp_matrix row_filter(_row_filter); const_temp_matrix col_filter(_col_filter); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); DLIB_ASSERT(scale != 0 && row_filter.size() != 0 && col_filter.size() != 0 && is_vector(row_filter) && @@ -440,12 +447,14 @@ namespace dlib << "\n\t is_vector(row_filter): "<< is_vector(row_filter) << "\n\t is_vector(col_filter): "<< is_vector(col_filter) ); - DLIB_ASSERT(is_same_object(in_img, out_img) == false, + DLIB_ASSERT(is_same_object(in_img_, out_img_) == false, "\trectangle spatially_filter_image_separable()" << "\n\tYou must give two different image objects" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) @@ -467,10 +476,9 @@ namespace dlib if (!add_to) zero_border_pixels(out_img, non_border); - typedef typename out_image_type::mem_manager_type mem_manager_type; typedef typename EXP1::type ptype; - array2d temp_img; + array2d temp_img; temp_img.set_size(in_img.nr(), in_img.nc()); // apply the row filter @@ -534,8 +542,8 @@ namespace dlib > struct is_float_filtering { - const static bool value = is_same_type::value && - is_same_type::value && + const static bool value = is_same_type::pixel_type,float>::value && + is_same_type::pixel_type,float>::value && is_same_type::value && is_same_type::value; }; @@ -551,11 +559,11 @@ namespace dlib typename EXP2 > rectangle float_spatially_filter_image_separable ( - const in_image_type& in_img, - out_image_type& out_img, + const in_image_type& in_img_, + out_image_type& out_img_, const matrix_exp& _row_filter, const matrix_exp& _col_filter, - out_image_type& scratch, + out_image_type& scratch_, bool add_to = false ) { @@ -576,12 +584,14 @@ namespace dlib << "\n\t is_vector(row_filter): "<< is_vector(row_filter) << "\n\t is_vector(col_filter): "<< is_vector(col_filter) ); - DLIB_ASSERT(is_same_object(in_img, out_img) == false, + DLIB_ASSERT(is_same_object(in_img_, out_img_) == false, "\trectangle float_spatially_filter_image_separable()" << "\n\tYou must give two different image objects" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) @@ -602,6 +612,7 @@ namespace dlib if (!add_to) zero_border_pixels(out_img, non_border); + image_view scratch(scratch_); scratch.set_size(in_img.nr(), in_img.nc()); // apply the row filter @@ -712,7 +723,7 @@ namespace dlib typename EXP2, typename T > - typename enable_if_c::grayscale && + typename enable_if_c::pixel_type>::grayscale && is_float_filtering::value,rectangle>::type spatially_filter_image_separable ( const in_image_type& in_img, @@ -747,7 +758,7 @@ namespace dlib typename EXP2, typename T > - typename enable_if_c::grayscale && + typename enable_if_c::pixel_type>::grayscale && !is_float_filtering::value,rectangle>::type spatially_filter_image_separable ( const in_image_type& in_img, @@ -771,10 +782,10 @@ namespace dlib typename EXP2, typename T > - typename disable_if_c::grayscale,rectangle>::type + typename disable_if_c::pixel_type>::grayscale,rectangle>::type spatially_filter_image_separable ( - const in_image_type& in_img, - out_image_type& out_img, + const in_image_type& in_img_, + out_image_type& out_img_, const matrix_exp& _row_filter, const matrix_exp& _col_filter, T scale @@ -782,8 +793,8 @@ namespace dlib { const_temp_matrix row_filter(_row_filter); const_temp_matrix col_filter(_col_filter); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); DLIB_ASSERT(scale != 0 && row_filter.size() != 0 && col_filter.size() != 0 && is_vector(row_filter) && @@ -796,12 +807,14 @@ namespace dlib << "\n\t is_vector(row_filter): "<< is_vector(row_filter) << "\n\t is_vector(col_filter): "<< is_vector(col_filter) ); - DLIB_ASSERT(is_same_object(in_img, out_img) == false, + DLIB_ASSERT(is_same_object(in_img_, out_img_) == false, "\trectangle spatially_filter_image_separable()" << "\n\tYou must give two different image objects" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) @@ -822,10 +835,10 @@ namespace dlib const rectangle non_border = rectangle(first_col, first_row, last_col-1, last_row-1); zero_border_pixels(out_img, non_border); - typedef typename out_image_type::mem_manager_type mem_manager_type; - typedef matrix::num,1> ptype; + typedef typename image_traits::pixel_type pixel_type; + typedef matrix::num,1> ptype; - array2d temp_img; + array2d temp_img; temp_img.set_size(in_img.nr(), in_img.nc()); // apply the row filter @@ -862,7 +875,7 @@ namespace dlib // save this pixel to the output image - typename in_image_type::type p; + pixel_type p; vector_to_pixel(p, temp); assign_pixel(out_img[r][c], p); } @@ -901,8 +914,8 @@ namespace dlib > rectangle spatially_filter_image_separable_down ( const unsigned long downsample, - const in_image_type& in_img, - out_image_type& out_img, + const in_image_type& in_img_, + out_image_type& out_img_, const matrix_exp& row_filter, const matrix_exp& col_filter, T scale, @@ -910,9 +923,9 @@ namespace dlib bool add_to = false ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::grayscale == true ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::grayscale == true ); DLIB_ASSERT(downsample > 0 && scale != 0 && @@ -929,12 +942,14 @@ namespace dlib << "\n\t is_vector(row_filter): "<< is_vector(row_filter) << "\n\t is_vector(col_filter): "<< is_vector(col_filter) ); - DLIB_ASSERT(is_same_object(in_img, out_img) == false, + DLIB_ASSERT(is_same_object(in_img_, out_img_) == false, "\trectangle spatially_filter_image_separable_down()" << "\n\tYou must give two different image objects" ); + const_image_view in_img(in_img_); + image_view out_img(out_img_); // if there isn't any input image then don't do anything if (in_img.size() == 0) @@ -961,8 +976,7 @@ namespace dlib typedef typename EXP1::type ptype; - typedef typename out_image_type::mem_manager_type mem_manager_type; - array2d temp_img; + array2d temp_img; temp_img.set_size(in_img.nr(), out_img.nc()); // apply the row filter @@ -1043,7 +1057,7 @@ namespace dlib > inline void separable_3x3_filter_block_grayscale ( T (&block)[NR][NC], - const in_image_type& img, + const in_image_type& img_, const long& r, const long& c, const U& fe1, // separable filter end @@ -1051,6 +1065,7 @@ namespace dlib const U& fe2 // separable filter end 2 ) { + const_image_view img(img_); // make sure requires clause is not broken DLIB_ASSERT(shrink_rect(get_rect(img),1).contains(c,r) && shrink_rect(get_rect(img),1).contains(c+NC-1,r+NR-1), @@ -1096,7 +1111,7 @@ namespace dlib > inline void separable_3x3_filter_block_rgb ( T (&block)[NR][NC], - const in_image_type& img, + const in_image_type& img_, const long& r, const long& c, const U& fe1, // separable filter end @@ -1104,6 +1119,7 @@ namespace dlib const U& fe2 // separable filter end 2 ) { + const_image_view img(img_); // make sure requires clause is not broken DLIB_ASSERT(shrink_rect(get_rect(img),1).contains(c,r) && shrink_rect(get_rect(img),1).contains(c+NC-1,r+NR-1), @@ -1217,7 +1233,7 @@ namespace dlib << "\n\t is_same_object(in_img,out_img): " << is_same_object(in_img,out_img) ); - typedef typename pixel_traits::basic_pixel_type type; + typedef typename pixel_traits::pixel_type>::basic_pixel_type type; typedef typename promote::type ptype; const matrix& filt = create_gaussian_filter(sigma, max_size); @@ -1239,24 +1255,26 @@ namespace dlib typename image_type2 > void sum_filter ( - const image_type1& img, - image_type2& out, + const image_type1& img_, + image_type2& out_, const rectangle& rect ) { + const_image_view img(img_); + image_view out(out_); DLIB_ASSERT(img.nr() == out.nr() && img.nc() == out.nc() && - is_same_object(img,out) == false, + is_same_object(img_,out_) == false, "\t void sum_filter()" << "\n\t Invalid arguments given to this function." << "\n\t img.nr(): " << img.nr() << "\n\t img.nc(): " << img.nc() << "\n\t out.nr(): " << out.nr() << "\n\t out.nc(): " << out.nc() - << "\n\t is_same_object(img,out): " << is_same_object(img,out) + << "\n\t is_same_object(img_,out_): " << is_same_object(img_,out_) ); - typedef typename image_type1::type pixel_type; + typedef typename image_traits::pixel_type pixel_type; typedef typename promote::type ptype; std::vector column_sum; @@ -1324,9 +1342,9 @@ namespace dlib cur_sum = cur_sum + column_sum[c+width] - column_sum[c]; if (add_to) - out[r][c] += static_cast(cur_sum); + out[r][c] += static_cast::pixel_type>(cur_sum); else - out[r][c] = static_cast(cur_sum); + out[r][c] = static_cast::pixel_type>(cur_sum); } } } @@ -1355,7 +1373,7 @@ namespace dlib const rectangle& rect ) { - out.set_size(img.nr(), img.nc()); + set_image_size(out, num_rows(img), num_columns(img)); impl::sum_filter(img,out,rect); } @@ -1446,18 +1464,20 @@ namespace dlib typename image_type2 > void max_filter ( - image_type1& img, - image_type2& out, + image_type1& img_, + image_type2& out_, const long width, const long height, - const typename image_type1::type& thresh + const typename image_traits::pixel_type& thresh ) { + image_view img(img_); + image_view out(out_); DLIB_ASSERT( width > 0 && height > 0 && out.nr() == img.nr() && out.nc() == img.nc() && - is_same_object(img,out) == false, + is_same_object(img_,out_) == false, "\t void max_filter()" << "\n\t Invalid arguments given to this function." << "\n\t img.nr(): " << img.nr() @@ -1466,10 +1486,10 @@ namespace dlib << "\n\t out.nc(): " << out.nc() << "\n\t width: " << width << "\n\t height: " << height - << "\n\t is_same_object(img,out): " << is_same_object(img,out) + << "\n\t is_same_object(img_,out_): " << is_same_object(img_,out_) ); - typedef typename image_type1::type pixel_type; + typedef typename image_traits::pixel_type pixel_type; dlib::impl::fast_deque > Q(std::max(width,height)); diff --git a/dlib/image_transforms/spatial_filtering_abstract.h b/dlib/image_transforms/spatial_filtering_abstract.h index c2cce8a94..e23c81f83 100644 --- a/dlib/image_transforms/spatial_filtering_abstract.h +++ b/dlib/image_transforms/spatial_filtering_abstract.h @@ -27,15 +27,17 @@ 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::has_alpha == false - - pixel_traits::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 + - in_img and out_img do not contain pixels with an alpha channel. That is, + pixel_traits::has_alpha is false for the pixels in these objects. - is_same_object(in_img, out_img) == false - T must be some scalar type - filter.size() != 0 - scale != 0 - - if (pixel_traits::grayscale == false) then + - if (in_img doesn't contain grayscale pixels) then - use_abs == false && add_to == false (i.e. You can only use the use_abs and add_to options with grayscale images) ensures @@ -47,7 +49,7 @@ namespace dlib any applicable color space conversion or value saturation is performed. Note that if add_to is true then the filtered output value will be added to out_img rather than overwriting the original value. - - if (pixel_traits::grayscale == false) then + - if (in_img doesn't contain grayscale pixels) then - The filter is applied to each color channel independently. - if (use_abs == true) then - pixel values after filtering that are < 0 are converted to their absolute values. @@ -88,10 +90,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::has_alpha == false - - pixel_traits::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 + - in_img and out_img do not contain pixels with an alpha channel. That is, + pixel_traits::has_alpha is false for the pixels in these objects. - is_same_object(in_img, out_img) == false - T must be some scalar type - scale != 0 @@ -99,7 +103,7 @@ namespace dlib - col_filter.size() != 0 - is_vector(row_filter) == true - is_vector(col_filter) == true - - if (pixel_traits::grayscale == false) then + - if (in_img doesn't contain grayscale pixels) then - use_abs == false && add_to == false (i.e. You can only use the use_abs and add_to options with grayscale images) ensures @@ -114,7 +118,7 @@ namespace dlib any applicable color space conversion or value saturation is performed. Note that if add_to is true then the filtered output value will be added to out_img rather than overwriting the original value. - - if (pixel_traits::grayscale == false) then + - if (in_img doesn't contain grayscale pixels) then - The filter is applied to each color channel independently. - if (use_abs == true) then - pixel values after filtering that are < 0 are converted to their absolute values @@ -153,8 +157,10 @@ 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 + - 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_img, out_img, row_filter, and col_filter must all contain float type elements. - is_same_object(in_img, out_img) == false - row_filter.size() != 0 @@ -196,11 +202,13 @@ 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::has_alpha == false - - pixel_traits::has_alpha == false - - pixel_traits::grayscale == true + - 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_img and out_img do not contain pixels with an alpha channel. That is, + pixel_traits::has_alpha is false for the pixels in these objects. + - out_img contains grayscale pixels. - is_same_object(in_img, out_img) == false - T must be some scalar type - scale != 0 @@ -244,8 +252,8 @@ namespace dlib ); /*! requires - - in_image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits must be defined + - in_image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h - T and U should be scalar types - shrink_rect(get_rect(img),1).contains(c,r) - shrink_rect(get_rect(img),1).contains(c+NC-1,r+NR-1) @@ -281,8 +289,10 @@ namespace dlib ); /*! requires - - in_image_type == is an implementation of array2d/array2d_kernel_abstract.h - - pixel_traits::rgb == true + - in_image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h + - img must contain RGB pixels, that is pixel_traits::rgb == true for the pixels + in img. - T should be a struct with .red .green and .blue members. - U should be a scalar type - shrink_rect(get_rect(img),1).contains(c,r) @@ -350,10 +360,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::has_alpha == false - - pixel_traits::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 + - in_img and out_img do not contain pixels with an alpha channel. That is, + pixel_traits::has_alpha is false for the pixels in these objects. - is_same_object(in_img, out_img) == false - sigma > 0 - max_size > 0 @@ -365,7 +377,7 @@ namespace dlib results are stored into #out_img. - Pixel values are stored into out_img using the assign_pixel() function and therefore any applicable color space conversion or value saturation is performed. - - if (pixel_traits::grayscale == false) then + - if (in_img doesn't contain grayscale pixels) then - The filter is applied to each color channel independently. - Pixels close enough to the edge of in_img to not have the filter still fit inside the image are set to zero. @@ -388,10 +400,10 @@ namespace dlib requires - out.nr() == img.nr() - out.nc() == img.nc() - - image_type1 == an implementation of array2d/array2d_kernel_abstract.h - and it must contain a scalar type - - image_type2 == an implementation of array2d/array2d_kernel_abstract.h - and it must contain a scalar type + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h and it must contain grayscale pixels. + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h and it must contain grayscale pixels. - is_same_object(img,out) == false ensures - for all valid r and c: @@ -413,10 +425,10 @@ namespace dlib ); /*! requires - - image_type1 == an implementation of array2d/array2d_kernel_abstract.h - and it must contain a scalar type - - image_type2 == an implementation of array2d/array2d_kernel_abstract.h - and it must contain a scalar type + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h and it must contain grayscale pixels. + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h and it must contain grayscale pixels. - is_same_object(img,out) == false ensures - #out.nr() == img.nr() @@ -438,16 +450,16 @@ namespace dlib image_type2& out, const long width, const long height, - const typename image_type1::type& thresh + const typename image_traits::pixel_type& thresh ); /*! requires - out.nr() == img.nr() - out.nc() == img.nc() - - image_type1 == an implementation of array2d/array2d_kernel_abstract.h - and it must contain a scalar type - - image_type2 == an implementation of array2d/array2d_kernel_abstract.h - and it must contain a scalar type + - image_type1 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h and it must contain grayscale pixels. + - image_type2 == an image object that implements the interface defined in + dlib/image_processing/generic_image.h and it must contain grayscale pixels. - is_same_object(img,out) == false - width > 0 && height > 0 ensures diff --git a/dlib/image_transforms/thresholding.h b/dlib/image_transforms/thresholding.h index 34b4189fb..52cf05bdd 100644 --- a/dlib/image_transforms/thresholding.h +++ b/dlib/image_transforms/thresholding.h @@ -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::basic_pixel_type thresh + const in_image_type& in_img_, + out_image_type& out_img_, + typename pixel_traits::pixel_type>::basic_pixel_type thresh ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); + COMPILE_TIME_ASSERT(pixel_traits::pixel_type>::grayscale); + + const_image_view in_img(in_img_); + image_view 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::basic_pixel_type thresh + typename pixel_traits::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::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::is_unsigned == true ); - COMPILE_TIME_ASSERT( pixel_traits::is_unsigned == true ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::is_unsigned == true ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::is_unsigned == true ); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); + COMPILE_TIME_ASSERT(pixel_traits::pixel_type>::grayscale); + + const_image_view in_img(in_img_); + image_view 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::basic_pixel_type lower_thresh, - typename pixel_traits::basic_pixel_type upper_thresh + const in_image_type& in_img_, + out_image_type& out_img_, + typename pixel_traits::pixel_type>::basic_pixel_type lower_thresh, + typename pixel_traits::pixel_type>::basic_pixel_type upper_thresh ) { - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); - COMPILE_TIME_ASSERT( pixel_traits::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); + COMPILE_TIME_ASSERT( pixel_traits::pixel_type>::has_alpha == false ); - COMPILE_TIME_ASSERT(pixel_traits::grayscale); + COMPILE_TIME_ASSERT(pixel_traits::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_img(in_img_); + image_view 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::basic_pixel_type p; + typename pixel_traits::pixel_type>::basic_pixel_type p; assign_pixel(p,in_img[r][c]); if (p >= upper_thresh) { diff --git a/dlib/image_transforms/thresholding_abstract.h b/dlib/image_transforms/thresholding_abstract.h index 22498be11..0fd27aca1 100644 --- a/dlib/image_transforms/thresholding_abstract.h +++ b/dlib/image_transforms/thresholding_abstract.h @@ -22,15 +22,15 @@ namespace dlib void threshold_image ( const in_image_type& in_img, out_image_type& out_img, - typename pixel_traits::basic_pixel_type thresh + typename pixel_traits::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::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::has_alpha == false + - pixel_traits::pixel_type>::grayscale == true + - pixel_traits::pixel_type>::has_alpha == false + - pixel_traits::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::basic_pixel_type thresh + typename pixel_traits::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::max() <= 65535 - - pixel_traits::has_alpha == false - - pixel_traits::is_unsigned == true - - pixel_traits::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::is_unsigned == true + - pixel_traits::pixel_type>::max() <= 65535 + - pixel_traits::pixel_type>::has_alpha == false + - pixel_traits::pixel_type>::is_unsigned == true + - pixel_traits::pixel_type>::grayscale == true + - pixel_traits::pixel_type>::has_alpha == false + - pixel_traits::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::basic_pixel_type lower_thresh, - typename pixel_traits::basic_pixel_type upper_thresh + typename pixel_traits::pixel_type>::basic_pixel_type lower_thresh, + typename pixel_traits::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::grayscale == true - - pixel_traits::has_alpha == false - - pixel_traits::has_alpha == false + - pixel_traits::pixel_type>::grayscale == true + - pixel_traits::pixel_type>::has_alpha == false + - pixel_traits::pixel_type>::has_alpha == false - lower_thresh <= upper_thresh - is_same_object(in_img, out_img) == false ensures diff --git a/dlib/matrix.h b/dlib/matrix.h index bb5926e71..d2ae69afb 100644 --- a/dlib/matrix.h +++ b/dlib/matrix.h @@ -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" diff --git a/dlib/matrix/matrix_generic_image.h b/dlib/matrix/matrix_generic_image.h new file mode 100644 index 000000000..855885368 --- /dev/null +++ b/dlib/matrix/matrix_generic_image.h @@ -0,0 +1,99 @@ +// 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 > + { + typedef T pixel_type; + }; + + template < + typename T, + long NR, + long NC, + typename MM + > + inline long num_rows( const matrix& img) { return img.nr(); } + + template < + typename T, + long NR, + long NC, + typename MM + > + inline long num_columns( const matrix& img) { return img.nc(); } + + template < + typename T, + long NR, + long NC, + typename MM + > + inline void set_image_size( + matrix& img, + long rows, + long cols + ) { img.set_size(rows,cols); } + + template < + typename T, + long NR, + long NC, + typename MM + > + inline void* image_data( + matrix& 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& 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& img + ) + { + return img.nc()*sizeof(T); + } + +} + +#endif // DLIB_MATRIX_GENERIC_iMAGE_H__ + + diff --git a/dlib/matrix/matrix_mat.h b/dlib/matrix/matrix_mat.h index d716603d2..d9d3e61dc 100644 --- a/dlib/matrix/matrix_mat.h +++ b/dlib/matrix/matrix_mat.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 - struct op_array2d_to_mat : does_not_alias + template + 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 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 > > mat ( - const array2d& 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,matrix_op::pixel_type> > >::type mat ( + const image_type& img ) { - typedef op_array2d_to_mat > op; - return matrix_op(op(array)); + typedef op_image_to_mat::pixel_type> op; + return matrix_op(op(img)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_image_view_to_mat : does_not_alias + { + op_image_view_to_mat( const image_view& img) : imgview(img){} + + typedef typename image_traits::pixel_type pixel_type; + + const image_view& 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 > mat ( + const image_view& img + ) + { + typedef op_image_view_to_mat op; + return matrix_op(op(img)); + } + +// ---------------------------------------------------------------------------------------- + + template + struct op_const_image_view_to_mat : does_not_alias + { + op_const_image_view_to_mat( const const_image_view& img) : imgview(img){} + + typedef typename image_traits::pixel_type pixel_type; + + const const_image_view& 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 > mat ( + const const_image_view& img + ) + { + typedef op_const_image_view_to_mat op; + return matrix_op(op(img)); } // ---------------------------------------------------------------------------------------- @@ -418,6 +492,42 @@ namespace dlib return array; } +// ---------------------------------------------------------------------------------------- + + template + 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 > > mat ( + const array2d& array + ) + { + typedef op_array2d_to_mat > op; + return matrix_op(op(array)); + } + template < typename array_type > diff --git a/dlib/matrix/matrix_mat_abstract.h b/dlib/matrix/matrix_mat_abstract.h index a80623a4c..19927b466 100644 --- a/dlib/matrix/matrix_mat_abstract.h +++ b/dlib/matrix/matrix_mat_abstract.h @@ -28,14 +28,20 @@ namespace dlib // ---------------------------------------------------------------------------------------- template < - typename T, - typename MM + typename image_type > const matrix_exp mat ( - const array2d& 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() diff --git a/dlib/opencv/cv_image.h b/dlib/opencv/cv_image.h index 608d89afa..3d8ef882a 100644 --- a/dlib/opencv/cv_image.h +++ b/dlib/opencv/cv_image.h @@ -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 + struct image_traits > + { + typedef T pixel_type; + }; + + template + inline long num_rows( const cv_image& img) { return img.nr(); } + template + inline long num_columns( const cv_image& img) { return img.nc(); } + + template + inline void* image_data( + cv_image& img + ) + { + if (img.size() != 0) + return &img[0][0]; + else + return 0; + } + + template + inline const void* image_data( + const cv_image& img + ) + { + if (img.size() != 0) + return &img[0][0]; + else + return 0; + } + + template + inline long width_step( + const cv_image& img + ) + { + return img.width_step(); + } + +// ---------------------------------------------------------------------------------------- + } #endif // DLIB_CvIMAGE_H_ diff --git a/dlib/opencv/to_open_cv.h b/dlib/opencv/to_open_cv.h index 221a4eaa7..92bf34c5a 100644 --- a/dlib/opencv/to_open_cv.h +++ b/dlib/opencv/to_open_cv.h @@ -19,49 +19,20 @@ namespace dlib image_type& img ) { - if (img.size() == 0) + if (image_size(img) == 0) return cv::Mat(); - typedef typename image_type::type type; + typedef typename image_traits::pixel_type type; if (pixel_traits::num == 1) { - return cv::Mat(img.nr(), img.nc(), cv::DataType::type, (void*)&img[0][0], img.width_step()); + return cv::Mat(num_rows(img), num_columns(img), cv::DataType::type, image_data(img), width_step(img)); } else { int depth = sizeof(typename pixel_traits::basic_pixel_type)*8; int channels = pixel_traits::num; int thetype = CV_MAKETYPE(depth, channels); - return cv::Mat(img.nr(), img.nc(), thetype, (void*)&img[0][0], img.width_step()); - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - long NR, - long NC, - typename MM - > - cv::Mat toMat ( - matrix& img - ) - { - if (img.size() == 0) - return cv::Mat(); - - typedef T type; - if (pixel_traits::num == 1) - { - return cv::Mat(img.nr(), img.nc(), cv::DataType::type, (void*)&img(0,0), img.nc()*sizeof(type)); - } - else - { - int depth = sizeof(typename pixel_traits::basic_pixel_type)*8; - int channels = pixel_traits::num; - int thetype = CV_MAKETYPE(depth, channels); - return cv::Mat(img.nr(), img.nc(), thetype, (void*)&img(0,0), img.nc()*sizeof(type)); + return cv::Mat(num_rows(img), num_columns(img), thetype, image_data(img), width_step(img)); } } diff --git a/dlib/opencv/to_open_cv_abstract.h b/dlib/opencv/to_open_cv_abstract.h index a61dff8ed..cb55e2690 100644 --- a/dlib/opencv/to_open_cv_abstract.h +++ b/dlib/opencv/to_open_cv_abstract.h @@ -15,9 +15,10 @@ namespace dlib ); /*! requires - - image_type == an implementation of dlib/array2d/array2d_kernel_abstract.h or - a dlib::matrix object which uses a row_major_layout. - - pixel_traits is defined + - image_type == an image object that implements the interface defined in + dlib/image_processing/generic_image.h or a dlib::matrix object which uses a + row_major_layout. + - pixel_traits is defined for the contents of img. ensures - returns an OpenCV Mat object which represents the same image as img. This is done by setting up the Mat object to point to the same memory as img.