183 lines
5.3 KiB
C++
183 lines
5.3 KiB
C++
// Copyright (C) 2006 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_EQUALIZE_HISTOGRAm_
|
|
#define DLIB_EQUALIZE_HISTOGRAm_
|
|
|
|
#include "../pixel.h"
|
|
#include "equalize_histogram_abstract.h"
|
|
#include <vector>
|
|
#include "../enable_if.h"
|
|
#include "../matrix.h"
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ---------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename in_image_type,
|
|
long R,
|
|
long C,
|
|
typename MM
|
|
>
|
|
void get_histogram (
|
|
const in_image_type& in_img_,
|
|
matrix<unsigned long,R,C,MM>& hist,
|
|
size_t hist_size
|
|
)
|
|
{
|
|
typedef typename image_traits<in_image_type>::pixel_type pixel_type;
|
|
COMPILE_TIME_ASSERT( pixel_traits<pixel_type>::is_unsigned == true );
|
|
|
|
// make sure hist is the right size
|
|
if (R == 1)
|
|
hist.set_size(1,hist_size);
|
|
else
|
|
hist.set_size(hist_size,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)
|
|
{
|
|
for (long c = 0; c < in_img.nc(); ++c)
|
|
{
|
|
auto p = get_pixel_intensity(in_img[r][c]);
|
|
if (p < hist_size)
|
|
++hist(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename in_image_type,
|
|
long R,
|
|
long C,
|
|
typename MM
|
|
>
|
|
void get_histogram (
|
|
const in_image_type& in_img_,
|
|
matrix<unsigned long,R,C,MM>& hist
|
|
)
|
|
{
|
|
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<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<pixel_type>::max()+1);
|
|
else
|
|
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)
|
|
{
|
|
for (long c = 0; c < in_img.nc(); ++c)
|
|
{
|
|
unsigned long p = get_pixel_intensity(in_img[r][c]);
|
|
++hist(p);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------------
|
|
|
|
template <
|
|
typename in_image_type,
|
|
typename out_image_type
|
|
>
|
|
void equalize_histogram (
|
|
const in_image_type& in_img_,
|
|
out_image_type& out_img_
|
|
)
|
|
{
|
|
const_image_view<in_image_type> in_img(in_img_);
|
|
image_view<out_image_type> out_img(out_img_);
|
|
|
|
typedef typename image_traits<in_image_type>::pixel_type in_pixel_type;
|
|
typedef typename image_traits<out_image_type>::pixel_type out_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);
|
|
|
|
|
|
// if there isn't any input image then don't do anything
|
|
if (in_img.size() == 0)
|
|
{
|
|
out_img.clear();
|
|
return;
|
|
}
|
|
|
|
out_img.set_size(in_img.nr(),in_img.nc());
|
|
|
|
unsigned long p;
|
|
|
|
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))
|
|
scale /= in_img.size()-histogram(0);
|
|
else
|
|
scale = 0;
|
|
|
|
// make the black pixels remain black in the output image
|
|
histogram(0) = 0;
|
|
|
|
// compute the transform function
|
|
for (long i = 1; i < histogram.size(); ++i)
|
|
histogram(i) += histogram(i-1);
|
|
// scale so that it is in the range [0,pixel_traits<out_pixel_type>::max()]
|
|
for (long i = 0; i < histogram.size(); ++i)
|
|
histogram(i) = static_cast<unsigned long>(histogram(i)*scale);
|
|
|
|
// now do the transform
|
|
for (long row = 0; row < in_img.nr(); ++row)
|
|
{
|
|
for (long col = 0; col < in_img.nc(); ++col)
|
|
{
|
|
p = histogram(get_pixel_intensity(in_img[row][col]));
|
|
assign_pixel(out_img[row][col], in_img[row][col]);
|
|
assign_pixel_intensity(out_img[row][col],p);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
template <
|
|
typename image_type
|
|
>
|
|
void equalize_histogram (
|
|
image_type& img
|
|
)
|
|
{
|
|
equalize_histogram(img,img);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_EQUALIZE_HISTOGRAm_
|
|
|
|
|
|
|