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
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "array2d/array2d_kernel.h" #include "array2d/array2d_kernel.h"
#include "array2d/serialize_pixel_overloads.h" #include "array2d/serialize_pixel_overloads.h"
#include "array2d/array2d_generic_image.h"
#endif // DLIB_ARRAY2d_ #endif // DLIB_ARRAY2d_
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_ARRAY2D_GENERIC_iMAGE_H__
#define DLIB_ARRAY2D_GENERIC_iMAGE_H__
#include "array2d_kernel.h"
#include "../image_processing/generic_image.h"
namespace dlib
{
template <typename T, typename mm>
struct image_traits<array2d<T,mm> >
{
typedef T pixel_type;
};
template <typename T, typename mm>
inline long num_rows( const array2d<T,mm>& img) { return img.nr(); }
template <typename T, typename mm>
inline long num_columns( const array2d<T,mm>& img) { return img.nc(); }
template <typename T, typename mm>
inline void set_image_size(
array2d<T,mm>& img,
long rows,
long cols
) { img.set_size(rows,cols); }
template <typename T, typename mm>
inline void* image_data(
array2d<T,mm>& img
)
{
if (img.size() != 0)
return &img[0][0];
else
return 0;
}
template <typename T, typename mm>
inline const void* image_data(
const array2d<T,mm>& img
)
{
if (img.size() != 0)
return &img[0][0];
else
return 0;
}
template <typename T, typename mm>
inline long width_step(
const array2d<T,mm>& img
)
{
return img.width_step();
}
}
#endif // DLIB_ARRAY2D_GENERIC_iMAGE_H__
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <iostream> #include <iostream>
#include "../serialize.h" #include "../serialize.h"
#include "vector.h" #include "vector.h"
#include "../image_processing/generic_image.h"
namespace dlib namespace dlib
{ {
...@@ -645,7 +646,7 @@ namespace dlib ...@@ -645,7 +646,7 @@ namespace dlib
const T& m const T& m
) )
{ {
return rectangle(0, 0, m.nc()-1, m.nr()-1); return rectangle(0, 0, num_columns(m)-1, num_rows(m)-1);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
......
...@@ -715,9 +715,12 @@ namespace dlib ...@@ -715,9 +715,12 @@ namespace dlib
); );
/*! /*!
requires 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 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 (i.e. assuming T represents some kind of rectangular grid, such as
the dlib::matrix or dlib::array2d objects, this function returns the the dlib::matrix or dlib::array2d objects, this function returns the
bounding rectangle for that gridded object.) bounding rectangle for that gridded object.)
......
...@@ -3253,12 +3253,12 @@ namespace dlib ...@@ -3253,12 +3253,12 @@ namespace dlib
// if the new image has a different size when compared to the previous image // if the new image has a different size when compared to the previous image
// then we should readjust the total rectangle size. // 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) 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 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 else
{ {
......
...@@ -66,7 +66,7 @@ namespace dlib ...@@ -66,7 +66,7 @@ namespace dlib
const image_type& img const image_type& img
) )
{ {
COMPILE_TIME_ASSERT( pixel_traits<typename image_type::type>::has_alpha == false ); COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false );
load_impl(mat(img)); load_impl(mat(img));
} }
......
...@@ -103,7 +103,7 @@ namespace dlib ...@@ -103,7 +103,7 @@ namespace dlib
requires requires
- image_type is a dlib::matrix or something convertible to a matrix - image_type is a dlib::matrix or something convertible to a matrix
via mat() via mat()
- pixel_traits<typename image_type::type>::has_alpha == false - pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false
ensures ensures
- if (img.nr() < min_size || img.nc() < min_size) then - if (img.nr() < min_size || img.nc() < min_size) then
- the image is too small so we don't compute anything on it - the image is too small so we don't compute anything on it
......
...@@ -309,7 +309,7 @@ namespace dlib ...@@ -309,7 +309,7 @@ namespace dlib
// use the inverse frequency as the scale for each feature. We also scale // 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 // 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). // 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) for (unsigned long i = 0; i < feat_counts.size(); ++i)
{ {
feat_counts[i] = scale/feat_counts[i]; feat_counts[i] = scale/feat_counts[i];
......
...@@ -82,7 +82,7 @@ namespace dlib ...@@ -82,7 +82,7 @@ namespace dlib
const image_type& img const image_type& img
) )
{ {
COMPILE_TIME_ASSERT( pixel_traits<typename image_type::type>::has_alpha == false ); COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false );
load_impl(mat(img)); load_impl(mat(img));
} }
......
...@@ -158,8 +158,8 @@ namespace dlib ...@@ -158,8 +158,8 @@ namespace dlib
/*! /*!
requires requires
- image_type is a dlib::matrix or something convertible to a matrix - image_type is a dlib::matrix or something convertible to a matrix
via mat() via mat().
- pixel_traits<typename image_type::type>::has_alpha == false - pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false
ensures ensures
- if (img.nr() < min_size || img.nc() < min_size) then - if (img.nr() < min_size || img.nc() < min_size) then
- the image is too small so we don't compute anything on it - the image is too small so we don't compute anything on it
......
...@@ -138,7 +138,7 @@ namespace dlib ...@@ -138,7 +138,7 @@ namespace dlib
const image_type& img const image_type& img
) )
{ {
COMPILE_TIME_ASSERT( pixel_traits<typename image_type::type>::has_alpha == false ); COMPILE_TIME_ASSERT( pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false );
poly_coef.resize(get_num_dimensions()); poly_coef.resize(get_num_dimensions());
des.set_size(get_num_dimensions()); des.set_size(get_num_dimensions());
......
...@@ -166,8 +166,9 @@ namespace dlib ...@@ -166,8 +166,9 @@ namespace dlib
); );
/*! /*!
requires requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h - image_type == an image object that implements the interface defined in
- pixel_traits<typename image_type::type>::has_alpha == false dlib/image_processing/generic_image.h
- pixel_traits<typename image_traits<image_type>::pixel_type>::has_alpha == false
ensures ensures
- Performs the feature extraction described in the WHAT THIS OBJECT REPRESENTS - Performs the feature extraction described in the WHAT THIS OBJECT REPRESENTS
section above. This means after load() finishes you can call (*this)(row,col) section above. This means after load() finishes you can call (*this)(row,col)
......
...@@ -248,7 +248,7 @@ namespace dlib ...@@ -248,7 +248,7 @@ namespace dlib
); );
// Figure out the proper scalar type we should use to work with these pixels. // Figure out the proper scalar type we should use to work with these pixels.
typedef typename pixel_traits<typename image_type::type>::basic_pixel_type bp_type; typedef typename pixel_traits<typename image_traits<image_type>::pixel_type>::basic_pixel_type bp_type;
typedef typename promote<bp_type>::type working_pixel_type; typedef typename promote<bp_type>::type working_pixel_type;
// make an integral image first // make an integral image first
......
...@@ -133,8 +133,10 @@ namespace dlib ...@@ -133,8 +133,10 @@ namespace dlib
requires requires
- max_points > 0 - max_points > 0
- detection_threshold >= 0 - detection_threshold >= 0
- image_type == a type that implements the array2d/array2d_kernel_abstract.h interface - image_type == an image object that implements the interface defined in
- pixel_traits<image_type::type> must be defined dlib/image_processing/generic_image.h
- Let P denote the type of pixel in img, then we require:
- pixel_traits<P>::has_alpha == false
ensures ensures
- This function runs the complete SURF algorithm on the given input image and - This function runs the complete SURF algorithm on the given input image and
returns the points it found. returns the points it found.
......
...@@ -31,10 +31,11 @@ namespace dlib ...@@ -31,10 +31,11 @@ namespace dlib
typename image_type typename image_type
> >
void load_bmp ( void load_bmp (
image_type& image, image_type& image_,
std::istream& in_ std::istream& in_
) )
{ {
image_view<image_type> image(image_);
try try
{ {
unsigned long bytes_read_so_far = 0; unsigned long bytes_read_so_far = 0;
...@@ -550,10 +551,11 @@ namespace dlib ...@@ -550,10 +551,11 @@ namespace dlib
typename image_type typename image_type
> >
void load_dng ( void load_dng (
image_type& image, image_type& image_,
std::istream& in std::istream& in
) )
{ {
image_view<image_type> image(image_);
using namespace dng_helpers_namespace; using namespace dng_helpers_namespace;
try try
{ {
...@@ -788,7 +790,7 @@ namespace dlib ...@@ -788,7 +790,7 @@ namespace dlib
// Only use long double precision if the target image contains long // Only use long double precision if the target image contains long
// doubles because it's slower to use those. // doubles because it's slower to use those.
if (!is_same_type<typename image_type::type,long double>::value) if (!is_same_type<typename image_traits<image_type>::pixel_type,long double>::value)
{ {
double temp = cur; double temp = cur;
assign_pixel(image[r][c],temp); assign_pixel(image[r][c],temp);
......
...@@ -29,8 +29,8 @@ namespace dlib ...@@ -29,8 +29,8 @@ namespace dlib
); );
/*! /*!
requires requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h - image_type == an image object that implements the interface defined in
- pixel_traits<typename image_type::type> is defined dlib/image_processing/generic_image.h
ensures ensures
- #image == the image of the MS Windows BMP file that was available - #image == the image of the MS Windows BMP file that was available
in the input stream in. in the input stream in.
...@@ -61,8 +61,8 @@ namespace dlib ...@@ -61,8 +61,8 @@ namespace dlib
); );
/*! /*!
requires requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h - image_type == an image object that implements the interface defined in
- pixel_traits<typename image_type::type> is defined dlib/image_processing/generic_image.h
ensures ensures
- opens the file indicated by file_name with an input file stream named fin - opens the file indicated by file_name with an input file stream named fin
and performs: and performs:
...@@ -87,8 +87,8 @@ namespace dlib ...@@ -87,8 +87,8 @@ namespace dlib
); );
/*! /*!
requires requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h - image_type == an image object that implements the interface defined in
- pixel_traits<typename image_type::type> is defined dlib/image_processing/generic_image.h
ensures ensures
- #image == the image of the dlib dng file that was available - #image == the image of the dlib dng file that was available
in the input stream in. in the input stream in.
...@@ -119,8 +119,8 @@ namespace dlib ...@@ -119,8 +119,8 @@ namespace dlib
); );
/*! /*!
requires requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h - image_type == an image object that implements the interface defined in
- pixel_traits<typename image_type::type> is defined dlib/image_processing/generic_image.h
ensures ensures
- opens the file indicated by file_name with an input file stream named fin - opens the file indicated by file_name with an input file stream named fin
and performs: and performs:
......
...@@ -25,7 +25,7 @@ namespace dlib ...@@ -25,7 +25,7 @@ namespace dlib
bool is_rgb() const; bool is_rgb() const;
template<typename T> template<typename T>
void get_image( T& t) const void get_image( T& t_) const
{ {
#ifndef DLIB_JPEG_SUPPORT #ifndef DLIB_JPEG_SUPPORT
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
...@@ -36,6 +36,7 @@ namespace dlib ...@@ -36,6 +36,7 @@ namespace dlib
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
COMPILE_TIME_ASSERT(sizeof(T) == 0); COMPILE_TIME_ASSERT(sizeof(T) == 0);
#endif #endif
image_view<T> t(t_);
t.set_size( height_, width_ ); t.set_size( height_, width_ );
for ( unsigned n = 0; n < height_;n++ ) for ( unsigned n = 0; n < height_;n++ )
......
...@@ -99,8 +99,8 @@ namespace dlib ...@@ -99,8 +99,8 @@ namespace dlib
) const; ) const;
/*! /*!
requires requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h - image_type == an image object that implements the interface defined in
- pixel_traits<typename image_type::type> is defined dlib/image_processing/generic_image.h
ensures ensures
- loads the JPEG image stored in this object into img - loads the JPEG image stored in this object into img
!*/ !*/
...@@ -118,8 +118,8 @@ namespace dlib ...@@ -118,8 +118,8 @@ namespace dlib
); );
/*! /*!
requires requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h - image_type == an image object that implements the interface defined in
- pixel_traits<typename image_type::type> is defined dlib/image_processing/generic_image.h
ensures ensures
- performs: jpeg_loader(file_name).get_image(image); - performs: jpeg_loader(file_name).get_image(image);
!*/ !*/
......
...@@ -15,8 +15,8 @@ namespace dlib ...@@ -15,8 +15,8 @@ namespace dlib
); );
/*! /*!
requires requires
- image_type == is an implementation of array2d/array2d_kernel_abstract.h - image_type == an image object that implements the interface defined in
- pixel_traits<typename image_type::type> is defined dlib/image_processing/generic_image.h
ensures ensures
- let EXT == the extension of the file given by file_name converted - let EXT == the extension of the file given by file_name converted
to lower case (i.e. the part of the file after the '.') to lower case (i.e. the part of the file after the '.')
......
...@@ -30,7 +30,7 @@ namespace dlib ...@@ -30,7 +30,7 @@ namespace dlib
unsigned int bit_depth () const { return bit_depth_; } unsigned int bit_depth () const { return bit_depth_; }
template<typename T> template<typename T>
void get_image( T& t) const void get_image( T& t_) const
{ {
#ifndef DLIB_PNG_SUPPORT #ifndef DLIB_PNG_SUPPORT
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
...@@ -42,7 +42,8 @@ namespace dlib ...@@ -42,7 +42,8 @@ namespace dlib
COMPILE_TIME_ASSERT(sizeof(T) == 0); COMPILE_TIME_ASSERT(sizeof(T) == 0);
#endif #endif
typedef typename T::type pixel_type; typedef typename image_traits<T>::pixel_type pixel_type;
image_view<T> t(t_);
t.set_size( height_, width_ ); t.set_size( height_, width_ );
...@@ -148,7 +149,7 @@ namespace dlib ...@@ -148,7 +149,7 @@ namespace dlib
} }
else if (is_rgba() && bit_depth_ == 8) else if (is_rgba() && bit_depth_ == 8)
{ {
if (!pixel_traits<typename T::type>::has_alpha) if (!pixel_traits<pixel_type>::has_alpha)
assign_all_pixels(t,0); assign_all_pixels(t,0);
for ( unsigned n = 0; n < height_;n++ ) for ( unsigned n = 0; n < height_;n++ )
...@@ -167,7 +168,7 @@ namespace dlib ...@@ -167,7 +168,7 @@ namespace dlib
} }
else if (is_rgba() && bit_depth_ == 16) else if (is_rgba() && bit_depth_ == 16)
{ {
if (!pixel_traits<typename T::type>::has_alpha) if (!pixel_traits<pixel_type>::has_alpha)
assign_all_pixels(t,0); assign_all_pixels(t,0);
for ( unsigned n = 0; n < height_;n++ ) for ( unsigned n = 0; n < height_;n++ )
......
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