void HOGFeatures<T>::pyramid(const Mat& im, vectorMat& pyrafeatures) { // calculate the scaling factor Size_<float> imsize = im.size(); nscales_ = 1 + floor(log(min(imsize.height, imsize.width)/(5.0f*(float)binsize_))/log(sfactor_)); vectorMat pyraimages; pyraimages.resize(nscales_); pyrafeatures.clear(); pyrafeatures.resize(nscales_); pyraimages.resize(nscales_); scales_.clear(); scales_.resize(nscales_); // perform the non-power of two scaling // TODO: is this the most intuitive way to represent scaling? #ifdef _OPENMP #pragma omp parallel for #endif for (unsigned int i = 0; i < interval_; ++i) { Mat scaled; resize(im, scaled, imsize * (1.0f/pow(sfactor_,(int)i))); pyraimages[i] = scaled; scales_[i] = pow(sfactor_,(int)i)*binsize_; // perform subsequent power of two scaling for (unsigned int j = i+interval_; j < nscales_; j+=interval_) { Mat scaled2; pyrDown(scaled, scaled2); pyraimages[j] = scaled2; scales_[j] = 2 * scales_[j-interval_]; scaled2.copyTo(scaled); } } // perform the actual feature computation, in parallel if possible #ifdef _OPENMP #pragma omp parallel for #endif for (unsigned int n = 0; n < nscales_; ++n) { Mat feature; Mat padded; switch (im.depth()) { case CV_32F: features<float>(pyraimages[n], feature); break; case CV_64F: features<double>(pyraimages[n], feature); break; case CV_8U: features<uint8_t>(pyraimages[n], feature); break; case CV_16U: features<uint16_t>(pyraimages[n], feature); break; default: CV_Error(cv::Error::StsUnsupportedFormat, "Unsupported image type"); break; } //copyMakeBorder(feature, padded, 3, 3, 3*flen_, 3*flen_, BORDER_CONSTANT, 0); //boundaryOcclusionFeature(padded, flen_, 3); pyrafeatures[n] = feature; } }
/*! @brief return the filters for all mixtures of a part * * @param out the filters to return */ void filters(vectorMat& out) const { out.clear(); for (unsigned int m = 0; m < filterid_[self_].size(); ++m) { out.push_back((*filtersw_)[(*filterid_)[self_][m]]); } }