I modified the predict functions from LBPH part (the same code can be applied to eigenfaces and fisherfaces parts):
void LBPH::predict(InputArray _src, std::vector<int> &minClass, std::vector<double> &minDist, int maxN) const {
if (_histograms.empty()) {
// throw error if no data (or simply return -1?)
String error_message = "This LBPH model is not computed yet. Did you call the train method?";
CV_Error(Error::StsBadArg, error_message);
}
Mat src = _src.getMat();
// get the spatial histogram from input image
Mat lbp_image = elbp(src, _radius, _neighbors);
Mat query = spatial_histogram(
lbp_image, /* lbp_image */
static_cast<int>(std::pow(2.0, static_cast<double>(_neighbors))), /* number of possible patterns */
_grid_x, /* grid size x */
_grid_y, /* grid size y */
true /* normed histograms */);
// find first maxN nearest neighbors
// using priority for keeping maxN min distances and maxN min classes
// remember to include queue header file and algorithm for greater<double>
std::priority_queue<double, std::vector<double>, std::greater<double>> minDist1;
std::priority_queue<int, std::vector<int>, std::greater<int>> minClass1;
for (size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++) {
double dist = compareHist(_histograms[sampleIdx], query, HISTCMP_CHISQR_ALT);
if (dist < _threshold)
{
if (minDist1.size() < maxN)
{
minDist1.push(dist);
minClass1.push(_labels.at<int>((int)sampleIdx));
}
else if (dist < minDist1.top())
{
minDist1.pop();
minClass1.pop();
minDist1.push(dist);
minClass1.push(_labels.at<int>((int)sampleIdx));
}
}
}
minDist = std::vector<double>(minDist1.size());
minClass = std::vector<int>(minClass1.size());
// storing the results back to vector objects
while (!minDist1.empty())
{
minDist.emplace_back(minDist1.top());
minClass.emplace_back(minClass1.top());
minDist1.pop();
minClass1.pop();
}
}
std::vector<std::pair<int, double>> LBPH::predict(InputArray _src, int maxN) const {
std::vector<int> label;
std::vector<double> weight;
predict(_src, label, weight, maxN);
std::vector<std::pair<int, double>> result(label.size());
for (int i = 0; i < label.size(); i++)
result[i] = std::make_pair(label[i], weight[i]);
return result;
}
Hope this helps.
just calculate one to all, all the distances, then sort them out and then take the top 10?
It require rewrite face module itself - no API for "to all, all the distances", it's not much hard, but i don't like to grow own forks and make entropy on code that i want just to use, not contribute.
You could look at it the other way, this problem has been stated many times before, why not implement it, dig into the code, contribute it back and be greatful for the fact that you can use this very decent open source computer vision library for free. We would all be thankful.
related attempts:
https://github.com/Itseez/opencv_cont...
https://github.com/Itseez/opencv_cont...