histogram_of_oriented_gradients.cpp
Go to the documentation of this file.
00001 
00002 #include <jsk_perception/histogram_of_oriented_gradients.h>
00003 
00004 HOGFeatureDescriptor::HOGFeatureDescriptor(
00005     const int cell_size, const int block_per_cell,
00006     const int n_bins, const float angle) :
00007   CELL(cell_size),
00008   BLOCK(block_per_cell),
00009   ANGLE(angle),
00010   N_BINS(n_bins) {
00011   this->BINS_ANGLE = this->ANGLE / this->N_BINS;
00012 }
00013 
00014 void HOGFeatureDescriptor::bilinearBinVoting(
00015     const float &angle, int &lower_index, int &higher_index) {
00016     float nearest_lower = FLT_MAX;
00017     float nearest_higher = FLT_MAX;
00018     lower_index = 0;
00019     higher_index = 0;
00020     for (int i = BINS_ANGLE/2; i < ANGLE; i += BINS_ANGLE) {
00021        float distance = abs(angle - i);
00022         if (i < angle) {
00023             if (distance < nearest_lower) {
00024                 nearest_lower = distance;
00025                 lower_index = i;
00026             }
00027         } else {
00028             if (distance < nearest_higher) {
00029                 nearest_higher = distance;
00030                 higher_index = i;
00031             }
00032         }
00033     }
00034 }
00035 
00036 void HOGFeatureDescriptor::imageGradient(
00037     const cv::Mat &image, cv::Mat &hog_bins) {
00038     cv::Mat xsobel;
00039     cv::Mat ysobel;
00040     cv::Sobel(image, xsobel, CV_32F, 1, 0, 7);
00041     cv::Sobel(image, ysobel, CV_32F, 0, 1, 7);
00042     cv::Mat Imag;
00043     cv::Mat Iang;
00044     cv::cartToPolar(xsobel, ysobel, Imag, Iang, true);
00045     cv::add(Iang, cv::Scalar(ANGLE), Iang, Iang < 0);
00046     cv::add(Iang, cv::Scalar(-ANGLE), Iang, Iang >= ANGLE);
00047     cv::Mat orientation_histogram;
00048     for (int j = 0; j < image.rows; j += CELL) {
00049         for (int i = 0; i < image.cols; i += CELL) {
00050            cv::Rect rect = cv::Rect(i, j, CELL, CELL);
00051            if ((rect.x + rect.width <= image.cols) &&
00052                (rect.y + rect.height <= image.rows)) {
00053               cv::Mat bin = cv::Mat::zeros(1, N_BINS, CV_32F);
00054                 for (int y = rect.y; y < (rect.y + rect.height); y++) {
00055                     for (int x = rect.x; x < (rect.x + rect.width); x++) {
00056                        float angle = static_cast<float>(Iang.at<float>(y, x));
00057                        int l_bin;
00058                        int h_bin;
00059                        this->bilinearBinVoting(angle, l_bin, h_bin);
00060                        float l_ratio = 1 - (angle - l_bin)/BINS_ANGLE;
00061                        float h_ratio = 1 + (angle - h_bin)/BINS_ANGLE;
00062                        int l_index = (l_bin-(BINS_ANGLE/2))/BINS_ANGLE;
00063                        int h_index = (h_bin-(BINS_ANGLE/2))/BINS_ANGLE;
00064                         bin.at<float>(0, l_index) +=
00065                            (Imag.at<float>(y, x) * l_ratio);
00066                         bin.at<float>(0, h_index) +=
00067                            (Imag.at<float>(y, x) * h_ratio);
00068                     }
00069                 }
00070                 orientation_histogram.push_back(bin);
00071             }
00072         }
00073     }
00074     hog_bins = orientation_histogram.clone();
00075 }
00076 
00077 cv::Mat HOGFeatureDescriptor::blockGradient(
00078     const int col, const int row, cv::Mat &bins) {
00079     cv::Mat block_hogMD = cv::Mat(cv::Size(N_BINS * BLOCK * BLOCK, 1), CV_32F);
00080     int icounter = 0;
00081     for (int j = row; j < (row + BLOCK); j++) {
00082        for (int i = col; i < (col + BLOCK); i++) {
00083           int index = (j * CELL) + i;
00084           for (int k = 0; k < N_BINS; k++) {
00085              block_hogMD.at<float>(0, icounter++) = bins.at<float>(index);
00086           }
00087         }
00088     }
00089     return block_hogMD;
00090 }
00091 
00092 void HOGFeatureDescriptor::getHOG(
00093     const cv::Mat &image, cv::Mat &bins, cv::Mat &featureMD) {
00094     for (int j = 0; j < image.rows; j += CELL) {
00095        for (int i = 0; i < image.cols; i += CELL) {
00096           cv::Rect rect = cv::Rect(i, j, CELL*BLOCK, CELL*BLOCK);
00097             if ((rect.x + rect.width <= image.cols) &&
00098                 (rect.y + rect.height <= image.rows)) {
00099                cv::Mat hogMD = this->blockGradient(rect.x, rect.y, bins);
00100                normalize(hogMD, hogMD, 1, 0, CV_L2);
00101                featureMD.push_back(hogMD);
00102             }
00103         }
00104     }
00105 }
00106 
00107 cv::Mat HOGFeatureDescriptor::computeHOG(
00108     const cv::Mat &img) {
00109     cv::Mat image = img.clone();
00110     if (image.type() != CV_8U) {
00111        cv::cvtColor(image, image, CV_BGR2GRAY);
00112     }
00113     cv::Mat bins;
00114     this->imageGradient(image, bins);
00115     cv::Mat featureMD;
00116     getHOG(image, bins, featureMD);
00117     featureMD = featureMD.reshape(1, 1);
00118     return featureMD;
00119 }
00120 
00121 template<typename T>
00122 T HOGFeatureDescriptor::computeHOGHistogramDistances(
00123     const cv::Mat &patch, std::vector<cv::Mat> &imageHOG,
00124     const int distance_type) {
00125     T sum = 0.0;
00126     T argMinDistance = FLT_MAX;
00127     for (int i = 0; i < imageHOG.size(); i++) {
00128        cv::Mat img_hog = imageHOG[i];
00129        T d = compareHist(patch, img_hog, distance_type);
00130         if (d < argMinDistance) {
00131             argMinDistance = static_cast<double>(d);
00132         }
00133     }
00134     sum = static_cast<T>(argMinDistance);
00135     return static_cast<T>(sum);
00136 }


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Tue Jul 2 2019 19:41:07