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


jsk_perception
Author(s): Manabu Saito, Ryohei Ueda
autogenerated on Wed Sep 16 2015 04:36:15