Permalink
Fetching contributors…
Cannot retrieve contributors at this time
308 lines (266 sloc) 10.9 KB
// Copyright (C) 2014 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_LBP_Hh_
#define DLIB_LBP_Hh_
#include "lbp_abstract.h"
#include "../image_processing/generic_image.h"
#include "assign_image.h"
#include "../pixel.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename image_type,
typename image_type2
>
void make_uniform_lbp_image (
const image_type& img_,
image_type2& lbp_
)
{
const static unsigned char uniform_lbps[] = {
0, 1, 2, 3, 4, 58, 5, 6, 7, 58, 58, 58, 8, 58, 9, 10, 11, 58, 58, 58, 58, 58,
58, 58, 12, 58, 58, 58, 13, 58, 14, 15, 16, 58, 58, 58, 58, 58, 58, 58, 58, 58,
58, 58, 58, 58, 58, 58, 17, 58, 58, 58, 58, 58, 58, 58, 18, 58, 58, 58, 19, 58,
20, 21, 22, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 23, 58, 58, 58, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 24, 58, 58, 58, 58, 58, 58, 58, 25, 58,
58, 58, 26, 58, 27, 28, 29, 30, 58, 31, 58, 58, 58, 32, 58, 58, 58, 58, 58, 58,
58, 33, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 34, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
58, 58, 58, 58, 58, 58, 58, 58, 58, 35, 36, 37, 58, 38, 58, 58, 58, 39, 58, 58,
58, 58, 58, 58, 58, 40, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58,
58, 41, 42, 43, 58, 44, 58, 58, 58, 45, 58, 58, 58, 58, 58, 58, 58, 46, 47, 48,
58, 49, 58, 58, 58, 50, 51, 52, 58, 53, 54, 55, 56, 57
};
COMPILE_TIME_ASSERT(sizeof(uniform_lbps) == 256);
const_image_view<image_type> img(img_);
image_view<image_type2> lbp(lbp_);
lbp.set_size(img.nr(), img.nc());
// set all the border pixels to the "non-uniform LBP value".
assign_border_pixels(lbp, 1, 1, 58);
typedef typename image_traits<image_type>::pixel_type pixel_type;
typedef typename pixel_traits<pixel_type>::basic_pixel_type basic_pixel_type;
for (long r = 1; r+1 < img.nr(); ++r)
{
for (long c = 1; c+1 < img.nc(); ++c)
{
const basic_pixel_type pix = get_pixel_intensity(img[r][c]);
unsigned char b1 = 0;
unsigned char b2 = 0;
unsigned char b3 = 0;
unsigned char b4 = 0;
unsigned char b5 = 0;
unsigned char b6 = 0;
unsigned char b7 = 0;
unsigned char b8 = 0;
unsigned char x = 0;
if (get_pixel_intensity(img[r-1][c-1]) > pix) b1 = 0x80;
if (get_pixel_intensity(img[r-1][c ]) > pix) b2 = 0x40;
if (get_pixel_intensity(img[r-1][c+1]) > pix) b3 = 0x20;
x |= b1;
if (get_pixel_intensity(img[r ][c-1]) > pix) b4 = 0x10;
x |= b2;
if (get_pixel_intensity(img[r ][c+1]) > pix) b5 = 0x08;
x |= b3;
if (get_pixel_intensity(img[r+1][c-1]) > pix) b6 = 0x04;
x |= b4;
if (get_pixel_intensity(img[r+1][c ]) > pix) b7 = 0x02;
x |= b5;
if (get_pixel_intensity(img[r+1][c+1]) > pix) b8 = 0x01;
x |= b6;
x |= b7;
x |= b8;
lbp[r][c] = uniform_lbps[x];
}
}
}
// ----------------------------------------------------------------------------------------
template <
typename image_type,
typename T
>
void extract_histogram_descriptors (
const image_type& img_,
const point& loc,
std::vector<T>& histograms,
const unsigned int cell_size = 10,
const unsigned int block_size = 4,
const unsigned int max_val = 58
)
{
// make sure requires clause is not broken
DLIB_ASSERT(cell_size >= 1 && block_size >= 1 && max_val < 256 &&
(unsigned int)max(mat(img_)) <= max_val,
"\t void extract_histogram_descriptors()"
<< "\n\t Invalid inputs were given to this function."
<< "\n\t cell_size: " << cell_size
<< "\n\t block_size: " << block_size
<< "\n\t max_val: " << max_val
<< "\n\t max(mat(img_)): " << max(mat(img_))
);
typedef typename image_traits<image_type>::pixel_type pixel_type;
COMPILE_TIME_ASSERT((is_same_type<pixel_type, unsigned char>::value));
const_image_view<image_type> img(img_);
const rectangle area = get_rect(img);
const rectangle window = centered_rect(loc, block_size*cell_size, block_size*cell_size);
unsigned int cell_top = window.top();
for (unsigned int br = 0; br < block_size; ++br)
{
unsigned int cell_left = window.left();
for (unsigned int bc = 0; bc < block_size; ++bc)
{
// figure out the cell boundaries
rectangle cell(cell_left, cell_top, cell_left+cell_size-1, cell_top+cell_size-1);
cell = cell.intersect(area);
// make the actual histogram for this cell
unsigned int hist[256] = {0};
for (long r = cell.top(); r <= cell.bottom(); ++r)
{
for (long c = cell.left(); c <= cell.right(); ++c)
{
hist[img[r][c]]++;
}
}
// copy histogram into the output.
histograms.insert(histograms.end(), hist, hist + max_val+1);
cell_left += cell_size;
}
cell_top += cell_size;
}
}
// ----------------------------------------------------------------------------------------
template <
typename image_type,
typename T
>
void extract_uniform_lbp_descriptors (
const image_type& img,
std::vector<T>& feats,
const unsigned int cell_size = 10
)
{
// make sure requires clause is not broken
DLIB_ASSERT(cell_size >= 1,
"\t void extract_uniform_lbp_descriptors()"
<< "\n\t Invalid inputs were given to this function."
<< "\n\t cell_size: " << cell_size
);
feats.clear();
array2d<unsigned char> lbp;
make_uniform_lbp_image(img, lbp);
for (long r = 0; r < lbp.nr(); r+=cell_size)
{
for (long c = 0; c < lbp.nc(); c+=cell_size)
{
const rectangle cell = rectangle(c,r,c+cell_size-1,r+cell_size-1).intersect(get_rect(lbp));
// make the actual histogram for this cell
unsigned int hist[59] = {0};
for (long r = cell.top(); r <= cell.bottom(); ++r)
{
for (long c = cell.left(); c <= cell.right(); ++c)
{
hist[lbp[r][c]]++;
}
}
// copy histogram into the output.
feats.insert(feats.end(), hist, hist + 59);
}
}
for (unsigned long i = 0; i < feats.size(); ++i)
feats[i] = std::sqrt(feats[i]);
}
// ----------------------------------------------------------------------------------------
template <
typename image_type,
typename T
>
void extract_highdim_face_lbp_descriptors (
const image_type& img,
const full_object_detection& det,
std::vector<T>& feats
)
{
// make sure requires clause is not broken
DLIB_CASSERT(det.num_parts() == 68,
"\t void extract_highdim_face_lbp_descriptors()"
<< "\n\t Invalid inputs were given to this function."
<< "\n\t det.num_parts(): " << det.num_parts()
);
const unsigned long num_scales = 5;
feats.clear();
dlib::vector<double,2> l, r;
double cnt = 0;
// Find the center of the left eye by averaging the points around
// the eye.
for (unsigned long i = 36; i <= 41; ++i)
{
l += det.part(i);
++cnt;
}
l /= cnt;
// Find the center of the right eye by averaging the points around
// the eye.
cnt = 0;
for (unsigned long i = 42; i <= 47; ++i)
{
r += det.part(i);
++cnt;
}
r /= cnt;
// We only do feature extraction from these face parts. These are things like the
// corners of the eyes and mouth and stuff like that.
std::vector<point> parts;
parts.reserve(30);
parts.push_back(l);
parts.push_back(r);
parts.push_back(det.part(17));
parts.push_back(det.part(21));
parts.push_back(det.part(22));
parts.push_back(det.part(26));
parts.push_back(det.part(36));
parts.push_back(det.part(39));
parts.push_back(det.part(42));
parts.push_back(det.part(45));
parts.push_back(det.part(27));
parts.push_back(det.part(28));
parts.push_back(det.part(29));
parts.push_back(det.part(30));
parts.push_back(det.part(31));
parts.push_back(det.part(35));
parts.push_back(det.part(33));
parts.push_back(det.part(48));
parts.push_back(det.part(54));
parts.push_back(det.part(51));
parts.push_back(det.part(57));
array2d<unsigned char> lbp;
make_uniform_lbp_image(img, lbp);
for (unsigned long i = 0; i < parts.size(); ++i)
extract_histogram_descriptors(lbp, parts[i], feats);
if (num_scales > 1)
{
pyramid_down<4> pyr;
image_type img_temp;
pyr(img, img_temp);
unsigned long num_pyr_calls = 1;
// now pull the features out at coarser scales
for (unsigned long iter = 1; iter < num_scales; ++iter)
{
// now do the feature extraction
make_uniform_lbp_image(img_temp, lbp);
for (unsigned long i = 0; i < parts.size(); ++i)
extract_histogram_descriptors(lbp, pyr.point_down(parts[i],num_pyr_calls), feats);
if (iter+1 < num_scales)
{
pyr(img_temp);
++num_pyr_calls;
}
}
}
for (unsigned long i = 0; i < feats.size(); ++i)
feats[i] = std::sqrt(feats[i]);
DLIB_ASSERT(feats.size() == 99120, feats.size());
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_LBP_Hh_