mirror of
https://gitcode.com/gh_mirrors/ope/OpenFace.git
synced 2026-04-26 14:10:17 +00:00
308 lines
11 KiB
C++
308 lines
11 KiB
C++
// 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_
|
|
|