summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/image_transforms/fhog.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/image_transforms/fhog.h')
-rw-r--r--ml/dlib/dlib/image_transforms/fhog.h1404
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_
-