Commit 6c78c5ee2f266f2f632b27f8d220407418534417
1 parent
59e268e5
removed meanshift
Showing
1 changed file
with
0 additions
and
124 deletions
openbr/plugins/cluster/meanshift.cpp deleted
| 1 | -#include <openbr/plugins/openbr_internal.h> | ||
| 2 | -#include <openbr/core/opencvutils.h> | ||
| 3 | - | ||
| 4 | -using namespace cv; | ||
| 5 | - | ||
| 6 | -namespace br | ||
| 7 | -{ | ||
| 8 | - | ||
| 9 | -/*! | ||
| 10 | - * \brief A transform implementing the mean shift clustering algorithm. | ||
| 11 | - * \author Jordan Cheney \cite JordanCheney | ||
| 12 | - * \br_property br::Distance* distance The distance used to compute the distance between templates | ||
| 13 | - * \br_property int kernelBandwidth The size of the kernel used to converge points to a cluster center | ||
| 14 | - * \br_property float shiftThreshold The cutoff threshold distance for a shifted point. A value lower then this threshold indicates a point has finished shifting to a cluster center. | ||
| 15 | - * \br_property float distanceThreshold The distance threshold for a point to join a cluster. A point must be at least this close to another point to be included in the same cluster as that point. | ||
| 16 | - * \br_link http://spin.atomicobject.com/2015/05/26/mean-shift-clustering/ | ||
| 17 | - */ | ||
| 18 | -class MeanShiftClusteringTransform : public TimeVaryingTransform | ||
| 19 | -{ | ||
| 20 | - Q_OBJECT | ||
| 21 | - | ||
| 22 | - Q_PROPERTY(br::Distance* distance READ get_distance WRITE set_distance RESET reset_distance STORED false) | ||
| 23 | - Q_PROPERTY(int kernelBandwidth READ get_kernelBandwidth WRITE set_kernelBandwidth RESET reset_kernelBandwidth STORED false) | ||
| 24 | - Q_PROPERTY(float shiftThreshold READ get_shiftThreshold WRITE set_shiftThreshold RESET reset_shiftThreshold STORED false) | ||
| 25 | - Q_PROPERTY(float distanceThreshold READ get_distanceThreshold WRITE set_distanceThreshold RESET reset_distanceThreshold STORED false) | ||
| 26 | - BR_PROPERTY(br::Distance*, distance, Distance::make(".Dist(L2, false)", NULL)) | ||
| 27 | - BR_PROPERTY(int, kernelBandwidth, 3) | ||
| 28 | - BR_PROPERTY(float, shiftThreshold, 1e-3) | ||
| 29 | - BR_PROPERTY(float, distanceThreshold, 1e-1) | ||
| 30 | - | ||
| 31 | -public: | ||
| 32 | - MeanShiftClusteringTransform() : TimeVaryingTransform(false, false) {} | ||
| 33 | - | ||
| 34 | -private: | ||
| 35 | - void projectUpdate(const TemplateList &src, TemplateList &) | ||
| 36 | - { | ||
| 37 | - templates.append(src); | ||
| 38 | - } | ||
| 39 | - | ||
| 40 | - void finalize(TemplateList &output) | ||
| 41 | - { | ||
| 42 | - output.clear(); | ||
| 43 | - | ||
| 44 | - QList<Mat> original_points, shifted_points; | ||
| 45 | - original_points = shifted_points = templates.data(); | ||
| 46 | - | ||
| 47 | - Mat shift_mask = Mat::zeros(1, shifted_points.size(), CV_32S); | ||
| 48 | - while (countNonZero(shift_mask) != shifted_points.size()) { | ||
| 49 | - for (int i = 0; i < shifted_points.size(); i++) { | ||
| 50 | - if (shift_mask.at<int>(0, i)) | ||
| 51 | - continue; | ||
| 52 | - | ||
| 53 | - Mat point = shifted_points[i]; | ||
| 54 | - Mat shifted_point = point.clone(); | ||
| 55 | - meanshift(shifted_point, original_points); | ||
| 56 | - | ||
| 57 | - float dist = distance->compare(point, shifted_point); | ||
| 58 | - if (dist < shiftThreshold) | ||
| 59 | - shift_mask.at<int>(0, i) = 1; | ||
| 60 | - | ||
| 61 | - shifted_points[i] = shifted_point; | ||
| 62 | - } | ||
| 63 | - } | ||
| 64 | - | ||
| 65 | - QList<int> clusters = assignClusterID(shifted_points); | ||
| 66 | - for (int i = 0; i < templates.size(); i++) | ||
| 67 | - templates[i].file.set("Cluster", clusters[i]); | ||
| 68 | - output.append(templates); | ||
| 69 | - } | ||
| 70 | - | ||
| 71 | - void meanshift(Mat &point, const QList<Mat> &original_points) | ||
| 72 | - { | ||
| 73 | - Mat distances(1, original_points.size(), CV_32FC1); | ||
| 74 | - for (int i = 0; i < original_points.size(); i++) | ||
| 75 | - distances.at<float>(0, i) = distance->compare(point, original_points[i]); | ||
| 76 | - | ||
| 77 | - Mat weights = gaussianKernel(distances, kernelBandwidth); | ||
| 78 | - point = (weights * OpenCVUtils::toMat(original_points)) / sum(weights)[0]; | ||
| 79 | - } | ||
| 80 | - | ||
| 81 | - inline Mat gaussianKernel(const Mat &distance, const float bandwidth) | ||
| 82 | - { | ||
| 83 | - Mat p, e; | ||
| 84 | - pow(distance / bandwidth, 2, p); | ||
| 85 | - exp(-0.5 * p, e); | ||
| 86 | - | ||
| 87 | - return (1.0 / (bandwidth * sqrt(2 * CV_PI))) * e; | ||
| 88 | - } | ||
| 89 | - | ||
| 90 | - QList<int> assignClusterID(const QList<Mat> &points) | ||
| 91 | - { | ||
| 92 | - QList<int> groups; | ||
| 93 | - int newGroupIdx = 0; | ||
| 94 | - foreach (const Mat &point, points) { | ||
| 95 | - int group = nearestGroup(point, points, groups); | ||
| 96 | - if (group < 0) | ||
| 97 | - group = newGroupIdx++; | ||
| 98 | - groups.append(group); | ||
| 99 | - } | ||
| 100 | - | ||
| 101 | - if (Globals->verbose) | ||
| 102 | - qDebug("created %d clusters from %d templates", newGroupIdx, points.size()); | ||
| 103 | - | ||
| 104 | - return groups; | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | - int nearestGroup(const Mat &point, const QList<Mat> &points, const QList<int> groups) | ||
| 108 | - { | ||
| 109 | - for (int i = 0; i < groups.size(); i++) { | ||
| 110 | - float dist = distance->compare(point, points[i]); | ||
| 111 | - if (dist < distanceThreshold) | ||
| 112 | - return groups[i]; | ||
| 113 | - } | ||
| 114 | - return -1; | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - TemplateList templates; | ||
| 118 | -}; | ||
| 119 | - | ||
| 120 | -BR_REGISTER(Transform, MeanShiftClusteringTransform) | ||
| 121 | - | ||
| 122 | -} // namespace br | ||
| 123 | - | ||
| 124 | -#include "cluster/meanshift.moc" |