--- src/cpp/algorithms/dist_extended.h 1969-12-31 16:00:00.000000000 -0800 +++ src/cpp/algorithms/dist_extended.h 2009-11-17 13:25:55.000000000 -0800 @@ -0,0 +1,180 @@ +/* + * Software License Agreement (BSD License) + * + * Copyright (c) 2009, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +/** + * \author Romain Thibaux (thibaux@willowgarage.com) + */ + +#ifndef DIST_EXTENDED_H +#define DIST_EXTENDED_H + +#include + +// L_infinity distance (NOT A VALID FLANN DISTANCE - NOT DIMENSIONWISE ADDITIVE) +template +double max_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0) +{ + double dist = acc; + Iterator1 lastgroup = last1 - 3; + double diff0, diff1, diff2, diff3; + + /* Process 4 items with each loop for efficiency. */ + while (first1 < lastgroup) { + diff0 = fabs(first1[0] - first2[0]); + diff1 = fabs(first1[1] - first2[1]); + diff2 = fabs(first1[2] - first2[2]); + diff3 = fabs(first1[3] - first2[3]); + if (diff0 > dist) dist = diff0; + if (diff1 > dist) dist = diff1; + if (diff2 > dist) dist = diff2; + if (diff3 > dist) dist = diff3; + first1 += 4; + first2 += 4; + } + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (first1 < last1) { + diff0 = fabs(*first1++ - *first2++); + dist = (diff0 > dist) ? diff0 : dist; + } + return dist; +} + +template +double hist_intersection_kernel(Iterator1 first1, Iterator1 last1, Iterator2 first2) +{ + double kernel = 0; + Iterator1 lastgroup = last1 - 3; + double min0, min1, min2, min3; + + /* Process 4 items with each loop for efficiency. */ + while (first1 < lastgroup) { + min0 = first1[0] < first2[0] ? first1[0] : first2[0]; + min1 = first1[1] < first2[1] ? first1[1] : first2[1]; + min2 = first1[2] < first2[2] ? first1[2] : first2[2]; + min3 = first1[3] < first2[3] ? first1[3] : first2[3]; + kernel += min0 + min1 + min2 + min3; + first1 += 4; + first2 += 4; + } + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (first1 < last1) { + min0 = first1[0] < first2[0] ? first1[0] : first2[0]; + kernel += min0; + first1++; + first2++; + } + return kernel; +} + +template +double hist_intersection_dist_sq(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0) +{ + double dist_sq = acc - 2 * hist_intersection_kernel(first1, last1, first2); + while (first1 < last1) { + dist_sq += *first1 + *first2; + first1++; + first2++; + } + return dist_sq; +} + +// Hellinger distance +template +double jm_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0) +{ + double distsq = acc; + double diff0, diff1, diff2, diff3; + Iterator1 lastgroup = last1 - 3; + + /* Process 4 items with each loop for efficiency. */ + while (first1 < lastgroup) { + diff0 = sqrt(first1[0]) - sqrt(first2[0]); + diff1 = sqrt(first1[1]) - sqrt(first2[1]); + diff2 = sqrt(first1[2]) - sqrt(first2[2]); + diff3 = sqrt(first1[3]) - sqrt(first2[3]); + distsq += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3; + first1 += 4; + first2 += 4; + } + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (first1 < last1) { + diff0 = sqrt(*first1++) - sqrt(*first2++); + distsq += diff0 * diff0; + } + return distsq; +} + + + +// Hellinger distance +template +double cs_dist(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0) +{ + double dist = acc; + + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (first1 < last1) { + double sum = *first1 + *first2; + if (sum > 0) { + double diff = *first1 - *first2; + dist += diff * diff / sum; + } + first1++; + first2++; + } + return dist; +} + + +// KL divergence (NOT A VALID FLANN DISTANCE - NOT SYMMETRIC) +template +double KL_divergence(Iterator1 first1, Iterator1 last1, Iterator2 first2, double acc = 0) +{ + double div = acc; + + /* Process last 0-3 pixels. Not needed for standard vector lengths. */ + while (first1 < last1) { + if (*first2 != 0) { + double ratio = *first1 / *first2; + if (ratio > 0) { + div += *first1 * log(ratio); + } + } + first1++; + first2++; + } + return div; +} + +#endif //DIST_EXTENDED_H --- src/cpp/algorithms/dist.h 2009-02-27 14:14:00.000000000 -0800 +++ src/cpp/algorithms/dist.h 2009-11-17 13:33:43.000000000 -0800 @@ -34,6 +34,7 @@ using namespace std; #include "constants.h" +#include "dist_extended.h" /** * Distance function by default set to the custom distance @@ -168,6 +169,16 @@ return manhattan_dist(first1, last1, first2, acc); case MINKOWSKI: return minkowski_dist(first1, last1, first2, acc); + case MAXDIST: + return max_dist(first1, last1, first2, acc); + case HIK: + return hist_intersection_dist_sq(first1, last1, first2, acc); + case JM: + return jm_dist(first1, last1, first2, acc); + case CS: + return cs_dist(first1, last1, first2, acc); + case KL: + return KL_divergence(first1, last1, first2, acc); default: return euclidean_dist(first1, last1, first2, acc); } --- src/cpp/constants.h 2009-02-27 14:14:00.000000000 -0800 +++ src/cpp/constants.h 2009-11-17 13:32:53.000000000 -0800 @@ -56,7 +56,12 @@ enum flann_distance_t { EUCLIDEAN = 1, MANHATTAN = 2, - MINKOWSKI = 3 + MINKOWSKI = 3, + MAXDIST = 4, + HIK = 5, + JM = 6, + CS = 7, + KL = 8 }; #endif // CONSTANTS_H --- src/cpp/CMakeLists.txt 2009-11-17 14:22:12.000000000 -0800 +++ src/cpp/CMakeLists.txt 2009-11-17 14:22:26.000000000 -0800 @@ -38,6 +38,6 @@ # ) INSTALL ( - FILES flann.h constants.h + FILES flann.h constants.h algorithms/dist.h algorithms/dist_extended.h DESTINATION include )