Neighborhood br::knnFromSimmat(const QList<cv::Mat> &simmats, int k) { Neighborhood neighborhood; float globalMax = -std::numeric_limits<float>::max(); float globalMin = std::numeric_limits<float>::max(); int numGalleries = (int)sqrt((float)simmats.size()); if (numGalleries*numGalleries != simmats.size()) qFatal("Incorrect number of similarity matrices."); // Process each simmat for (int i=0; i<numGalleries; i++) { QVector<Neighbors> allNeighbors; int currentRows = -1; int columnOffset = 0; for (int j=0; j<numGalleries; j++) { cv::Mat m = simmats[i * numGalleries + j]; if (j==0) { currentRows = m.rows; allNeighbors.resize(currentRows); } if (currentRows != m.rows) qFatal("Row count mismatch."); // Get data row by row for (int k=0; k<m.rows; k++) { Neighbors &neighbors = allNeighbors[k]; neighbors.reserve(neighbors.size() + m.cols); for (int l=0; l<m.cols; l++) { float val = m.at<float>(k,l); if ((i==j) && (k==l)) continue; // Skips self-similarity scores if (val != -std::numeric_limits<float>::max() && val != -std::numeric_limits<float>::infinity() && val != std::numeric_limits<float>::infinity()) { globalMax = std::max(globalMax, val); globalMin = std::min(globalMin, val); } neighbors.append(Neighbor(l+columnOffset, val)); } } columnOffset += m.cols; } // Keep the top matches for (int j=0; j<allNeighbors.size(); j++) { Neighbors &val = allNeighbors[j]; const int cutoff = k; // Number of neighbors to keep int keep = std::min(cutoff, val.size()); std::partial_sort(val.begin(), val.begin()+keep, val.end(), compareNeighbors); neighborhood.append((Neighbors)val.mid(0, keep)); } } return neighborhood; }
Neighborhood getNeighborhood(const QStringList &simmats) { Neighborhood neighborhood; float globalMax = -std::numeric_limits<float>::max(); float globalMin = std::numeric_limits<float>::max(); int numGalleries = (int)sqrt((float)simmats.size()); if (numGalleries*numGalleries != simmats.size()) qFatal("Incorrect number of similarity matrices."); // Process each simmat for (int i=0; i<numGalleries; i++) { QVector<Neighbors> allNeighbors; int currentRows = -1; int columnOffset = 0; for (int j=0; j<numGalleries; j++) { QScopedPointer<br::Format> format(br::Factory<br::Format>::make(simmats[i*numGalleries+j])); br::Template t = format->read(); cv::Mat m = t.m(); if (j==0) { currentRows = m.rows; allNeighbors.resize(currentRows); } if (currentRows != m.rows) qFatal("Row count mismatch."); // Get data row by row for (int k=0; k<m.rows; k++) { Neighbors &neighbors = allNeighbors[k]; neighbors.reserve(neighbors.size() + m.cols); for (int l=0; l<m.cols; l++) { float val = m.at<float>(k,l); if ((i==j) && (k==l)) continue; // Skips self-similarity scores if (val != -std::numeric_limits<float>::max() && val != -std::numeric_limits<float>::infinity() && val != std::numeric_limits<float>::infinity()) { globalMax = std::max(globalMax, val); globalMin = std::min(globalMin, val); } neighbors.append(Neighbor(l+columnOffset, val)); } } columnOffset += m.cols; } // Keep the top matches for (int j=0; j<allNeighbors.size(); j++) { Neighbors &val = allNeighbors[j]; const int cutoff = 20; // Somewhat arbitrary number of neighbors to keep int keep = std::min(cutoff, val.size()); std::partial_sort(val.begin(), val.begin()+keep, val.end(), compareNeighbors); neighborhood.append((Neighbors)val.mid(0, keep)); } } // Normalize scores for (int i=0; i<neighborhood.size(); i++) { Neighbors &neighbors = neighborhood[i]; for (int j=0; j<neighbors.size(); j++) { Neighbor &neighbor = neighbors[j]; if (neighbor.second == -std::numeric_limits<float>::infinity()) neighbor.second = 0; else if (neighbor.second == std::numeric_limits<float>::infinity()) neighbor.second = 1; else neighbor.second = (neighbor.second - globalMin) / (globalMax - globalMin); } } return neighborhood; }