diff options
Diffstat (limited to 'ml/dlib/dlib/image_transforms/fhog.h')
-rw-r--r-- | ml/dlib/dlib/image_transforms/fhog.h | 1404 |
1 files changed, 0 insertions, 1404 deletions
diff --git a/ml/dlib/dlib/image_transforms/fhog.h b/ml/dlib/dlib/image_transforms/fhog.h deleted file mode 100644 index d99973adf..000000000 --- a/ml/dlib/dlib/image_transforms/fhog.h +++ /dev/null @@ -1,1404 +0,0 @@ -// Copyright (C) 2013 Davis E. King (davis@dlib.net) -// License: Boost Software License See LICENSE.txt for the full license. -#ifndef DLIB_fHOG_Hh_ -#define DLIB_fHOG_Hh_ - -#include "fhog_abstract.h" -#include "../matrix.h" -#include "../array2d.h" -#include "../array.h" -#include "../geometry.h" -#include "assign_image.h" -#include "draw.h" -#include "interpolation.h" -#include "../simd.h" - -namespace dlib -{ - -// ---------------------------------------------------------------------------------------- - - namespace impl_fhog - { - template <typename image_type, typename T> - inline typename dlib::enable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient ( - const int r, - const int c, - const image_type& img, - matrix<T,2,1>& grad, - T& len - ) - { - matrix<T, 2, 1> grad2, grad3; - // get the red gradient - grad(0) = (int)img[r][c+1].red-(int)img[r][c-1].red; - grad(1) = (int)img[r+1][c].red-(int)img[r-1][c].red; - len = length_squared(grad); - - // get the green gradient - grad2(0) = (int)img[r][c+1].green-(int)img[r][c-1].green; - grad2(1) = (int)img[r+1][c].green-(int)img[r-1][c].green; - T v2 = length_squared(grad2); - - // get the blue gradient - grad3(0) = (int)img[r][c+1].blue-(int)img[r][c-1].blue; - grad3(1) = (int)img[r+1][c].blue-(int)img[r-1][c].blue; - T v3 = length_squared(grad3); - - // pick color with strongest gradient - if (v2 > len) - { - len = v2; - grad = grad2; - } - if (v3 > len) - { - len = v3; - grad = grad3; - } - } - - template <typename image_type> - inline typename dlib::enable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient ( - const int r, - const int c, - const image_type& img, - simd4f& grad_x, - simd4f& grad_y, - simd4f& len - ) - { - simd4i rleft((int)img[r][c-1].red, - (int)img[r][c].red, - (int)img[r][c+1].red, - (int)img[r][c+2].red); - simd4i rright((int)img[r][c+1].red, - (int)img[r][c+2].red, - (int)img[r][c+3].red, - (int)img[r][c+4].red); - simd4i rtop((int)img[r-1][c].red, - (int)img[r-1][c+1].red, - (int)img[r-1][c+2].red, - (int)img[r-1][c+3].red); - simd4i rbottom((int)img[r+1][c].red, - (int)img[r+1][c+1].red, - (int)img[r+1][c+2].red, - (int)img[r+1][c+3].red); - - simd4i gleft((int)img[r][c-1].green, - (int)img[r][c].green, - (int)img[r][c+1].green, - (int)img[r][c+2].green); - simd4i gright((int)img[r][c+1].green, - (int)img[r][c+2].green, - (int)img[r][c+3].green, - (int)img[r][c+4].green); - simd4i gtop((int)img[r-1][c].green, - (int)img[r-1][c+1].green, - (int)img[r-1][c+2].green, - (int)img[r-1][c+3].green); - simd4i gbottom((int)img[r+1][c].green, - (int)img[r+1][c+1].green, - (int)img[r+1][c+2].green, - (int)img[r+1][c+3].green); - - simd4i bleft((int)img[r][c-1].blue, - (int)img[r][c].blue, - (int)img[r][c+1].blue, - (int)img[r][c+2].blue); - simd4i bright((int)img[r][c+1].blue, - (int)img[r][c+2].blue, - (int)img[r][c+3].blue, - (int)img[r][c+4].blue); - simd4i btop((int)img[r-1][c].blue, - (int)img[r-1][c+1].blue, - (int)img[r-1][c+2].blue, - (int)img[r-1][c+3].blue); - simd4i bbottom((int)img[r+1][c].blue, - (int)img[r+1][c+1].blue, - (int)img[r+1][c+2].blue, - (int)img[r+1][c+3].blue); - - simd4i grad_x_red = rright-rleft; - simd4i grad_y_red = rbottom-rtop; - simd4i grad_x_green = gright-gleft; - simd4i grad_y_green = gbottom-gtop; - simd4i grad_x_blue = bright-bleft; - simd4i grad_y_blue = bbottom-btop; - - simd4i rlen = grad_x_red*grad_x_red + grad_y_red*grad_y_red; - simd4i glen = grad_x_green*grad_x_green + grad_y_green*grad_y_green; - simd4i blen = grad_x_blue*grad_x_blue + grad_y_blue*grad_y_blue; - - simd4i cmp = rlen>glen; - simd4i tgrad_x = select(cmp,grad_x_red,grad_x_green); - simd4i tgrad_y = select(cmp,grad_y_red,grad_y_green); - simd4i tlen = select(cmp,rlen,glen); - - cmp = tlen>blen; - grad_x = select(cmp,tgrad_x,grad_x_blue); - grad_y = select(cmp,tgrad_y,grad_y_blue); - len = select(cmp,tlen,blen); - } - - // ------------------------------------------------------------------------------------ - - template <typename image_type> - inline typename dlib::enable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient( - const int r, - const int c, - const image_type& img, - simd8f& grad_x, - simd8f& grad_y, - simd8f& len - ) - { - simd8i rleft((int)img[r][c - 1].red, - (int)img[r][c].red, - (int)img[r][c + 1].red, - (int)img[r][c + 2].red, - (int)img[r][c + 3].red, - (int)img[r][c + 4].red, - (int)img[r][c + 5].red, - (int)img[r][c + 6].red); - simd8i rright((int)img[r][c + 1].red, - (int)img[r][c + 2].red, - (int)img[r][c + 3].red, - (int)img[r][c + 4].red, - (int)img[r][c + 5].red, - (int)img[r][c + 6].red, - (int)img[r][c + 7].red, - (int)img[r][c + 8].red); - simd8i rtop((int)img[r - 1][c].red, - (int)img[r - 1][c + 1].red, - (int)img[r - 1][c + 2].red, - (int)img[r - 1][c + 3].red, - (int)img[r - 1][c + 4].red, - (int)img[r - 1][c + 5].red, - (int)img[r - 1][c + 6].red, - (int)img[r - 1][c + 7].red); - simd8i rbottom((int)img[r + 1][c].red, - (int)img[r + 1][c + 1].red, - (int)img[r + 1][c + 2].red, - (int)img[r + 1][c + 3].red, - (int)img[r + 1][c + 4].red, - (int)img[r + 1][c + 5].red, - (int)img[r + 1][c + 6].red, - (int)img[r + 1][c + 7].red); - - simd8i gleft((int)img[r][c - 1].green, - (int)img[r][c].green, - (int)img[r][c + 1].green, - (int)img[r][c + 2].green, - (int)img[r][c + 3].green, - (int)img[r][c + 4].green, - (int)img[r][c + 5].green, - (int)img[r][c + 6].green); - simd8i gright((int)img[r][c + 1].green, - (int)img[r][c + 2].green, - (int)img[r][c + 3].green, - (int)img[r][c + 4].green, - (int)img[r][c + 5].green, - (int)img[r][c + 6].green, - (int)img[r][c + 7].green, - (int)img[r][c + 8].green); - simd8i gtop((int)img[r - 1][c].green, - (int)img[r - 1][c + 1].green, - (int)img[r - 1][c + 2].green, - (int)img[r - 1][c + 3].green, - (int)img[r - 1][c + 4].green, - (int)img[r - 1][c + 5].green, - (int)img[r - 1][c + 6].green, - (int)img[r - 1][c + 7].green); - simd8i gbottom((int)img[r + 1][c].green, - (int)img[r + 1][c + 1].green, - (int)img[r + 1][c + 2].green, - (int)img[r + 1][c + 3].green, - (int)img[r + 1][c + 4].green, - (int)img[r + 1][c + 5].green, - (int)img[r + 1][c + 6].green, - (int)img[r + 1][c + 7].green); - - simd8i bleft((int)img[r][c - 1].blue, - (int)img[r][c].blue, - (int)img[r][c + 1].blue, - (int)img[r][c + 2].blue, - (int)img[r][c + 3].blue, - (int)img[r][c + 4].blue, - (int)img[r][c + 5].blue, - (int)img[r][c + 6].blue); - simd8i bright((int)img[r][c + 1].blue, - (int)img[r][c + 2].blue, - (int)img[r][c + 3].blue, - (int)img[r][c + 4].blue, - (int)img[r][c + 5].blue, - (int)img[r][c + 6].blue, - (int)img[r][c + 7].blue, - (int)img[r][c + 8].blue); - simd8i btop((int)img[r - 1][c].blue, - (int)img[r - 1][c + 1].blue, - (int)img[r - 1][c + 2].blue, - (int)img[r - 1][c + 3].blue, - (int)img[r - 1][c + 4].blue, - (int)img[r - 1][c + 5].blue, - (int)img[r - 1][c + 6].blue, - (int)img[r - 1][c + 7].blue); - simd8i bbottom((int)img[r + 1][c].blue, - (int)img[r + 1][c + 1].blue, - (int)img[r + 1][c + 2].blue, - (int)img[r + 1][c + 3].blue, - (int)img[r + 1][c + 4].blue, - (int)img[r + 1][c + 5].blue, - (int)img[r + 1][c + 6].blue, - (int)img[r + 1][c + 7].blue); - - simd8i grad_x_red = rright - rleft; - simd8i grad_y_red = rbottom - rtop; - simd8i grad_x_green = gright - gleft; - simd8i grad_y_green = gbottom - gtop; - simd8i grad_x_blue = bright - bleft; - simd8i grad_y_blue = bbottom - btop; - - simd8i rlen = grad_x_red*grad_x_red + grad_y_red*grad_y_red; - simd8i glen = grad_x_green*grad_x_green + grad_y_green*grad_y_green; - simd8i blen = grad_x_blue*grad_x_blue + grad_y_blue*grad_y_blue; - - simd8i cmp = rlen > glen; - simd8i tgrad_x = select(cmp, grad_x_red, grad_x_green); - simd8i tgrad_y = select(cmp, grad_y_red, grad_y_green); - simd8i tlen = select(cmp, rlen, glen); - - cmp = tlen > blen; - grad_x = select(cmp, tgrad_x, grad_x_blue); - grad_y = select(cmp, tgrad_y, grad_y_blue); - len = select(cmp, tlen, blen); - } - - // ------------------------------------------------------------------------------------ - - template <typename image_type, typename T> - inline typename dlib::disable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient ( - const int r, - const int c, - const image_type& img, - matrix<T, 2, 1>& grad, - T& len - ) - { - grad(0) = (int)get_pixel_intensity(img[r][c+1])-(int)get_pixel_intensity(img[r][c-1]); - grad(1) = (int)get_pixel_intensity(img[r+1][c])-(int)get_pixel_intensity(img[r-1][c]); - len = length_squared(grad); - } - - template <typename image_type> - inline typename dlib::disable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient ( - int r, - int c, - const image_type& img, - simd4f& grad_x, - simd4f& grad_y, - simd4f& len - ) - { - simd4i left((int)get_pixel_intensity(img[r][c-1]), - (int)get_pixel_intensity(img[r][c]), - (int)get_pixel_intensity(img[r][c+1]), - (int)get_pixel_intensity(img[r][c+2])); - simd4i right((int)get_pixel_intensity(img[r][c+1]), - (int)get_pixel_intensity(img[r][c+2]), - (int)get_pixel_intensity(img[r][c+3]), - (int)get_pixel_intensity(img[r][c+4])); - - simd4i top((int)get_pixel_intensity(img[r-1][c]), - (int)get_pixel_intensity(img[r-1][c+1]), - (int)get_pixel_intensity(img[r-1][c+2]), - (int)get_pixel_intensity(img[r-1][c+3])); - simd4i bottom((int)get_pixel_intensity(img[r+1][c]), - (int)get_pixel_intensity(img[r+1][c+1]), - (int)get_pixel_intensity(img[r+1][c+2]), - (int)get_pixel_intensity(img[r+1][c+3])); - - grad_x = right-left; - grad_y = bottom-top; - - len = (grad_x*grad_x + grad_y*grad_y); - } - - // ------------------------------------------------------------------------------------ - - template <typename image_type> - inline typename dlib::disable_if_c<pixel_traits<typename image_type::pixel_type>::rgb>::type get_gradient( - int r, - int c, - const image_type& img, - simd8f& grad_x, - simd8f& grad_y, - simd8f& len - ) - { - simd8i left((int)get_pixel_intensity(img[r][c - 1]), - (int)get_pixel_intensity(img[r][c]), - (int)get_pixel_intensity(img[r][c + 1]), - (int)get_pixel_intensity(img[r][c + 2]), - (int)get_pixel_intensity(img[r][c + 3]), - (int)get_pixel_intensity(img[r][c + 4]), - (int)get_pixel_intensity(img[r][c + 5]), - (int)get_pixel_intensity(img[r][c + 6])); - simd8i right((int)get_pixel_intensity(img[r][c + 1]), - (int)get_pixel_intensity(img[r][c + 2]), - (int)get_pixel_intensity(img[r][c + 3]), - (int)get_pixel_intensity(img[r][c + 4]), - (int)get_pixel_intensity(img[r][c + 5]), - (int)get_pixel_intensity(img[r][c + 6]), - (int)get_pixel_intensity(img[r][c + 7]), - (int)get_pixel_intensity(img[r][c + 8])); - - simd8i top((int)get_pixel_intensity(img[r - 1][c]), - (int)get_pixel_intensity(img[r - 1][c + 1]), - (int)get_pixel_intensity(img[r - 1][c + 2]), - (int)get_pixel_intensity(img[r - 1][c + 3]), - (int)get_pixel_intensity(img[r - 1][c + 4]), - (int)get_pixel_intensity(img[r - 1][c + 5]), - (int)get_pixel_intensity(img[r - 1][c + 6]), - (int)get_pixel_intensity(img[r - 1][c + 7])); - simd8i bottom((int)get_pixel_intensity(img[r + 1][c]), - (int)get_pixel_intensity(img[r + 1][c + 1]), - (int)get_pixel_intensity(img[r + 1][c + 2]), - (int)get_pixel_intensity(img[r + 1][c + 3]), - (int)get_pixel_intensity(img[r + 1][c + 4]), - (int)get_pixel_intensity(img[r + 1][c + 5]), - (int)get_pixel_intensity(img[r + 1][c + 6]), - (int)get_pixel_intensity(img[r + 1][c + 7])); - - grad_x = right - left; - grad_y = bottom - top; - - len = (grad_x*grad_x + grad_y*grad_y); - } - - // ------------------------------------------------------------------------------------ - - template <typename T, typename mm1, typename mm2> - inline void set_hog ( - dlib::array<array2d<T,mm1>,mm2>& hog, - int o, - int x, - int y, - const float& value - ) - { - hog[o][y][x] = value; - } - - template <typename T, typename mm1, typename mm2> - void init_hog ( - dlib::array<array2d<T,mm1>,mm2>& hog, - int hog_nr, - int hog_nc, - int filter_rows_padding, - int filter_cols_padding - ) - { - const int num_hog_bands = 27+4; - hog.resize(num_hog_bands); - for (int i = 0; i < num_hog_bands; ++i) - { - hog[i].set_size(hog_nr+filter_rows_padding-1, hog_nc+filter_cols_padding-1); - rectangle rect = get_rect(hog[i]); - rect.top() += (filter_rows_padding-1)/2; - rect.left() += (filter_cols_padding-1)/2; - rect.right() -= filter_cols_padding/2; - rect.bottom() -= filter_rows_padding/2; - zero_border_pixels(hog[i],rect); - } - } - - template <typename T, typename mm1, typename mm2> - void init_hog_zero_everything ( - dlib::array<array2d<T,mm1>,mm2>& hog, - int hog_nr, - int hog_nc, - int filter_rows_padding, - int filter_cols_padding - ) - { - const int num_hog_bands = 27+4; - hog.resize(num_hog_bands); - for (int i = 0; i < num_hog_bands; ++i) - { - hog[i].set_size(hog_nr+filter_rows_padding-1, hog_nc+filter_cols_padding-1); - assign_all_pixels(hog[i], 0); - } - } - - // ------------------------------------------------------------------------------------ - - template <typename T, typename mm> - inline void set_hog ( - array2d<matrix<T,31,1>,mm>& hog, - int o, - int x, - int y, - const float& value - ) - { - hog[y][x](o) = value; - } - - template <typename T, typename mm> - void init_hog ( - array2d<matrix<T,31,1>,mm>& hog, - int hog_nr, - int hog_nc, - int filter_rows_padding, - int filter_cols_padding - ) - { - hog.set_size(hog_nr+filter_rows_padding-1, hog_nc+filter_cols_padding-1); - - // now zero out the border region - rectangle rect = get_rect(hog); - rect.top() += (filter_rows_padding-1)/2; - rect.left() += (filter_cols_padding-1)/2; - rect.right() -= filter_cols_padding/2; - rect.bottom() -= filter_rows_padding/2; - border_enumerator be(get_rect(hog),rect); - while (be.move_next()) - { - const point p = be.element(); - set_all_elements(hog[p.y()][p.x()], 0); - } - } - - template <typename T, typename mm> - void init_hog_zero_everything ( - array2d<matrix<T,31,1>,mm>& hog, - int hog_nr, - int hog_nc, - int filter_rows_padding, - int filter_cols_padding - ) - { - hog.set_size(hog_nr+filter_rows_padding-1, hog_nc+filter_cols_padding-1); - - for (long r = 0; r < hog.nr(); ++r) - { - for (long c = 0; c < hog.nc(); ++c) - { - set_all_elements(hog[r][c], 0); - } - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename image_type, - typename out_type - > - void impl_extract_fhog_features_cell_size_1( - const image_type& img_, - out_type& hog, - int filter_rows_padding, - int filter_cols_padding - ) - { - const_image_view<image_type> img(img_); - // make sure requires clause is not broken - DLIB_ASSERT( filter_rows_padding > 0 && - filter_cols_padding > 0 , - "\t void extract_fhog_features()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t filter_rows_padding: " << filter_rows_padding - << "\n\t filter_cols_padding: " << filter_cols_padding - ); - - /* - This function is an optimized version of impl_extract_fhog_features() for - the case where cell_size == 1. - */ - - - // unit vectors used to compute gradient orientation - matrix<float,2,1> directions[9]; - directions[0] = 1.0000, 0.0000; - directions[1] = 0.9397, 0.3420; - directions[2] = 0.7660, 0.6428; - directions[3] = 0.500, 0.8660; - directions[4] = 0.1736, 0.9848; - directions[5] = -0.1736, 0.9848; - directions[6] = -0.5000, 0.8660; - directions[7] = -0.7660, 0.6428; - directions[8] = -0.9397, 0.3420; - - - - if (img.nr() <= 2 || img.nc() <= 2) - { - hog.clear(); - return; - } - - array2d<unsigned char> angle(img.nr(), img.nc()); - - array2d<float> norm(img.nr(), img.nc()); - zero_border_pixels(norm,1,1); - - // memory for HOG features - const long hog_nr = img.nr()-2; - const long hog_nc = img.nc()-2; - - const int padding_rows_offset = (filter_rows_padding-1)/2; - const int padding_cols_offset = (filter_cols_padding-1)/2; - init_hog_zero_everything(hog, hog_nr, hog_nc, filter_rows_padding, filter_cols_padding); - - - const int visible_nr = img.nr()-1; - const int visible_nc = img.nc()-1; - - // First populate the gradient histograms - for (int y = 1; y < visible_nr; y++) - { - int x; - for (x = 1; x < visible_nc - 7; x += 8) - { - // v will be the length of the gradient vectors. - simd8f grad_x, grad_y, v; - get_gradient(y, x, img, grad_x, grad_y, v); - - float _vv[8]; - v.store(_vv); - - // Now snap the gradient to one of 18 orientations - simd8f best_dot = 0; - simd8f best_o = 0; - for (int o = 0; o < 9; o++) - { - simd8f dot = grad_x*directions[o](0) + grad_y*directions[o](1); - simd8f_bool cmp = dot>best_dot; - best_dot = select(cmp, dot, best_dot); - dot *= -1; - best_o = select(cmp, o, best_o); - - cmp = dot > best_dot; - best_dot = select(cmp, dot, best_dot); - best_o = select(cmp, o + 9, best_o); - } - - int32 _best_o[8]; simd8i(best_o).store(_best_o); - - norm[y][x + 0] = _vv[0]; - norm[y][x + 1] = _vv[1]; - norm[y][x + 2] = _vv[2]; - norm[y][x + 3] = _vv[3]; - norm[y][x + 4] = _vv[4]; - norm[y][x + 5] = _vv[5]; - norm[y][x + 6] = _vv[6]; - norm[y][x + 7] = _vv[7]; - - angle[y][x + 0] = _best_o[0]; - angle[y][x + 1] = _best_o[1]; - angle[y][x + 2] = _best_o[2]; - angle[y][x + 3] = _best_o[3]; - angle[y][x + 4] = _best_o[4]; - angle[y][x + 5] = _best_o[5]; - angle[y][x + 6] = _best_o[6]; - angle[y][x + 7] = _best_o[7]; - } - // Now process the right columns that don't fit into simd registers. - for (; x < visible_nc; x++) - { - matrix<float,2,1> grad; - float v; - get_gradient(y,x,img,grad,v); - - // snap to one of 18 orientations - float best_dot = 0; - int best_o = 0; - for (int o = 0; o < 9; o++) - { - const float dot = dlib::dot(directions[o], grad); - if (dot > best_dot) - { - best_dot = dot; - best_o = o; - } - else if (-dot > best_dot) - { - best_dot = -dot; - best_o = o+9; - } - } - - norm[y][x] = v; - angle[y][x] = best_o; - } - } - - const float eps = 0.0001; - // compute features - for (int y = 0; y < hog_nr; y++) - { - const int yy = y+padding_rows_offset; - for (int x = 0; x < hog_nc; x++) - { - const simd4f z1(norm[y+1][x+1], - norm[y][x+1], - norm[y+1][x], - norm[y][x]); - - const simd4f z2(norm[y+1][x+2], - norm[y][x+2], - norm[y+1][x+1], - norm[y][x+1]); - - const simd4f z3(norm[y+2][x+1], - norm[y+1][x+1], - norm[y+2][x], - norm[y+1][x]); - - const simd4f z4(norm[y+2][x+2], - norm[y+1][x+2], - norm[y+2][x+1], - norm[y+1][x+1]); - - const simd4f temp0 = std::sqrt(norm[y+1][x+1]); - const simd4f nn = 0.2*sqrt(z1+z2+z3+z4+eps); - const simd4f n = 0.1/nn; - - simd4f t = 0; - - const int xx = x+padding_cols_offset; - - simd4f h0 = min(temp0,nn)*n; - const float vv = sum(h0); - set_hog(hog,angle[y+1][x+1],xx,yy, vv); - t += h0; - - t *= 2*0.2357; - - // contrast-insensitive features - set_hog(hog,angle[y+1][x+1]%9+18,xx,yy, vv); - - - float temp[4]; - t.store(temp); - - // texture features - set_hog(hog,27,xx,yy, temp[0]); - set_hog(hog,28,xx,yy, temp[1]); - set_hog(hog,29,xx,yy, temp[2]); - set_hog(hog,30,xx,yy, temp[3]); - } - } - } - - // ------------------------------------------------------------------------------------ - - template < - typename image_type, - typename out_type - > - void impl_extract_fhog_features( - const image_type& img_, - out_type& hog, - int cell_size, - int filter_rows_padding, - int filter_cols_padding - ) - { - const_image_view<image_type> img(img_); - // make sure requires clause is not broken - DLIB_ASSERT( cell_size > 0 && - filter_rows_padding > 0 && - filter_cols_padding > 0 , - "\t void extract_fhog_features()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t cell_size: " << cell_size - << "\n\t filter_rows_padding: " << filter_rows_padding - << "\n\t filter_cols_padding: " << filter_cols_padding - ); - - /* - This function implements the HOG feature extraction method described in - the paper: - P. Felzenszwalb, R. Girshick, D. McAllester, D. Ramanan - Object Detection with Discriminatively Trained Part Based Models - IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. 32, No. 9, Sep. 2010 - - Moreover, this function is derived from the HOG feature extraction code - from the features.cc file in the voc-releaseX code (see - http://people.cs.uchicago.edu/~rbg/latent/) which is has the following - license (note that the code has been modified to work with grayscale and - color as well as planar and interlaced input and output formats): - - Copyright (C) 2011, 2012 Ross Girshick, Pedro Felzenszwalb - Copyright (C) 2008, 2009, 2010 Pedro Felzenszwalb, Ross Girshick - Copyright (C) 2007 Pedro Felzenszwalb, Deva Ramanan - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION - OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - - if (cell_size == 1) - { - impl_extract_fhog_features_cell_size_1(img_,hog,filter_rows_padding,filter_cols_padding); - return; - } - - // unit vectors used to compute gradient orientation - matrix<float,2,1> directions[9]; - directions[0] = 1.0000, 0.0000; - directions[1] = 0.9397, 0.3420; - directions[2] = 0.7660, 0.6428; - directions[3] = 0.500, 0.8660; - directions[4] = 0.1736, 0.9848; - directions[5] = -0.1736, 0.9848; - directions[6] = -0.5000, 0.8660; - directions[7] = -0.7660, 0.6428; - directions[8] = -0.9397, 0.3420; - - - - // First we allocate memory for caching orientation histograms & their norms. - const int cells_nr = (int)((float)img.nr()/(float)cell_size + 0.5); - const int cells_nc = (int)((float)img.nc()/(float)cell_size + 0.5); - - if (cells_nr == 0 || cells_nc == 0) - { - hog.clear(); - return; - } - - // We give hist extra padding around the edges (1 cell all the way around the - // edge) so we can avoid needing to do boundary checks when indexing into it - // later on. So some statements assign to the boundary but those values are - // never used. - array2d<matrix<float,18,1> > hist(cells_nr+2, cells_nc+2); - for (long r = 0; r < hist.nr(); ++r) - { - for (long c = 0; c < hist.nc(); ++c) - { - hist[r][c] = 0; - } - } - - array2d<float> norm(cells_nr, cells_nc); - assign_all_pixels(norm, 0); - - // memory for HOG features - const int hog_nr = std::max(cells_nr-2, 0); - const int hog_nc = std::max(cells_nc-2, 0); - if (hog_nr == 0 || hog_nc == 0) - { - hog.clear(); - return; - } - const int padding_rows_offset = (filter_rows_padding-1)/2; - const int padding_cols_offset = (filter_cols_padding-1)/2; - init_hog(hog, hog_nr, hog_nc, filter_rows_padding, filter_cols_padding); - - const int visible_nr = std::min((long)cells_nr*cell_size,img.nr())-1; - const int visible_nc = std::min((long)cells_nc*cell_size,img.nc())-1; - - // First populate the gradient histograms - for (int y = 1; y < visible_nr; y++) - { - const float yp = ((float)y+0.5)/(float)cell_size - 0.5; - const int iyp = (int)std::floor(yp); - const float vy0 = yp - iyp; - const float vy1 = 1.0 - vy0; - int x; - for (x = 1; x < visible_nc - 7; x += 8) - { - simd8f xx(x, x + 1, x + 2, x + 3, x + 4, x + 5, x + 6, x + 7); - // v will be the length of the gradient vectors. - simd8f grad_x, grad_y, v; - get_gradient(y, x, img, grad_x, grad_y, v); - - // We will use bilinear interpolation to add into the histogram bins. - // So first we precompute the values needed to determine how much each - // pixel votes into each bin. - simd8f xp = (xx + 0.5) / (float)cell_size + 0.5; - simd8i ixp = simd8i(xp); - simd8f vx0 = xp - ixp; - simd8f vx1 = 1.0f - vx0; - - v = sqrt(v); - - // Now snap the gradient to one of 18 orientations - simd8f best_dot = 0; - simd8f best_o = 0; - for (int o = 0; o < 9; o++) - { - simd8f dot = grad_x*directions[o](0) + grad_y*directions[o](1); - simd8f_bool cmp = dot>best_dot; - best_dot = select(cmp, dot, best_dot); - dot *= -1; - best_o = select(cmp, o, best_o); - - cmp = dot > best_dot; - best_dot = select(cmp, dot, best_dot); - best_o = select(cmp, o + 9, best_o); - } - - - // Add the gradient magnitude, v, to 4 histograms around pixel using - // bilinear interpolation. - vx1 *= v; - vx0 *= v; - // The amounts for each bin - simd8f v11 = vy1*vx1; - simd8f v01 = vy0*vx1; - simd8f v10 = vy1*vx0; - simd8f v00 = vy0*vx0; - - int32 _best_o[8]; simd8i(best_o).store(_best_o); - int32 _ixp[8]; ixp.store(_ixp); - float _v11[8]; v11.store(_v11); - float _v01[8]; v01.store(_v01); - float _v10[8]; v10.store(_v10); - float _v00[8]; v00.store(_v00); - - hist[iyp + 1][_ixp[0]](_best_o[0]) += _v11[0]; - hist[iyp + 1 + 1][_ixp[0]](_best_o[0]) += _v01[0]; - hist[iyp + 1][_ixp[0] + 1](_best_o[0]) += _v10[0]; - hist[iyp + 1 + 1][_ixp[0] + 1](_best_o[0]) += _v00[0]; - - hist[iyp + 1][_ixp[1]](_best_o[1]) += _v11[1]; - hist[iyp + 1 + 1][_ixp[1]](_best_o[1]) += _v01[1]; - hist[iyp + 1][_ixp[1] + 1](_best_o[1]) += _v10[1]; - hist[iyp + 1 + 1][_ixp[1] + 1](_best_o[1]) += _v00[1]; - - hist[iyp + 1][_ixp[2]](_best_o[2]) += _v11[2]; - hist[iyp + 1 + 1][_ixp[2]](_best_o[2]) += _v01[2]; - hist[iyp + 1][_ixp[2] + 1](_best_o[2]) += _v10[2]; - hist[iyp + 1 + 1][_ixp[2] + 1](_best_o[2]) += _v00[2]; - - hist[iyp + 1][_ixp[3]](_best_o[3]) += _v11[3]; - hist[iyp + 1 + 1][_ixp[3]](_best_o[3]) += _v01[3]; - hist[iyp + 1][_ixp[3] + 1](_best_o[3]) += _v10[3]; - hist[iyp + 1 + 1][_ixp[3] + 1](_best_o[3]) += _v00[3]; - - hist[iyp + 1][_ixp[4]](_best_o[4]) += _v11[4]; - hist[iyp + 1 + 1][_ixp[4]](_best_o[4]) += _v01[4]; - hist[iyp + 1][_ixp[4] + 1](_best_o[4]) += _v10[4]; - hist[iyp + 1 + 1][_ixp[4] + 1](_best_o[4]) += _v00[4]; - - hist[iyp + 1][_ixp[5]](_best_o[5]) += _v11[5]; - hist[iyp + 1 + 1][_ixp[5]](_best_o[5]) += _v01[5]; - hist[iyp + 1][_ixp[5] + 1](_best_o[5]) += _v10[5]; - hist[iyp + 1 + 1][_ixp[5] + 1](_best_o[5]) += _v00[5]; - - hist[iyp + 1][_ixp[6]](_best_o[6]) += _v11[6]; - hist[iyp + 1 + 1][_ixp[6]](_best_o[6]) += _v01[6]; - hist[iyp + 1][_ixp[6] + 1](_best_o[6]) += _v10[6]; - hist[iyp + 1 + 1][_ixp[6] + 1](_best_o[6]) += _v00[6]; - - hist[iyp + 1][_ixp[7]](_best_o[7]) += _v11[7]; - hist[iyp + 1 + 1][_ixp[7]](_best_o[7]) += _v01[7]; - hist[iyp + 1][_ixp[7] + 1](_best_o[7]) += _v10[7]; - hist[iyp + 1 + 1][_ixp[7] + 1](_best_o[7]) += _v00[7]; - } - // Now process the right columns that don't fit into simd registers. - for (; x < visible_nc; x++) - { - matrix<float, 2, 1> grad; - float v; - get_gradient(y,x,img,grad,v); - - // snap to one of 18 orientations - float best_dot = 0; - int best_o = 0; - for (int o = 0; o < 9; o++) - { - const float dot = dlib::dot(directions[o], grad); - if (dot > best_dot) - { - best_dot = dot; - best_o = o; - } - else if (-dot > best_dot) - { - best_dot = -dot; - best_o = o+9; - } - } - - v = std::sqrt(v); - // add to 4 histograms around pixel using bilinear interpolation - const float xp = ((double)x + 0.5) / (double)cell_size - 0.5; - const int ixp = (int)std::floor(xp); - const float vx0 = xp - ixp; - const float vx1 = 1.0 - vx0; - - hist[iyp+1][ixp+1](best_o) += vy1*vx1*v; - hist[iyp+1+1][ixp+1](best_o) += vy0*vx1*v; - hist[iyp+1][ixp+1+1](best_o) += vy1*vx0*v; - hist[iyp+1+1][ixp+1+1](best_o) += vy0*vx0*v; - } - } - - // compute energy in each block by summing over orientations - for (int r = 0; r < cells_nr; ++r) - { - for (int c = 0; c < cells_nc; ++c) - { - for (int o = 0; o < 9; o++) - { - norm[r][c] += (hist[r+1][c+1](o) + hist[r+1][c+1](o+9)) * (hist[r+1][c+1](o) + hist[r+1][c+1](o+9)); - } - } - } - - const float eps = 0.0001; - // compute features - for (int y = 0; y < hog_nr; y++) - { - const int yy = y+padding_rows_offset; - for (int x = 0; x < hog_nc; x++) - { - const simd4f z1(norm[y+1][x+1], - norm[y][x+1], - norm[y+1][x], - norm[y][x]); - - const simd4f z2(norm[y+1][x+2], - norm[y][x+2], - norm[y+1][x+1], - norm[y][x+1]); - - const simd4f z3(norm[y+2][x+1], - norm[y+1][x+1], - norm[y+2][x], - norm[y+1][x]); - - const simd4f z4(norm[y+2][x+2], - norm[y+1][x+2], - norm[y+2][x+1], - norm[y+1][x+1]); - - const simd4f nn = 0.2*sqrt(z1+z2+z3+z4+eps); - const simd4f n = 0.1/nn; - - simd4f t = 0; - - const int xx = x+padding_cols_offset; - - // contrast-sensitive features - for (int o = 0; o < 18; o+=3) - { - simd4f temp0(hist[y+1+1][x+1+1](o)); - simd4f temp1(hist[y+1+1][x+1+1](o+1)); - simd4f temp2(hist[y+1+1][x+1+1](o+2)); - simd4f h0 = min(temp0,nn)*n; - simd4f h1 = min(temp1,nn)*n; - simd4f h2 = min(temp2,nn)*n; - set_hog(hog,o,xx,yy, sum(h0)); - set_hog(hog,o+1,xx,yy, sum(h1)); - set_hog(hog,o+2,xx,yy, sum(h2)); - t += h0+h1+h2; - } - - t *= 2*0.2357; - - // contrast-insensitive features - for (int o = 0; o < 9; o+=3) - { - simd4f temp0 = hist[y+1+1][x+1+1](o) + hist[y+1+1][x+1+1](o+9); - simd4f temp1 = hist[y+1+1][x+1+1](o+1) + hist[y+1+1][x+1+1](o+9+1); - simd4f temp2 = hist[y+1+1][x+1+1](o+2) + hist[y+1+1][x+1+1](o+9+2); - simd4f h0 = min(temp0,nn)*n; - simd4f h1 = min(temp1,nn)*n; - simd4f h2 = min(temp2,nn)*n; - set_hog(hog,o+18,xx,yy, sum(h0)); - set_hog(hog,o+18+1,xx,yy, sum(h1)); - set_hog(hog,o+18+2,xx,yy, sum(h2)); - } - - - float temp[4]; - t.store(temp); - - // texture features - set_hog(hog,27,xx,yy, temp[0]); - set_hog(hog,28,xx,yy, temp[1]); - set_hog(hog,29,xx,yy, temp[2]); - set_hog(hog,30,xx,yy, temp[3]); - } - } - } - - // ------------------------------------------------------------------------------------ - - inline void create_fhog_bar_images ( - dlib::array<matrix<float> >& mbars, - const long w - ) - { - const long bdims = 9; - // Make the oriented lines we use to draw on each HOG cell. - mbars.resize(bdims); - dlib::array<array2d<unsigned char> > bars(bdims); - array2d<unsigned char> temp(w,w); - for (unsigned long i = 0; i < bars.size(); ++i) - { - assign_all_pixels(temp, 0); - draw_line(temp, point(w/2,0), point(w/2,w-1), 255); - rotate_image(temp, bars[i], i*-pi/bars.size()); - - mbars[i] = subm(matrix_cast<float>(mat(bars[i])), centered_rect(get_rect(bars[i]),w,w) ); - } - } - - } // end namespace impl_fhog - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename image_type, - typename T, - typename mm1, - typename mm2 - > - void extract_fhog_features( - const image_type& img, - dlib::array<array2d<T,mm1>,mm2>& hog, - int cell_size = 8, - int filter_rows_padding = 1, - int filter_cols_padding = 1 - ) - { - impl_fhog::impl_extract_fhog_features(img, hog, cell_size, filter_rows_padding, filter_cols_padding); - // If the image is too small then the above function outputs an empty feature map. - // But to make things very uniform in usage we require the output to still have the - // 31 planes (but they are just empty). - if (hog.size() == 0) - hog.resize(31); - } - - template < - typename image_type, - typename T, - typename mm - > - void extract_fhog_features( - const image_type& img, - array2d<matrix<T,31,1>,mm>& hog, - int cell_size = 8, - int filter_rows_padding = 1, - int filter_cols_padding = 1 - ) - { - impl_fhog::impl_extract_fhog_features(img, hog, cell_size, filter_rows_padding, filter_cols_padding); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename image_type, - typename T - > - void extract_fhog_features( - const image_type& img, - matrix<T,0,1>& feats, - int cell_size = 8, - int filter_rows_padding = 1, - int filter_cols_padding = 1 - ) - { - dlib::array<array2d<T> > hog; - extract_fhog_features(img, hog, cell_size, filter_rows_padding, filter_cols_padding); - feats.set_size(hog.size()*hog[0].size()); - for (unsigned long i = 0; i < hog.size(); ++i) - { - const long size = hog[i].size(); - set_rowm(feats, range(i*size, (i+1)*size-1)) = reshape_to_column_vector(mat(hog[i])); - } - } - -// ---------------------------------------------------------------------------------------- - - template < - typename image_type - > - matrix<double,0,1> extract_fhog_features( - const image_type& img, - int cell_size = 8, - int filter_rows_padding = 1, - int filter_cols_padding = 1 - ) - { - matrix<double, 0, 1> feats; - extract_fhog_features(img, feats, cell_size, filter_rows_padding, filter_cols_padding); - return feats; - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - inline point image_to_fhog ( - point p, - int cell_size = 8, - int filter_rows_padding = 1, - int filter_cols_padding = 1 - ) - { - // make sure requires clause is not broken - DLIB_ASSERT( cell_size > 0 && - filter_rows_padding > 0 && - filter_cols_padding > 0 , - "\t point image_to_fhog()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t cell_size: " << cell_size - << "\n\t filter_rows_padding: " << filter_rows_padding - << "\n\t filter_cols_padding: " << filter_cols_padding - ); - - // There is a one pixel border around the image. - p -= point(1,1); - // There is also a 1 "cell" border around the HOG image formation. - return p/cell_size - point(1,1) + point((filter_cols_padding-1)/2,(filter_rows_padding-1)/2); - } - -// ---------------------------------------------------------------------------------------- - - inline rectangle image_to_fhog ( - const rectangle& rect, - int cell_size = 8, - int filter_rows_padding = 1, - int filter_cols_padding = 1 - ) - { - // make sure requires clause is not broken - DLIB_ASSERT( cell_size > 0 && - filter_rows_padding > 0 && - filter_cols_padding > 0 , - "\t rectangle image_to_fhog()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t cell_size: " << cell_size - << "\n\t filter_rows_padding: " << filter_rows_padding - << "\n\t filter_cols_padding: " << filter_cols_padding - ); - - return rectangle(image_to_fhog(rect.tl_corner(),cell_size,filter_rows_padding,filter_cols_padding), - image_to_fhog(rect.br_corner(),cell_size,filter_rows_padding,filter_cols_padding)); - } - -// ---------------------------------------------------------------------------------------- - - inline point fhog_to_image ( - point p, - int cell_size = 8, - int filter_rows_padding = 1, - int filter_cols_padding = 1 - ) - { - // make sure requires clause is not broken - DLIB_ASSERT( cell_size > 0 && - filter_rows_padding > 0 && - filter_cols_padding > 0 , - "\t point fhog_to_image()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t cell_size: " << cell_size - << "\n\t filter_rows_padding: " << filter_rows_padding - << "\n\t filter_cols_padding: " << filter_cols_padding - ); - - // Convert to image space and then set to the center of the cell. - point offset; - - p = (p+point(1,1)-point((filter_cols_padding-1)/2,(filter_rows_padding-1)/2))*cell_size + point(1,1); - if (p.x() >= 0 && p.y() >= 0) offset = point(cell_size/2,cell_size/2); - if (p.x() < 0 && p.y() >= 0) offset = point(-cell_size/2,cell_size/2); - if (p.x() >= 0 && p.y() < 0) offset = point(cell_size/2,-cell_size/2); - if (p.x() < 0 && p.y() < 0) offset = point(-cell_size/2,-cell_size/2); - return p + offset; - } - -// ---------------------------------------------------------------------------------------- - - inline rectangle fhog_to_image ( - const rectangle& rect, - int cell_size = 8, - int filter_rows_padding = 1, - int filter_cols_padding = 1 - ) - { - // make sure requires clause is not broken - DLIB_ASSERT( cell_size > 0 && - filter_rows_padding > 0 && - filter_cols_padding > 0 , - "\t rectangle fhog_to_image()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t cell_size: " << cell_size - << "\n\t filter_rows_padding: " << filter_rows_padding - << "\n\t filter_cols_padding: " << filter_cols_padding - ); - - return rectangle(fhog_to_image(rect.tl_corner(),cell_size,filter_rows_padding,filter_cols_padding), - fhog_to_image(rect.br_corner(),cell_size,filter_rows_padding,filter_cols_padding)); - } - -// ---------------------------------------------------------------------------------------- -// ---------------------------------------------------------------------------------------- - - template < - typename T, - typename mm1, - typename mm2 - > - matrix<unsigned char> draw_fhog( - const dlib::array<array2d<T,mm1>,mm2>& hog, - const long cell_draw_size = 15, - const float min_response_threshold = 0.0 - ) - { - // make sure requires clause is not broken - DLIB_ASSERT( cell_draw_size > 0 && hog.size()==31, - "\t matrix<unsigned char> draw_fhog()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t cell_draw_size: " << cell_draw_size - << "\n\t hog.size(): " << hog.size() - ); - - dlib::array<matrix<float> > mbars; - impl_fhog::create_fhog_bar_images(mbars,cell_draw_size); - - // now draw the bars onto the HOG cells - matrix<float> himg(hog[0].nr()*cell_draw_size, hog[0].nc()*cell_draw_size); - himg = 0; - for (unsigned long d = 0; d < mbars.size(); ++d) - { - for (long r = 0; r < himg.nr(); r+=cell_draw_size) - { - for (long c = 0; c < himg.nc(); c+=cell_draw_size) - { - const float val = hog[d][r/cell_draw_size][c/cell_draw_size] + - hog[d+mbars.size()][r/cell_draw_size][c/cell_draw_size] + - hog[d+mbars.size()*2][r/cell_draw_size][c/cell_draw_size]; - if (val > min_response_threshold) - { - set_subm(himg, r, c, cell_draw_size, cell_draw_size) += val*mbars[d%mbars.size()]; - } - } - } - } - - const float thresh = mean(himg) + 4 * stddev(himg); - if (thresh != 0) - return matrix_cast<unsigned char>(upperbound(round(himg*255/thresh),255)); - else - return matrix_cast<unsigned char>(himg); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T - > - matrix<unsigned char> draw_fhog ( - const std::vector<matrix<T> >& hog, - const long cell_draw_size = 15, - const float min_response_threshold = 0.0 - ) - { - // make sure requires clause is not broken - DLIB_ASSERT( cell_draw_size > 0 && hog.size()==31, - "\t matrix<unsigned char> draw_fhog()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t cell_draw_size: " << cell_draw_size - << "\n\t hog.size(): " << hog.size() - ); - - // Just convert the input into the right object and then call the above draw_fhog() - // function on it. - dlib::array<array2d<T> > temp(hog.size()); - for (unsigned long i = 0; i < temp.size(); ++i) - { - temp[i].set_size(hog[i].nr(), hog[i].nc()); - for (long r = 0; r < hog[i].nr(); ++r) - { - for (long c = 0; c < hog[i].nc(); ++c) - { - temp[i][r][c] = hog[i](r,c); - } - } - } - return draw_fhog(temp,cell_draw_size, min_response_threshold); - } - -// ---------------------------------------------------------------------------------------- - - template < - typename T, - typename mm - > - matrix<unsigned char> draw_fhog( - const array2d<matrix<T,31,1>,mm>& hog, - const long cell_draw_size = 15, - const float min_response_threshold = 0.0 - ) - { - // make sure requires clause is not broken - DLIB_ASSERT( cell_draw_size > 0, - "\t matrix<unsigned char> draw_fhog()" - << "\n\t Invalid inputs were given to this function. " - << "\n\t cell_draw_size: " << cell_draw_size - ); - - dlib::array<matrix<float> > mbars; - impl_fhog::create_fhog_bar_images(mbars,cell_draw_size); - - // now draw the bars onto the HOG cells - matrix<float> himg(hog.nr()*cell_draw_size, hog.nc()*cell_draw_size); - himg = 0; - for (unsigned long d = 0; d < mbars.size(); ++d) - { - for (long r = 0; r < himg.nr(); r+=cell_draw_size) - { - for (long c = 0; c < himg.nc(); c+=cell_draw_size) - { - const float val = hog[r/cell_draw_size][c/cell_draw_size](d) + - hog[r/cell_draw_size][c/cell_draw_size](d+mbars.size()) + - hog[r/cell_draw_size][c/cell_draw_size](d+mbars.size()*2); - if (val > min_response_threshold) - { - set_subm(himg, r, c, cell_draw_size, cell_draw_size) += val*mbars[d%mbars.size()]; - } - } - } - } - - const float thresh = mean(himg) + 4 * stddev(himg); - if (thresh != 0) - return matrix_cast<unsigned char>(upperbound(round(himg*255/thresh),255)); - else - return matrix_cast<unsigned char>(himg); - } - -// ---------------------------------------------------------------------------------------- - -} - -#endif // DLIB_fHOG_Hh_ - |