/** * @file PHOGFeature.cpp * @brief Implementation of the PHOG-Features and corresponding Kernel as done by Anna Bosch et al. * @author Alexander Lütz * @date 15/11/2011 */ #include "PHOGFeature.h" using namespace std; using namespace OBJREC; using namespace NICE; /** protected things*/ /** * @brief Calculates the PHOG-Pyramide for given gradient images (idea of Anna Bosch and Andrew Zisserman) * @author Alexander Lütz * @date 15/11/2011 */ void PHOGFeature::calculate_PHOG_Pyramide(const NICE::Image & gradient_orientations, const NICE::ImageT & gradient_magnitudes, std::vector< std::vector > & PHOG_descriptor) { float sum_of_all = 0.0; float sum_of_level = 0.0; std::vector one_collecting_vector; one_collecting_vector.clear(); std::vector HoG (number_Of_Bins); for (int j = 0; j < gradient_orientations.height(); j++) for (int i = 0; i < gradient_orientations.width(); i++) { int orientation (gradient_orientations(i,j)); if (( (orientation<0) || ((uint)orientation>=HoG.size())) && verbose) { cerr << "orientation is " << orientation << " and does not fit to HoG.size(): " << HoG.size() << endl; cerr << "i: " << i << " j: " << j << " gradient_orientations.width() : " << gradient_orientations.width() << " gradient_orientations.height() : " << gradient_orientations.height() << endl; } HoG[gradient_orientations(i,j)] += gradient_magnitudes(i,j); sum_of_all += gradient_magnitudes(i,j); sum_of_level += gradient_magnitudes(i,j); } switch(histrogram_concatenation) { case 0: { if (sum_of_level != 0.0) //normalize the descriptor-entries { for (std::vector::iterator HoG_it = HoG.begin(); HoG_it != HoG.end(); HoG_it++) { *HoG_it /= sum_of_level; } } PHOG_descriptor.push_back(HoG); break; } case 1: { if (sum_of_level != 0.0) //normalize the descriptor-entries { for (std::vector::iterator HoG_it = HoG.begin(); HoG_it != HoG.end(); HoG_it++) { *HoG_it /= sum_of_level; } } PHOG_descriptor.push_back(HoG); break; } case 2: { one_collecting_vector.insert(one_collecting_vector.begin()+one_collecting_vector.size(), HoG.begin(), HoG.end()); break; } } sum_of_all += sum_of_level; if (verbose) cerr << "PHOGFeature::calculate_PHOG_Pyramide -- Level 0 calculated, working on finer levels" << endl; if (verbose) cerr << "gradient_orientations.width(): " << gradient_orientations.width() << " gradient_orientations.height(): " << gradient_orientations.height() << endl; //further levels for (int level = 1; level < number_of_Levels; level++) { if (verbose) cerr << "PHOGFeature::calculate_PHOG_Pyramide -- working on level "<< level << endl; if (like_AnnaBosch) { int step_x = (int) floor(gradient_orientations.width() / pow(2.0f,level) ); int step_y = (int) floor(gradient_orientations.height() / pow(2.0f,level) ); vector PHoG_level; int run_y = 0; for (int y_counter = 0; y_counter < pow(2.0,level) ; y_counter++) { int run_x = 0; for (int x_counter = 0; x_counter < pow(2.0,level) ; x_counter++) { vector HoG_local (number_Of_Bins); float sum_of_hog(0.0); //check, wether rectangle lies on the boundary, if so, then correct the max-step int y_max = (run_y + step_y); if (gradient_orientations.height() < y_max) y_max = gradient_orientations.height(); int x_max = (run_x + step_x); if (gradient_orientations.width() < x_max) x_max = gradient_orientations.width(); for (int j = run_y; j < y_max; j++) for (int i = run_x; i < x_max; i++) { int orientation = 0; try{ orientation = gradient_orientations(i,j); } catch( ... ) { cerr << "WARNING: PHOGFeature::calculate_PHOG_Pyramide gradient_orientations(i,j) not possible. (i,j): " << i << " " << j << endl; } float magnitude = 0.0; try{ magnitude = gradient_magnitudes(i,j); } catch( ... ) { cerr << "WARNING: PHOGFeature::calculate_PHOG_Pyramide radient_magnitudes(i,j) not possible. (i,j): " << i << " " << j << endl; } HoG_local[orientation] += magnitude; sum_of_hog += magnitude; } sum_of_level += sum_of_hog; switch(histrogram_concatenation) { case 0: { if (sum_of_hog != 0.0) //normalize the descriptor-entries { for (std::vector::iterator hog_it = HoG_local.begin(); hog_it != HoG_local.end(); hog_it++) { *hog_it /= sum_of_hog; } } PHOG_descriptor.push_back(HoG_local); break; } case 1: { for (std::vector::const_iterator foo = HoG_local.begin(); foo != HoG_local.end(); foo++) { PHoG_level.insert(PHoG_level.begin()+PHoG_level.size(), HoG_local.begin(), HoG_local.end()); } break; } case 2: { PHoG_level.insert(PHoG_level.begin()+PHoG_level.size(), HoG_local.begin(), HoG_local.end()); break; } } run_x = run_x + step_x; } run_y = run_y + step_y; } sum_of_all += sum_of_level; switch(histrogram_concatenation) { case 0: { break; } case 1: { if (sum_of_level != 0.0) //normalize the descriptor-entries { for (std::vector::iterator Level_it = PHoG_level.begin(); Level_it != PHoG_level.end(); Level_it++) { *Level_it /= sum_of_level; } } PHOG_descriptor.push_back(PHoG_level); break; } case 2: { one_collecting_vector.insert(one_collecting_vector.begin()+one_collecting_vector.size(), PHoG_level.begin(), PHoG_level.end()); break; } } } else //better than anna bosch { int step_x = (int) ceil(gradient_orientations.width() / pow(2.0f,level) ); int step_y = (int) ceil(gradient_orientations.height() / pow(2.0f,level) ); if (verbose) cerr << "step_x: " << step_x << " step_y: " << step_y << endl; std::vector PHoG_level; int run_y = 0; for (int y_counter = 0; y_counter < pow(2.0f,level) ; y_counter++) { int run_x = 0; if (verbose) cerr << "run_y: " << run_y << endl; for (int x_counter = 0; x_counter < pow(2.0f,level) ; x_counter++) { if (verbose) cerr << "run_x: " << run_x << endl; float sum_of_hog(0.0); vector HoG_local (number_Of_Bins); //check, wether rectangle lies on the boundary, if so, then correct the max-step int y_max = (run_y + step_y); if (gradient_orientations.height() < y_max) { if (verbose) cerr << "y_max old:: " << y_max << " y_max_new: "<=HoG_local.size())) { cerr << "orientation is " << orientation << " and does not fit to HoG_local.size(): " << HoG_local.size() << endl; cerr << "i: " << i << " j: " << j << " gradient_orientations.width() : " << gradient_orientations.width() << " gradient_orientations.height() : " << gradient_orientations.height() << endl; } try{ HoG_local[orientation] += magnitude; } catch( ... ) { cerr << "WARNING: PHOGFeature::calculate_PHOG_Pyramide HoG_local[orientation] += magnitude not possible. orientation: " << orientation << " magnitude " << magnitude << endl; } sum_of_hog += magnitude; } sum_of_level += sum_of_hog; switch(histrogram_concatenation) { case 0: { if (sum_of_hog != 0.0) //normalize the descriptor-entries { for (std::vector::iterator hog_it = HoG_local.begin(); hog_it != HoG_local.end(); hog_it++) { *hog_it /= sum_of_hog; } } PHOG_descriptor.push_back(HoG_local); break; } case 1: { for (std::vector::const_iterator foo = HoG_local.begin(); foo != HoG_local.end(); foo++) { PHoG_level.insert(PHoG_level.begin()+PHoG_level.size(), HoG_local.begin(), HoG_local.end()); } break; } case 2: { PHoG_level.insert(PHoG_level.begin()+PHoG_level.size(), HoG_local.begin(), HoG_local.end()); break; } } run_x = run_x + step_x; } run_y = run_y + step_y; } sum_of_all += sum_of_level; switch(histrogram_concatenation) { case 0: { break; } case 1: { if (sum_of_level != 0.0) //normalize the descriptor-entries { for (std::vector::iterator Level_it = PHoG_level.begin(); Level_it != PHoG_level.end(); Level_it++) { *Level_it /= sum_of_level; } } PHOG_descriptor.push_back(PHoG_level); break; } case 2: { one_collecting_vector.insert(one_collecting_vector.begin()+one_collecting_vector.size(), PHoG_level.begin(), PHoG_level.end()); break; } } } } if (histrogram_concatenation == ALL) { if (sum_of_all != 0.0) //normalize the descriptor-entries { for (std::vector::iterator it = one_collecting_vector.begin(); it != one_collecting_vector.end(); it++) { *it /= sum_of_all; } } PHOG_descriptor.push_back(one_collecting_vector); } } /** * @brief Calculates resulting PHOG-Features for the specified ROI in the given image * @author Alexander Lütz * @date 15/11/2011 */ std::vector< std::vector > PHOGFeature::calculate_PHOG_Features(const NICE::Image & orig_Image, const NICE::Rect & roi) { if (like_AnnaBosch) //not supported in that version, 'cause ! { std::cerr << "PHOGFeature::calculate_PHOG_Features is not supported right now" << std::endl; // //Canny Edge Detector // Image canny_Image; // canny_Image = (*canny(orig_Image, 10,30) ); // // //gradient-calculation // GrayImage16s* grad_x_Image= sobelX(canny_Image); // GrayImage16s* grad_y_Image = sobelY(canny_Image); // if (verbose) cerr << "gradient-calculation done" << endl; // // //gradient-orientation-calculation // NICE::Image gradient_orientations; // image_tool.calculateGradientOrientations( *grad_x_Image, *grad_y_Image, number_Of_Bins, gradient_orientations, unsignedBins); // if (verbose) cerr << "gradient-orientation-calculation done" << endl; // // //gradient-magnitude-calculation // //maybe this is not good - implicit cast from int to float in image structure // NICE::Image* gradient_magnitudes_int = gradientStrength( (*grad_x_Image), (*grad_y_Image) ); // NICE::ImageT gradient_magnitudes(orig_Image.width(), orig_Image.height()); // for (int y = 0; y < orig_Image.height(); y++) // for (int x = 0; x < orig_Image.width(); x++) // { // gradient_magnitudes.setPixel(x,y,(*gradient_magnitudes_int).getPixel(x,y)); // } // if (verbose) cerr << "gradient-magnitude-calculation done" << endl; // // NICE::Image go_roi (gradient_orientations.subImage(roi)); // NICE::ImageT gm_roi (gradient_magnitudes.subImage(roi)); // // //pyramide-calculation // std::vector< std::vector > PHOG_pyramide; // calculate_PHOG_Pyramide(go_roi, gm_roi, PHOG_pyramide); // // if (verbose) cerr << "Pyramide-calculation done" << endl; return PHOG_pyramide; } else { //gradient-calculation NICE::ImageT grad_x_Image; NICE::ImageT grad_y_Image; image_tool.calculateGradients(orig_Image, grad_x_Image, grad_y_Image ); if (verbose) cerr << "gradient-calculation done" << endl; //gradient-orientation-calculation NICE::Image gradient_orientations; image_tool.calculateGradientOrientations(grad_x_Image, grad_y_Image, number_Of_Bins, gradient_orientations, unsignedBins); if (verbose) cerr << "gradient-orientation-calculation done" << endl; //gradient-magnitude-calculation NICE::ImageT gradient_magnitudes; image_tool.calculateGradientMagnitudes(grad_x_Image, grad_y_Image, gradient_magnitudes); if (verbose) cerr << "gradient-magnitude-calculation done" << endl; NICE::Image go_roi (gradient_orientations.subImage(roi)); NICE::ImageT gm_roi (gradient_magnitudes.subImage(roi)); //pyramide-calculation std::vector< std::vector > PHOG_pyramide; calculate_PHOG_Pyramide(go_roi, gm_roi, PHOG_pyramide); if (verbose) cerr << "Pyramide-calculation done" << endl; return PHOG_pyramide; } } //TODO ebenso für Farbbilder, falls das erwünscht ist. Frau Bosch macht einfach nur eine Grauwertkonvertierunt, also auch nicht so schön, wie Dalal und Triggs.! /** public things*/ /** * @brief Simple Default Constructor * @author Alexander Lütz * @date 15/11/2011 */ PHOGFeature::PHOGFeature() { image_tool = OBJREC::Image_tools(); number_Of_Bins = 9; unsignedBins = true; number_of_Levels = 3; like_AnnaBosch = false; distances_only_between_levels = true; histrogram_concatenation = NONE; verbose = false; } /** * @brief Recommended Constructor * @author Alexander Lütz * @date 15/11/2011 */ PHOGFeature::PHOGFeature( const Config *conf, std::string section) { image_tool = OBJREC::Image_tools(); number_Of_Bins = conf->gI("PHOGFeature", "number_Of_Bins", 9); unsignedBins = conf->gB("PHOGFeature", "unsignedBins", true); number_of_Levels = conf->gI("PHOGFeature", "number_of_Levels", 3); like_AnnaBosch = conf->gB("PHOGFeature", "like_AnnaBosch", false); distances_only_between_levels = conf->gB("PHOGFeature", "distances_only_between_levels", true); switch(conf->gI("PHOGFeature", "histrogram_concatenation", 0) ) { case 0: {histrogram_concatenation = NONE; break;} case 1: {histrogram_concatenation = LEVELWISE; break;} case 2: {histrogram_concatenation = ALL; break;} } verbose = conf->gB("PHOGFeature", "verbose", false); } /** * @brief Simple Destructor * @author Alexander Lütz * @date 15/11/2011 */ PHOGFeature::~PHOGFeature() { } /** * @brief Creating the PHOG-featureVectores of all trainingexamples * @author Alexander Lütz * @date 15/11/2011 */ // std::vector > > PHOGFeature::createAllFeatureVectors(const OBJREC::LabeledSet::Permutation & order) // { // // std::vector > > PHOG_Features_all_images; // // ProgressBar pb_createFV ("PHOGFeature::createAllFeatureVectors"); // pb_createFV.show(); // // uint k = 0; // for ( LabeledSet::Permutation::const_iterator i = order.begin(); i != order.end(); i++,k++ ) // { // string imgfilename = (*i).second->img(); // // NICE::Image img(imgfilename); // // NICE::Rect roi = NICE::Rect(0,0,img.width(),img.height()); // vector > PHOG = calculate_PHOG_Features(img, roi); // // PHOG_Features_all_images.push_back ( PHOG ); // // pb_createFV.update ( order.size() ); // } // // // hide the last progress bar // pb_createFV.hide(); // // return PHOG_Features_all_images; // } /** * @brief Creating the PHOG-featureVectores of all trainingexamples * @author Alexander Lütz * @date 15/11/2011 */ // std::vector > > PHOGFeature::createAllFeatureVectors(const OBJREC::LabeledSet::Permutation & order, std::vector< NICE::Image > & gradient_orientations, std::vector > & gradient_magnitudes) // { // // std::vector > > PHOG_Features_all_images; // // cerr << "Calculating gradient orientations." << endl; // gradient_orientations = calculate_gradient_orientations(order); // cerr << "Calculating gradient magnitudes." << endl; // gradient_magnitudes = calculate_gradient_magnitudes(order); // // ProgressBar pb_quantization ("PHOGFeature::createAllFeatureVectors"); // pb_quantization.show(); // // uint k = 0; // for ( LabeledSet::Permutation::const_iterator i = order.begin(); i != order.end(); i++,k++ ) // { // std::string imgfilename = (*i).second->img(); // // NICE::Image img(imgfilename); // // std::vector > PHOG; // calculate_PHOG_Pyramide(gradient_orientations[k], gradient_magnitudes[k], PHOG); // // PHOG_Features_all_images.push_back ( PHOG ); // // pb_quantization.update ( order.size() ); // } // // // hide the last progress bar // pb_quantization.hide(); // // return PHOG_Features_all_images; // } /** * @brief Creating the PHOG-featureVectores of all trainingexamples * @author Alexander Lütz * @date 15/11/2011 */ // // // std::vector > > PHOGFeature::createAllFeatureVectors(const OBJREC::LabeledSet::Permutation & order, const std::vector & trainSelection) // // // { // // // // // // std::vector > > PHOG_Features_all_images; // // // // // // ProgressBar pb_quantization ("PHOGFeature::createAllFeatureVectors"); // // // pb_quantization.show(); // // // // // // uint k = 0; // // // for ( std::vector::const_iterator i = trainSelection.begin(); i != trainSelection.end(); i++,k++ ) // // // { // // // if (verbose) cerr << " Image number " << *i << " will be treated now" << endl; // // // string imgfilename = order[*i].second->img(); // // // // // // NICE::Image img(imgfilename); // // // // // // NICE::Rect roi = NICE::Rect(0,0,img.width(),img.height()); // // // vector > PHOG = calculate_PHOG_Features(img, roi); // // // // // // PHOG_Features_all_images.push_back ( PHOG ); // // // // // // pb_quantization.update ( trainSelection.size() ); // // // } // // // // // // // hide the last progress bar // // // pb_quantization.hide(); // // // // // // return PHOG_Features_all_images; // // // } // // // // // // /** * @brief Creating the PHOG-featureVectore for one trainingexample * @author Alexander Lütz * @date 15/11/2011 */ std::vector > PHOGFeature::createOneFeatureVector(const std::string & imgfilename, const NICE::Rect & ROI) { NICE::Image img(imgfilename); std::vector > PHOG (calculate_PHOG_Features(img, ROI)); return PHOG; } /** * @brief Creating the PHOG-featureVectore for one trainingexample * @author Alexander Lütz * @date 15/11/2011 */ std::vector > PHOGFeature::createOneFeatureVector(const std::string & imgfilename) { NICE::Image img(imgfilename); NICE::Rect ROI(0,0,img.width(), img.height()); std::vector > PHOG (calculate_PHOG_Features(img, ROI)); return PHOG; } /** * @brief Creating the PHOG-featureVectore for one trainingexample * @author Alexander Lütz * @date 15/11/2011 */ std::vector > PHOGFeature::createOneFeatureVector(const NICE::Image img, const NICE::Rect & ROI) { std::vector > PHOG (calculate_PHOG_Features(img, ROI)); return PHOG; } /** * @brief Creating the PHOG-featureVectore for one trainingexample * @author Alexander Lütz * @date 15/11/2011 */ std::vector > PHOGFeature::createOneFeatureVector(const NICE::Image img) { NICE::Rect ROI(0,0,img.width(), img.height()); std::vector > PHOG (calculate_PHOG_Features(img, ROI)); return PHOG; } /** * @brief computes the featurevector for the given image, which is already converted to a gradient-image, just considering features in the specified ROI * @author Alexander Lütz * @date 15/11/2011 */ std::vector< std::vector > PHOGFeature::createOneFeatureVectorDirect(NICE::Image & gradient_orientations, NICE::ImageT & gradient_magnitudes, const NICE::Rect & ROI) { NICE::Image ROI_go (gradient_orientations.subImage(ROI)); NICE::ImageT ROI_gm (gradient_magnitudes.subImage(ROI)); std::vector< std::vector > PHOG_pyramide; calculate_PHOG_Pyramide(ROI_go, ROI_gm, PHOG_pyramide); return PHOG_pyramide; } /** * @brief computes the featurevector for the given image, which is already converted to a gradient-image, considering the whole image * @author Alexander Lütz * @date 15/11/2011 */ std::vector< std::vector > PHOGFeature::createOneFeatureVectorDirect(NICE::Image & gradient_orientations, NICE::ImageT & gradient_magnitudes) { NICE::Image ROI_go (gradient_orientations); NICE::ImageT ROI_gm (gradient_magnitudes); std::vector< std::vector > PHOG_pyramide; calculate_PHOG_Pyramide(ROI_go, ROI_gm, PHOG_pyramide ); return PHOG_pyramide; } // // // // /** // // * @brief computes the gradient-orientation-images of all training-images // // * @author Alexander Lütz // // * @date 15/11/2011 // // */ // // std::vector< NICE::Image> PHOGFeature::calculate_gradient_orientations(const OBJREC::LabeledSet::Permutation & order) // // { // // std::vector< NICE::Image> gradient_orientations; // // // // for(OBJREC::LabeledSet::Permutation::const_iterator i = order.begin(); i != order.end(); i++) // // { // // string filename = (*i).second->img(); // // NICE::Image img (filename); // // //gradient-calculation // // NICE::ImageT grad_x_Image; // // NICE::ImageT grad_y_Image; // // image_tool.calculateGradients(img, grad_x_Image, grad_y_Image ); // // // // //gradient-orientation-calculation // // NICE::Image gradient_orientation_image; // // image_tool.calculateGradientOrientations(grad_x_Image, grad_y_Image, number_Of_Bins, gradient_orientation_image, unsignedBins); // // // // gradient_orientations.push_back(gradient_orientation_image); // // } // // // // return gradient_orientations; // // } // // /** // * @brief computes the gradient-magnitudes-images of all training-images // * @author Alexander Lütz // * @date 15/11/2011 // */ // std::vector< NICE::ImageT > PHOGFeature::calculate_gradient_magnitudes(const OBJREC::LabeledSet::Permutation & order) // { // std::vector< NICE::ImageT > gradient_magnitudes; // // for(OBJREC::LabeledSet::Permutation::const_iterator i = order.begin(); i != order.end(); i++) // { // string filename = (*i).second->img(); // Image img (filename); // //gradient-calculation // NICE::ImageT grad_x_Image; // NICE::ImageT grad_y_Image; // image_tool.calculateGradients(img, grad_x_Image, grad_y_Image ); // // //gradient-orientation-calculation // NICE::ImageT gradient_magnitude_image; // image_tool.calculateGradientMagnitudes(grad_x_Image, grad_y_Image, gradient_magnitude_image); // // gradient_magnitudes.push_back(gradient_magnitude_image); // } // // return gradient_magnitudes; // } /** * @brief computes the gradient-orientation-images of all training-images * @author Alexander Lütz * @date 15/11/2011 */ NICE::Image PHOGFeature::calculate_gradient_orientations(const std::string & imgfilenam) { NICE::Image gradient_orientations; NICE::Image img (imgfilenam); //gradient-calculation NICE::ImageT grad_x_Image; NICE::ImageT grad_y_Image; image_tool.calculateGradients(img, grad_x_Image, grad_y_Image ); //gradient-orientation-calculation NICE::Image gradient_orientation_image; image_tool.calculateGradientOrientations(grad_x_Image, grad_y_Image, number_Of_Bins, gradient_orientation_image, unsignedBins); return gradient_orientations; } /** * @brief computes the gradient-magnitudes-images of all training-images * @author Alexander Lütz * @date 15/11/2011 */ NICE::ImageT PHOGFeature::calculate_gradient_magnitudes(const std::string & imgfilename) { NICE::ImageT gradient_magnitudes; Image img (imgfilename); //gradient-calculation NICE::ImageT grad_x_Image; NICE::ImageT grad_y_Image; image_tool.calculateGradients(img, grad_x_Image, grad_y_Image ); //gradient-orientation-calculation NICE::ImageT gradient_magnitude_image; image_tool.calculateGradientMagnitudes(grad_x_Image, grad_y_Image, gradient_magnitude_image); return gradient_magnitudes; } /** * @brief Compute the resulting kernel measuring the distance between the given feature-vectores * @author Alexander Lütz * @date 15/11/2011 */ void PHOGFeature::calculate_Kernel_from_Features(const std::vector > > & PHoG_Features, NICE::Matrix & PHoG_Kernel){ // ProgressBar pb_kernelcalc ("PHOGFeature::Kernel Calculation"); // pb_kernelcalc.show(); PHoG_Kernel = NICE::Matrix(PHoG_Features.size(), PHoG_Features.size(), 0.0); uint ik = 0; for ( std::vector< std::vector < std::vector > >::const_iterator i = PHoG_Features.begin();i != PHoG_Features.end(); i++,ik++ ) { uint jk = ik; for ( std::vector< std::vector< std::vector > >::const_iterator j = i; j != PHoG_Features.end(); j++,jk++ ) { double kernelValue (measureDistance(*i,*j)); PHoG_Kernel(ik,jk) = kernelValue; PHoG_Kernel(jk,ik) = kernelValue; } // pb_kernelcalc.update ( PHoG_Features.size() ); } } /** * @brief function which computes the exp^(-Chi^2)-kernel of two PHOG-feature-vectores a and b * @author Alexander Lütz * @date 15/11/2011 */ double PHOGFeature::measureDistance ( const std::vector > & a, const std::vector > & b ) { double expChi_value = 0.0; if (a.size() != b.size() ) { cerr << "a.size(): " << a.size() << " and b.size(): " << b.size() << endl; fthrow(IOException, "Sizes of PHOG-Feature-vectores do not fit!"); } for (uint i = 0; i < a.size(); i++) //run over every HoG-Level { std::vector a_intern = a[i]; std::vector b_intern = b[i]; double chi_value = 0.0; if (a_intern.size() != b_intern.size() ) { cerr << "a_intern.size(): " << a_intern.size() << " and b_intern.size(): " << b_intern.size() << endl; fthrow(IOException, "Sizes of PHOG-Feature-vectores do not fit!"); } for (uint j = 0; j < a_intern.size(); j++) //run over every HoG-entry of this level { float u = a_intern[j]; float v = b_intern[j]; float s = ( u + v ); if ( fabs(s) < 10e-6 ) continue; float d = u-v; chi_value += d*d / s; } chi_value *= 0.5; expChi_value += exp(-chi_value); } expChi_value /= a.size(); //normalize to be in between zero and one return expChi_value; } /** * @brief Simply set the verbose-flag * @author Alexander Lütz * @date 15/11/2011 */ void PHOGFeature::set_verbose(const bool & new_verbose){ verbose = new_verbose; }