Commit fa2499d8 authored by Davis King's avatar Davis King
Browse files

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

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

Any user code that was using array2d objects to represent images will still
work.  However, this change makes it so that users can use their own custom
image objects with dlib by simply implementing a few global functions for their
image object.
parent dc0fd24d
......@@ -127,8 +127,8 @@ namespace dlib
) const;
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- loads the PNG image stored in this object into img
!*/
......@@ -146,8 +146,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- performs: png_loader(file_name).get_image(image);
!*/
......
// 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<image_type>
{
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<typename image_traits<image_type>::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 <typename image_type>
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<image_type>::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<image_type>::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<unsigned long>(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 <typename image_type>
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<image_type>::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<unsigned long>(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 <typename image_type>
image_view<image_type> make_image_view ( image_type& img)
{ return image_view<image_type>(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 <typename image_type>
const_image_view<image_type> make_image_view (const image_type& img)
{ return const_image_view<image_type>(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 <typename image_type>
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 <typename image_type>
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 <typename image_type>
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__
......@@ -589,8 +589,6 @@ namespace dlib
feats.set_size(levels);
typedef typename image_type::type pixel_type;
typedef typename image_type::mem_manager_type mem_manager_type;
// build our feature pyramid
fe(img, feats[0], cell_size,filter_rows_padding,filter_cols_padding);
......@@ -600,7 +598,7 @@ namespace dlib
if (feats.size() > 1)
{
array2d<pixel_type,mem_manager_type> temp1, temp2;
image_type temp1, temp2;
pyr(img, temp1);
fe(temp1, feats[1], cell_size,filter_rows_padding,filter_cols_padding);
swap(temp1,temp2);
......
......@@ -56,8 +56,8 @@ namespace dlib
for (unsigned long i = 0; i < images.size(); ++i)
{
if (images[0].nr() != images[i].nr() ||
images[0].nc() != images[i].nc())
if (num_rows(images[0]) != num_rows(images[i]) ||
num_columns(images[0]) != num_columns(images[i]))
return false;
}
......@@ -93,7 +93,7 @@ namespace dlib
#endif
typedef typename image_array_type::type::type pixel_type;
typedef typename image_traits<typename image_array_type::type>::pixel_type pixel_type;
typedef typename promote<pixel_type>::type ptype;
ptype temp = 0;
......@@ -151,7 +151,7 @@ namespace dlib
);
}
#endif
typedef typename image_array_type::type::type pixel_type;
typedef typename image_traits<typename image_array_type::type>::pixel_type pixel_type;
typedef typename promote<pixel_type>::type ptype;
ptype temp = 0;
......@@ -190,12 +190,13 @@ namespace dlib
>
void find_points_above_thresh (
std::vector<std::pair<double, point> >& dets,
const image_type& img,
const image_type& img_,
const double thresh,
const unsigned long max_dets
)
{
typedef typename image_type::type ptype;
const_image_view<image_type> img(img_);
typedef typename image_traits<image_type>::pixel_type ptype;
dets.clear();
if (max_dets == 0)
......@@ -269,7 +270,7 @@ namespace dlib
typedef typename image_array_type::type::type pixel_type;
typedef typename image_traits<typename image_array_type::type>::pixel_type pixel_type;
typedef typename promote<pixel_type>::type ptype;
array2d<ptype> accum(images[0].nr(), images[0].nc());
......@@ -338,7 +339,7 @@ namespace dlib
if (movable_rects.size() == 0 && fixed_rects.size() == 0)
return;
typedef typename image_array_type::type::type pixel_type;
typedef typename image_traits<typename image_array_type::type>::pixel_type pixel_type;
typedef typename promote<pixel_type>::type ptype;
array2d<ptype> accum(images[0].nr(), images[0].nc());
......
......@@ -21,7 +21,8 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h
ensures
- if (all elements of images have the same dimensions (i.e.
for all i and j: get_rect(images[i]) == get_rect(images[j]))) then
......@@ -43,8 +44,9 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h. Moreover, these objects must
contain a scalar pixel type (e.g. int rather than rgb_pixel)
- all_images_same_size(images) == true
- for all valid i: rects[i].first < images.size()
(i.e. all the rectangles must reference valid elements of images)
......@@ -70,8 +72,9 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h. Moreover, these objects must
contain a scalar pixel type (e.g. int rather than rgb_pixel)
- all_images_same_size(images) == true
- center(window) == point(0,0)
- for all valid i:
......@@ -109,8 +112,9 @@ namespace dlib
);
/*!
requires
- image_type == an implementation of array2d/array2d_kernel_abstract.h
- image_type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h. Moreover, these it must contain a
scalar pixel type (e.g. int rather than rgb_pixel)
ensures
- #dets == a list of points from img which had pixel values >= thresh.
- Specifically, we have:
......@@ -142,8 +146,9 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h. Moreover, these objects must
contain a scalar pixel type (e.g. int rather than rgb_pixel)
- images.size() > 0
- rects.size() > 0
- all_images_same_size(images) == true
......@@ -179,8 +184,9 @@ namespace dlib
/*!
requires
- image_array_type == an implementation of array/array_kernel_abstract.h
- image_array_type::type == an implementation of array2d/array2d_kernel_abstract.h
- image_array_type::type::type == a scalar pixel type (e.g. int rather than rgb_pixel)
- image_array_type::type == an image object that implements the interface
defined in dlib/image_processing/generic_image.h. Moreover, these objects must
contain a scalar pixel type (e.g. int rather than rgb_pixel)
- images.size() > 0
- all_images_same_size(images) == true
- center(window) == point(0,0)
......
......@@ -10,6 +10,7 @@
#include "../array2d.h"
#include <vector>
#include "full_object_detection.h"
#include "../image_processing/generic_image.h"
namespace dlib
{
......
......@@ -127,9 +127,9 @@ namespace dlib
- image_type must be a type with the following properties:
- image_type is default constructable.
- image_type is swappable by the global swap() function.
- image_type logically represents some kind of image and therefore
has .nr() and .nc() member functions. .nr() should return the
number of rows while .nc() returns the number of columns.
- image_type logically represents some kind of image and therefore its
number of rows and columns can be queried via num_rows(img) and
num_columns(img) respectively.
- image_type objects can be loaded into Feature_extractor_type
objects via Feature_extractor_type::load().
- image_type objects can be used with Pyramid_type. That is,
......
......@@ -33,7 +33,7 @@ namespace dlib
template <
typename image_type,
bool grayscale = pixel_traits<typename image_type::type>::grayscale
bool grayscale = pixel_traits<typename image_traits<image_type>::pixel_type>::grayscale
>
struct save_bmp_helper;
......@@ -42,10 +42,11 @@ namespace dlib
struct save_bmp_helper<image_type,false>
{
static void save_bmp (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
// we are going to write out a 24bit color image.
byte_orderer::kernel_1a bo;
......@@ -133,10 +134,11 @@ namespace dlib
struct save_bmp_helper<image_type,true>
{
static void save_bmp (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
// we are going to write out an 8bit color image.
byte_orderer::kernel_1a bo;
......@@ -256,20 +258,9 @@ namespace dlib
namespace dng_helpers_namespace
{
template <
typename image_type,
int pixel_type = static_switch <
pixel_traits<typename image_type::type>::grayscale && sizeof(typename image_type::type) == 1,
pixel_traits<typename image_type::type>::rgb,
pixel_traits<typename image_type::type>::hsi,
false,
pixel_traits<typename image_type::type>::rgb_alpha,
false,
pixel_traits<typename image_type::type>::grayscale && sizeof(typename image_type::type) != 1 &&
!is_float_type<typename image_type::type>::value,
is_float_type<typename image_type::type>::value
>::value
typename enabled = void
>
struct save_dng_helper;
......@@ -279,13 +270,14 @@ namespace dlib
typedef entropy_encoder_model<256,encoder_type>::kernel_4a eem_exp_type;
template <typename image_type >
struct save_dng_helper<image_type, grayscale_float>
struct save_dng_helper<image_type, typename enable_if<is_float_type<typename image_traits<image_type>::pixel_type> >::type >
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -334,14 +326,24 @@ namespace dlib
};
template <typename image_type>
struct is_non_float_non8bit_grayscale
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::grayscale &&
sizeof(pixel_type) != 1 &&
!is_float_type<pixel_type>::value;
};
template <typename image_type >
struct save_dng_helper<image_type, grayscale_16bit>
struct save_dng_helper<image_type, typename enable_if<is_non_float_non8bit_grayscale<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -375,15 +377,22 @@ namespace dlib
}
};
template <typename image_type>
struct is_8bit_grayscale
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::grayscale && sizeof(pixel_type) == 1;
};
template <typename image_type>
struct save_dng_helper<image_type, grayscale>
struct save_dng_helper<image_type, typename enable_if<is_8bit_grayscale<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -415,13 +424,21 @@ namespace dlib
};
template <typename image_type>
struct save_dng_helper<image_type,rgb>
struct is_rgb_image
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::rgb;
};
template <typename image_type>
struct save_dng_helper<image_type,typename enable_if<is_rgb_image<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -480,13 +497,21 @@ namespace dlib
};
template <typename image_type>
struct save_dng_helper<image_type,rgb_alpha>
struct is_rgb_alpha_image
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::rgb_alpha;
};
template <typename image_type>
struct save_dng_helper<image_type,typename enable_if<is_rgb_alpha_image<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......@@ -547,13 +572,21 @@ namespace dlib
};
template <typename image_type>
struct save_dng_helper<image_type,hsi>
struct is_hsi_image
{
typedef typename image_traits<image_type>::pixel_type pixel_type;
const static bool value = pixel_traits<pixel_type>::hsi;
};
template <typename image_type>
struct save_dng_helper<image_type,typename enable_if<is_hsi_image<image_type> >::type>
{
static void save_dng (
const image_type& image,
const image_type& image_,
std::ostream& out
)
{
const_image_view<image_type> image(image_);
out.write("DNG",3);
unsigned long version = 1;
serialize(version,out);
......
......@@ -29,9 +29,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any kind of matrix expression.
ensures
- writes the image to the out stream in the Microsoft Windows BMP format.
- image[0][0] will be in the upper left corner of the image.
......@@ -58,9 +57,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any kind of matrix expression.
ensures
- opens the file indicated by file_name with an output file stream named fout
and performs:
......@@ -85,9 +83,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any kind of matrix expression.
ensures
- writes the image to the out stream in the dlib dng format.
- image[0][0] will be in the upper left corner of the image.
......@@ -114,9 +111,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any kind of matrix expression.
ensures
- opens the file indicated by file_name with an output file stream named fout
and performs:
......
......@@ -41,10 +41,12 @@ namespace dlib
typename image_type
>
typename disable_if<is_matrix<image_type> >::type save_png(
const image_type& img,
const image_type& img_,
const std::string& file_name
)
{
const_image_view<image_type> img(img_);
// make sure requires clause is not broken
DLIB_CASSERT(img.size() != 0,
"\t save_png()"
......@@ -62,7 +64,7 @@ namespace dlib
COMPILE_TIME_ASSERT(sizeof(image_type) == 0);
#else
std::vector<unsigned char*> row_pointers(img.nr());
typedef typename image_type::type pixel_type;
typedef typename image_traits<image_type>::pixel_type pixel_type;
if (is_same_type<rgb_pixel,pixel_type>::value)
{
......@@ -82,7 +84,7 @@ namespace dlib
{
// convert from HSI to RGB (Or potentially RGB pixels that aren't laid out as R G B)
array2d<rgb_pixel> temp_img;
assign_image(temp_img, img);
assign_image(temp_img, img_);
for (unsigned long i = 0; i < row_pointers.size(); ++i)
row_pointers[i] = (unsigned char*)(&temp_img[i][0]);
......@@ -92,7 +94,7 @@ namespace dlib
{
// convert from RGBA pixels that aren't laid out as R G B A
array2d<rgb_alpha_pixel> temp_img;
assign_image(temp_img, img);
assign_image(temp_img, img_);
for (unsigned long i = 0; i < row_pointers.size(); ++i)
row_pointers[i] = (unsigned char*)(&temp_img[i][0]);
......@@ -120,7 +122,7 @@ namespace dlib
{
// convert from whatever this is to 16bit grayscale
array2d<dlib::uint16> temp_img;
assign_image(temp_img, img);
assign_image(temp_img, img_);
for (unsigned long i = 0; i < row_pointers.size(); ++i)
row_pointers[i] = (unsigned char*)(&temp_img[i][0]);
......
......@@ -19,9 +19,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or a matrix expression
- image.size() != 0
ensures
- writes the image to the file indicated by file_name in the PNG (Portable Network Graphics)
......
......@@ -14,52 +14,34 @@ namespace dlib
template <
typename dest_image_type,
typename src_pixel_type
typename src_image_type
>
typename enable_if<is_matrix<dest_image_type> >::type impl_assign_single_pixel (
dest_image_type& img,
long r,
long c,
const src_pixel_type& pix
void impl_assign_image (
image_view<dest_image_type>& dest,
const src_image_type& src
)
{
assign_pixel(img(r,c), pix);
}
template <
typename dest_image_type,
typename src_pixel_type
>
typename disable_if<is_matrix<dest_image_type> >::type impl_assign_single_pixel (
dest_image_type& img,
long r,
long c,
const src_pixel_type& pix
)
dest.set_size(src.nr(),src.nc());
for (long r = 0; r < src.nr(); ++r)
{
assign_pixel(img[r][c], pix);
for (long c = 0; c < src.nc(); ++c)
{
assign_pixel(dest[r][c], src(r,c));
}
}
}
// ----------------------------------------------------------------------------------------
template <
typename dest_image_type,
typename src_image_type
>
void impl_assign_image (
dest_image_type& dest,
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_image_type> 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_image_type>& dest,
const src_image_type& src,
const double thresh = 4
const double thresh
)
{
DLIB_ASSERT( thresh > 0,
......@@ -96,12 +78,15 @@ namespace dlib
<< "\n\t thresh: " << thresh
);
typedef typename image_traits<dest_image_type>::pixel_type dest_pixel;
// If the destination has a dynamic range big enough to contain the source image data then just do a
// regular assign_image()
if (pixel_traits<typename dest_image_type::type>::max() >= pixel_traits<typename src_image_type::type>::max() &&
pixel_traits<typename dest_image_type::type>::min() <= pixel_traits<typename src_image_type::type>::min() )
if (pixel_traits<dest_pixel>::max() >= pixel_traits<typename src_image_type::type>::max() &&
pixel_traits<dest_pixel>::min() <= pixel_traits<typename src_image_type::type>::min() )
{
assign_image(dest, src);
impl_assign_image(dest, src);
return;
}
......@@ -112,7 +97,7 @@ namespace dlib
if (src.size() == 1)
{
impl_assign_single_pixel(dest,0,0, src(0,0));
impl_assign_image(dest, src);
return;
}
......@@ -131,8 +116,8 @@ namespace dlib
{
// If the destination has a dynamic range big enough to contain the source image data then just do a
// regular assign_image()
if (pixel_traits<typename dest_image_type::type>::max() >= rs.max() &&
pixel_traits<typename dest_image_type::type>::min() <= rs.min() )
if (pixel_traits<dest_pixel>::max() >= rs.max() &&
pixel_traits<dest_pixel>::min() <= rs.min() )
{
impl_assign_image(dest, src);
return;
......@@ -145,8 +130,8 @@ namespace dlib
const double lower = std::max(rs.mean() - thresh*rs.stddev(), rs.min());
const double dest_min = pixel_traits<typename dest_image_type::type>::min();
const double dest_max = pixel_traits<typename dest_image_type::type>::max();
const double dest_min = pixel_traits<dest_pixel>::min();
const double dest_max = pixel_traits<dest_pixel>::max();
const double scale = (upper!=lower)? ((dest_max - dest_min) / (upper - lower)) : 0;
......@@ -156,11 +141,25 @@ namespace dlib
{
const double val = get_pixel_intensity(src(r,c)) - lower;
impl_assign_single_pixel(dest,r,c, scale*val + dest_min);
assign_pixel(dest[r][c], scale*val + dest_min);
}
}
}
template <
typename dest_image_type,
typename src_image_type
>
void impl_assign_image_scaled (
dest_image_type& dest_,
const src_image_type& src,
const double thresh
)
{
image_view<dest_image_type> dest(dest_);
impl_assign_image_scaled(dest, src, thresh);
}
template <
typename dest_image_type,
typename src_image_type
......@@ -185,7 +184,7 @@ namespace dlib
typename src_pixel_type
>
void assign_all_pixels (
dest_image_type& dest_img,
image_view<dest_image_type>& dest_img,
const src_pixel_type& src_pixel
)
{
......@@ -198,16 +197,31 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template <
typename dest_image_type,
typename src_pixel_type
>
void assign_all_pixels (
dest_image_type& dest_img_,
const src_pixel_type& src_pixel
)
{
image_view<dest_image_type> dest_img(dest_img_);
assign_all_pixels(dest_img, src_pixel);
}
// ----------------------------------------------------------------------------------------
template <
typename image_type
>
void assign_border_pixels (
image_type& img,
image_view<image_type>& img,
long x_border_size,
long y_border_size,
const typename image_type::type& p
const typename image_traits<image_type>::pixel_type& p
)
{
DLIB_ASSERT( x_border_size >= 0 && y_border_size >= 0,
......@@ -251,6 +265,20 @@ namespace dlib
}
}
template <
typename image_type
>
void assign_border_pixels (
image_type& img_,
long x_border_size,
long y_border_size,
const typename image_traits<image_type>::pixel_type& p
)
{
image_view<image_type> img(img_);
assign_border_pixels(img, x_border_size, y_border_size, p);
}
// ----------------------------------------------------------------------------------------
template <
......@@ -269,7 +297,7 @@ namespace dlib
<< "\n\ty_border_size: " << y_border_size
);
typename image_type::type zero_pixel;
typename image_traits<image_type>::pixel_type zero_pixel;
assign_pixel_intensity(zero_pixel, 0);
assign_border_pixels(img, x_border_size, y_border_size, zero_pixel);
}
......@@ -280,7 +308,30 @@ namespace dlib
typename image_type
>
void zero_border_pixels (
image_type& img,
image_view<image_type>& img,
long x_border_size,
long y_border_size
)
{
DLIB_ASSERT( x_border_size >= 0 && y_border_size >= 0,
"\tvoid zero_border_pixels(img, p, border_size)"
<< "\n\tYou have given an invalid border_size"
<< "\n\tx_border_size: " << x_border_size
<< "\n\ty_border_size: " << y_border_size
);
typename image_traits<image_type>::pixel_type zero_pixel;
assign_pixel_intensity(zero_pixel, 0);
assign_border_pixels(img, x_border_size, y_border_size, zero_pixel);
}
// ----------------------------------------------------------------------------------------
template <
typename image_type
>
void zero_border_pixels (
image_view<image_type>& img,
rectangle inside
)
{
......@@ -307,6 +358,20 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template <
typename image_type
>
void zero_border_pixels (
image_type& img_,
const rectangle& inside
)
{
image_view<image_type> img(img_);
zero_border_pixels(img, inside);
}
// ----------------------------------------------------------------------------------------
}
......
......@@ -20,12 +20,11 @@ namespace dlib
);
/*!
requires
- src_image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix or something convertible to a matrix via mat()
- dest_image_type == is an implementation of array2d/array2d_kernel_abstract.h or
is a dlib::matrix.
- pixel_traits<typename src_image_type::type> is defined
- pixel_traits<typename dest_image_type::type> is defined
- src_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any object convertible to a matrix
via mat().
- dest_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view.
ensures
- #dest_img.nc() == src_img.nc()
- #dest_img.nr() == src_img.nr()
......@@ -47,12 +46,11 @@ namespace dlib
);
/*!
requires
- src_image_type == is an implementation of array2d/array2d_kernel_abstract.h or
a dlib::matrix or something convertible to a matrix via mat()
- dest_image_type == is an implementation of array2d/array2d_kernel_abstract.h or
is a dlib::matrix.
- pixel_traits<typename src_image_type::type> is defined
- pixel_traits<typename dest_image_type::type> is defined
- src_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or any object convertible to a matrix
via mat().
- dest_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view.
- thresh > 0
ensures
- #dest_img.nc() == src_img.nc()
......@@ -77,8 +75,8 @@ namespace dlib
the following mapping:
let SRC_UPPER = min(M + thresh*D, max(mat(src_img)))
let SRC_LOWER = max(M - thresh*D, min(mat(src_img)))
let DEST_UPPER = pixel_traits<dest_image_type::type>::max()
let DEST_LOWER = pixel_traits<dest_image_type::type>::min()
let DEST_UPPER = pixel_traits<image_traits<dest_image_type>::pixel_type>::max()
let DEST_LOWER = pixel_traits<image_traits<dest_image_type>::pixel_type>::min()
MAPPING: [SRC_LOWER, SRC_UPPER] -> [DEST_LOWER, DEST_UPPER]
......@@ -101,8 +99,8 @@ namespace dlib
);
/*!
requires
- dest_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename dest_image_type::type> is defined
- dest_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view.
- pixel_traits<src_pixel_type> is defined
ensures
- #dest_img.nc() == dest_img.nc()
......@@ -122,11 +120,12 @@ namespace dlib
image_type& img,
long x_border_size,
long y_border_size,
const typename image_type::type& p
const typename image_traits<image_type>::pixel_type& p
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view
- x_border_size >= 0
- y_border_size >= 0
ensures
......@@ -151,10 +150,10 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view
- x_border_size >= 0
- y_border_size >= 0
- pixel_traits<typename image_type::type> is defined
ensures
- #img.nc() == img.nc()
- #img.nr() == img.nr()
......@@ -176,8 +175,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename image_type::type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h or an image_view
ensures
- #img.nc() == img.nc()
- #img.nr() == img.nr()
......
......@@ -25,7 +25,7 @@ namespace dlib
const static long NC = 0;
typedef rgb_pixel type;
typedef const rgb_pixel const_ret_type;
typedef typename T::mem_manager_type mem_manager_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const
......@@ -47,8 +47,8 @@ namespace dlib
}
}
long nr () const { return img.nr(); }
long nc () const { return img.nc(); }
long nr () const { return num_rows(img); }
long nc () const { return num_columns(img); }
};
template <
......@@ -84,7 +84,7 @@ namespace dlib
const static long NC = 0;
typedef rgb_pixel type;
typedef const rgb_pixel const_ret_type;
typedef typename T::mem_manager_type mem_manager_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const
......@@ -107,8 +107,8 @@ namespace dlib
return pix;
}
long nr () const { return img.nr(); }
long nc () const { return img.nc(); }
long nr () const { return num_rows(img); }
long nc () const { return num_columns(img); }
};
template <
......@@ -158,7 +158,7 @@ namespace dlib
const static long NC = 0;
typedef rgb_pixel type;
typedef const rgb_pixel const_ret_type;
typedef typename T::mem_manager_type mem_manager_type;
typedef default_memory_manager mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const
......@@ -203,8 +203,8 @@ namespace dlib
return pix;
}
long nr () const { return img.nr(); }
long nc () const { return img.nc(); }
long nr () const { return num_rows(img); }
long nc () const { return num_columns(img); }
};
template <
......
......@@ -21,9 +21,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- randomly generates a mapping from gray level pixel values
to the RGB pixel space and then uses this mapping to create
......@@ -46,9 +46,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- Interprets img as a grayscale image and returns a new matrix
which represents a colored version of img. In particular, the
......@@ -68,9 +68,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- returns heatmap(img, max(mat(img)), min(mat(img)))
!*/
......@@ -88,9 +88,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- Interprets img as a grayscale image and returns a new matrix which represents
a colored version of img. In particular, the colors will depict img using a
......@@ -110,9 +110,9 @@ namespace dlib
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h, a
dlib::matrix, or something convertible to a matrix via mat().
- pixel_traits<image_type::type> must be defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h, or something convertible to a matrix
via mat().
ensures
- returns jet(img, max(mat(img)), min(mat(img)))
!*/
......
......@@ -23,10 +23,11 @@ namespace dlib
long y1,
long x2,
long y2,
image_type& c,
image_type& c_,
const pixel_type& val
)
{
image_view<image_type> c(c_);
if (x1 == x2)
{
// make sure y1 comes before y2
......@@ -214,11 +215,12 @@ namespace dlib
typename pixel_type
>
void fill_rect (
image_type& img,
image_type& img_,
const rectangle& rect,
const pixel_type& pixel
)
{
image_view<image_type> img(img_);
rectangle area = rect.intersect(get_rect(img));
for (long r = area.top(); r <= area.bottom(); ++r)
......@@ -235,11 +237,11 @@ namespace dlib
template <
typename image_array_type
>
matrix<typename image_array_type::value_type::type> tile_images (
matrix<typename image_traits<typename image_array_type::value_type>::pixel_type> tile_images (
const image_array_type& images
)
{
typedef typename image_array_type::value_type::type T;
typedef typename image_traits<typename image_array_type::value_type>::pixel_type T;
if (images.size() == 0)
return matrix<T>();
......@@ -252,8 +254,8 @@ namespace dlib
long nc = 0;
for (unsigned long i = 0; i < images.size(); ++i)
{
nr = std::max(images[i].nr(), nr);
nc = std::max(images[i].nc(), nc);
nr = std::max(num_rows(images[i]), nr);
nc = std::max(num_columns(images[i]), nc);
}
matrix<T> temp(size_nr*nr, size_nc*nc);
......
......@@ -22,8 +22,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<pixel_type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- #img.nr() == img.nr() && #img.nc() == img.nc()
(i.e. the dimensions of the input image are not changed)
......@@ -48,8 +48,8 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<pixel_type> is defined
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
ensures
- performs draw_line(img, point(x1,y1), point(x2,y2), val)
!*/
......@@ -68,12 +68,13 @@ namespace dlib
);
/*!
requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- pixel_traits<pixel_type> is defined
ensures
- Draws the given rectangle onto the image img. It does this by calling
draw_line() four times to draw the four sides of the rectangle.
- The rectancle is drawn with the color given by val.
- The rectangle is drawn with the color given by val.
- The drawn rectangle will have edges that are thickness pixels wide.
!*/
......@@ -90,6 +91,8 @@ namespace dlib
);
/*!
requires
- image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- pixel_traits<pixel_type> is defined
ensures
- fills the area defined by rect in the given image with the given pixel value.
......@@ -100,13 +103,13 @@ namespace dlib
template <
typename image_array_type
>
matrix<typename image_array_type::value_type::type> tile_images (
matrix<typename image_traits<typename image_array_type::value_type>::pixel_type> tile_images (
const image_array_type& images
);
/*!
requires
- image_array_type is a dlib::array of array2d objects, each containing pixels
with a pixel_traits definition or any type with a compatible interface.
- image_array_type is a dlib::array of image objects where each image object
implements the interface defined in dlib/image_processing/generic_image.h
ensures
- This function takes the given images and tiles them into a single large
square image and returns this new big tiled image. Therefore, it is a useful
......
......@@ -101,19 +101,20 @@ namespace dlib
typename out_image_type
>
void sobel_edge_detector (
const in_image_type& in_img,
out_image_type& horz,
out_image_type& vert
const in_image_type& in_img_,
out_image_type& horz_,
out_image_type& vert_
)
{
COMPILE_TIME_ASSERT(pixel_traits<typename out_image_type::type>::is_unsigned == false);
DLIB_ASSERT( !is_same_object(in_img,horz) && !is_same_object(in_img,vert) &&
!is_same_object(horz,vert),
"\tvoid sobel_edge_detector(in_img, horz, vert)"
typedef typename image_traits<out_image_type>::pixel_type pixel_type;
COMPILE_TIME_ASSERT(pixel_traits<pixel_type>::is_unsigned == false);
DLIB_ASSERT( !is_same_object(in_img_,horz_) && !is_same_object(in_img_,vert_) &&
!is_same_object(horz_,vert_),
"\tvoid sobel_edge_detector(in_img_, horz_, vert_)"
<< "\n\t You can't give the same image as more than one argument"
<< "\n\t is_same_object(in_img,horz): " << is_same_object(in_img,horz)
<< "\n\t is_same_object(in_img,vert): " << is_same_object(in_img,vert)
<< "\n\t is_same_object(horz,vert): " << is_same_object(horz,vert)
<< "\n\t is_same_object(in_img_,horz_): " << is_same_object(in_img_,horz_)
<< "\n\t is_same_object(in_img_,vert_): " << is_same_object(in_img_,vert_)
<< "\n\t is_same_object(horz_,vert_): " << is_same_object(horz_,vert_)
);
......@@ -127,6 +128,11 @@ namespace dlib
const long M = 3;
const long N = 3;
const_image_view<in_image_type> in_img(in_img_);
image_view<out_image_type> horz(horz_);
image_view<out_image_type> vert(vert_);
horz.set_size(in_img.nr(),in_img.nc());
vert.set_size(in_img.nr(),in_img.nc());
......@@ -145,7 +151,7 @@ namespace dlib
{
for (long c = first_col; c < last_col; ++c)
{
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type bp_type;
typedef typename pixel_traits<typename image_traits<in_image_type>::pixel_type>::basic_pixel_type bp_type;
typename promote<bp_type>::type p, horz_temp, vert_temp;
horz_temp = 0;
......@@ -185,12 +191,16 @@ namespace dlib
typename out_image_type
>
void suppress_non_maximum_edges (
const in_image_type& horz,
const in_image_type& vert,
out_image_type& out_img
const in_image_type& horz_,
const in_image_type& vert_,
out_image_type& out_img_
)
{
COMPILE_TIME_ASSERT(is_signed_type<typename in_image_type::type>::value);
const_image_view<in_image_type> horz(horz_);
const_image_view<in_image_type> vert(vert_);
image_view<out_image_type> out_img(out_img_);
COMPILE_TIME_ASSERT(is_signed_type<typename image_traits<in_image_type>::pixel_type>::value);
DLIB_ASSERT( horz.nr() == vert.nr() && horz.nc() == vert.nc(),
"\tvoid suppress_non_maximum_edges(horz, vert, out_img)"
<< "\n\tYou have to give horz and vert gradient images that are the same size"
......@@ -199,11 +209,11 @@ namespace dlib
<< "\n\tvert.nr(): " << vert.nr()
<< "\n\tvert.nc(): " << vert.nc()
);
DLIB_ASSERT( !is_same_object(out_img,horz) && !is_same_object(out_img,vert),
"\tvoid suppress_non_maximum_edges(horz, vert, out_img)"
DLIB_ASSERT( !is_same_object(out_img_,horz_) && !is_same_object(out_img_,vert_),
"\tvoid suppress_non_maximum_edges(horz_, vert_, out_img_)"
<< "\n\t out_img can't be the same as one of the input images."
<< "\n\t is_same_object(out_img,horz): " << is_same_object(out_img,horz)
<< "\n\t is_same_object(out_img,vert): " << is_same_object(out_img,vert)
<< "\n\t is_same_object(out_img_,horz_): " << is_same_object(out_img_,horz_)
<< "\n\t is_same_object(out_img_,vert_): " << is_same_object(out_img_,vert_)
);
using std::min;
......@@ -237,7 +247,7 @@ namespace dlib
{
for (long c = first_col; c < last_col; ++c)
{
typedef typename promote<typename in_image_type::type>::type T;
typedef typename promote<typename image_traits<in_image_type>::pixel_type>::type T;
const T y = horz[r][c];
const T x = vert[r][c];
......
......@@ -45,10 +45,11 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type> must be defined
- pixel_traits<typename out_image_type::type>::is_unsigned == false
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type must use signed grayscale pixels
- is_same_object(in_img,horz) == false
- is_same_object(in_img,vert) == false
- is_same_object(horz,vert) == false
......@@ -79,14 +80,15 @@ namespace dlib
);
/*!
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename out_image_type::type> must be defined
- in_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- out_image_type == an image object that implements the interface defined in
dlib/image_processing/generic_image.h
- horz.nr() == vert.nr()
- horz.nc() == vert.nc()
- is_same_object(out_img, horz) == false
- is_same_object(out_img, vert) == false
- in_image_type::type == A signed scalar type (e.g. int, double, etc.)
- image_traits<in_image_type>::pixel_type == A signed scalar type (e.g. int, double, etc.)
ensures
- #out_img.nr() = horz.nr()
- #out_img.nc() = horz.nc()
......
......@@ -21,24 +21,26 @@ namespace dlib
typename MM
>
void get_histogram (
const in_image_type& in_img,
const in_image_type& in_img_,
matrix<unsigned long,R,C,MM>& hist
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::is_unsigned == true );
typedef typename image_traits<in_image_type>::pixel_type pixel_type;
COMPILE_TIME_ASSERT( pixel_traits<pixel_type>::is_unsigned == true );
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type in_image_basic_pixel_type;
typedef typename pixel_traits<pixel_type>::basic_pixel_type in_image_basic_pixel_type;
COMPILE_TIME_ASSERT( sizeof(in_image_basic_pixel_type) <= 2);
// make sure hist is the right size
if (R == 1)
hist.set_size(1,pixel_traits<typename in_image_type::type>::max()+1);
hist.set_size(1,pixel_traits<pixel_type>::max()+1);
else
hist.set_size(pixel_traits<typename in_image_type::type>::max()+1,1);
hist.set_size(pixel_traits<pixel_type>::max()+1,1);
set_all_elements(hist,0);
const_image_view<in_image_type> in_img(in_img_);
// compute the histogram
for (long r = 0; r < in_img.nr(); ++r)
{
......@@ -57,20 +59,25 @@ namespace dlib
typename out_image_type
>
void equalize_histogram (
const in_image_type& in_img,
out_image_type& out_img
const in_image_type& in_img_,
out_image_type& out_img_
)
{
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::has_alpha == false );
const_image_view<in_image_type> in_img(in_img_);
image_view<out_image_type> out_img(out_img_);
COMPILE_TIME_ASSERT( pixel_traits<typename in_image_type::type>::is_unsigned == true );
COMPILE_TIME_ASSERT( pixel_traits<typename out_image_type::type>::is_unsigned == true );
typedef typename image_traits<in_image_type>::pixel_type in_pixel_type;
typedef typename image_traits<out_image_type>::pixel_type out_pixel_type;
typedef typename pixel_traits<typename in_image_type::type>::basic_pixel_type in_image_basic_pixel_type;
COMPILE_TIME_ASSERT( pixel_traits<in_pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<out_pixel_type>::has_alpha == false );
COMPILE_TIME_ASSERT( pixel_traits<in_pixel_type>::is_unsigned == true );
COMPILE_TIME_ASSERT( pixel_traits<out_pixel_type>::is_unsigned == true );
typedef typename pixel_traits<in_pixel_type>::basic_pixel_type in_image_basic_pixel_type;
COMPILE_TIME_ASSERT( sizeof(in_image_basic_pixel_type) <= 2);
typedef typename out_image_type::type out_pixel_type;
// if there isn't any input image then don't do anything
if (in_img.size() == 0)
......@@ -83,8 +90,9 @@ namespace dlib
unsigned long p;
matrix<unsigned long,1,0,typename in_image_type::mem_manager_type> histogram;
get_histogram(in_img, histogram);
matrix<unsigned long,1,0> histogram;
get_histogram(in_img_, histogram);
in_img = in_img_;
double scale = pixel_traits<out_pixel_type>::max();
if (in_img.size() > histogram(0))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment