quickshift.c
Go to the documentation of this file.
00001 
00007 /*
00008 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00009 All rights reserved.
00010 
00011 This file is part of the VLFeat library and is made available under
00012 the terms of the BSD license (see the COPYING file).
00013 */
00014 
00125 #include "quickshift.h"
00126 #include "mathop.h"
00127 #include <string.h>
00128 #include <math.h>
00129 #include <stdio.h>
00130 
00152 VL_INLINE
00153 vl_qs_type
00154 vl_quickshift_distance(vl_qs_type const * I,
00155          int N1, int N2, int K,
00156          int i1, int i2,
00157          int j1, int j2)
00158 {
00159   vl_qs_type dist = 0 ;
00160   int d1 = j1 - i1 ;
00161   int d2 = j2 - i2 ;
00162   int k ;
00163   dist += d1*d1 + d2*d2 ;
00164   /* For k = 0...K-1, d+= L2 distance between I(i1,i2,k) and
00165    * I(j1,j2,k) */
00166   for (k = 0 ; k < K ; ++k) {
00167     vl_qs_type d =
00168       I [i1 + N1 * i2 + (N1*N2) * k] -
00169       I [j1 + N1 * j2 + (N1*N2) * k] ;
00170     dist += d*d ;
00171   }
00172   return dist ;
00173 }
00174 
00196 VL_INLINE
00197 vl_qs_type
00198 vl_quickshift_inner(vl_qs_type const * I,
00199       int N1, int N2, int K,
00200       int i1, int i2,
00201       int j1, int j2)
00202 {
00203   vl_qs_type ker = 0 ;
00204   int k ;
00205   ker += i1*j1 + i2*j2 ;
00206   for (k = 0 ; k < K ; ++k) {
00207     ker +=
00208       I [i1 + N1 * i2 + (N1*N2) * k] *
00209       I [j1 + N1 * j2 + (N1*N2) * k] ;
00210   }
00211   return ker ;
00212 }
00213 
00229 VL_EXPORT
00230 VlQS *
00231 vl_quickshift_new(vl_qs_type const * image, int height, int width,
00232                        int channels)
00233 {
00234   VlQS * q = vl_malloc(sizeof(VlQS));
00235 
00236   q->image    = (vl_qs_type *)image;
00237   q->height   = height;
00238   q->width    = width;
00239   q->channels = channels;
00240 
00241   q->medoid   = VL_FALSE;
00242   q->tau      = VL_MAX(height,width)/50;
00243   q->sigma    = VL_MAX(2, q->tau/3);
00244 
00245   q->dists    = vl_calloc(height*width, sizeof(vl_qs_type));
00246   q->parents  = vl_calloc(height*width, sizeof(int));
00247   q->density  = vl_calloc(height*width, sizeof(vl_qs_type)) ;
00248 
00249   return q;
00250 }
00251 
00257 VL_EXPORT
00258 void vl_quickshift_process(VlQS * q)
00259 {
00260   vl_qs_type const *I = q->image;
00261   int        *parents = q->parents;
00262   vl_qs_type *E = q->density;
00263   vl_qs_type *dists = q->dists;
00264   vl_qs_type *M = 0, *n = 0 ;
00265   vl_qs_type sigma = q->sigma ;
00266   vl_qs_type tau = q->tau;
00267   vl_qs_type tau2 = tau*tau;
00268 
00269   int K = q->channels, d;
00270   int N1 = q->height, N2 = q->width;
00271   int i1,i2, j1,j2, R, tR;
00272 
00273   d = 2 + K ; /* Total dimensions include spatial component (x,y) */
00274 
00275   if (q->medoid) { /* n and M are only used in mediod shift */
00276     M = (vl_qs_type *) vl_calloc(N1*N2*d, sizeof(vl_qs_type)) ;
00277     n = (vl_qs_type *) vl_calloc(N1*N2,   sizeof(vl_qs_type)) ;
00278   }
00279 
00280   R = (int) ceil (3 * sigma) ;
00281   tR = (int) ceil (tau) ;
00282 
00283   /* -----------------------------------------------------------------
00284    *                                                                 n
00285    * -------------------------------------------------------------- */
00286 
00287   /* If we are doing medoid shift, initialize n to the inner product of the
00288    * image with itself
00289    */
00290   if (n) {
00291     for (i2 = 0 ; i2 < N2 ; ++ i2) {
00292       for (i1 = 0 ; i1 < N1 ; ++ i1) {
00293         n [i1 + N1 * i2] = vl_quickshift_inner(I,N1,N2,K,
00294                                                i1,i2,
00295                                                i1,i2) ;
00296       }
00297     }
00298   }
00299 
00300   /* -----------------------------------------------------------------
00301    *                                                 E = - [oN'*F]', M
00302    * -------------------------------------------------------------- */
00303 
00304   /*
00305      D_ij = d(x_i,x_j)
00306      E_ij = exp(- .5 * D_ij / sigma^2) ;
00307      F_ij = - E_ij
00308      E_i  = sum_j E_ij
00309      M_di = sum_j X_j F_ij
00310 
00311      E is the parzen window estimate of the density
00312      0 = dissimilar to everything, windowsize = identical
00313   */
00314 
00315   for (i2 = 0 ; i2 < N2 ; ++ i2) {
00316     for (i1 = 0 ; i1 < N1 ; ++ i1) {
00317 
00318       int j1min = VL_MAX(i1 - R, 0   ) ;
00319       int j1max = VL_MIN(i1 + R, N1-1) ;
00320       int j2min = VL_MAX(i2 - R, 0   ) ;
00321       int j2max = VL_MIN(i2 + R, N2-1) ;
00322 
00323       /* For each pixel in the window compute the distance between it and the
00324        * source pixel */
00325       for (j2 = j2min ; j2 <= j2max ; ++ j2) {
00326         for (j1 = j1min ; j1 <= j1max ; ++ j1) {
00327           vl_qs_type Dij = vl_quickshift_distance(I,N1,N2,K, i1,i2, j1,j2) ;
00328           /* Make distance a similarity */
00329           vl_qs_type Fij = - exp(- Dij / (2*sigma*sigma)) ;
00330 
00331           /* E is E_i above */
00332           E [i1 + N1 * i2] -= Fij ;
00333 
00334           if (M) {
00335             /* Accumulate votes for the median */
00336             int k ;
00337             M [i1 + N1*i2 + (N1*N2) * 0] += j1 * Fij ;
00338             M [i1 + N1*i2 + (N1*N2) * 1] += j2 * Fij ;
00339             for (k = 0 ; k < K ; ++k) {
00340               M [i1 + N1*i2 + (N1*N2) * (k+2)] +=
00341                 I [j1 + N1*j2 + (N1*N2) * k] * Fij ;
00342             }
00343           }
00344 
00345         } /* j1 */
00346       } /* j2 */
00347 
00348     }  /* i1 */
00349   } /* i2 */
00350 
00351   /* -----------------------------------------------------------------
00352    *                                               Find best neighbors
00353    * -------------------------------------------------------------- */
00354 
00355   if (q->medoid) {
00356 
00357     /*
00358        Qij = - nj Ei - 2 sum_k Gjk Mik
00359        n is I.^2
00360     */
00361 
00362     /* medoid shift */
00363     for (i2 = 0 ; i2 < N2 ; ++i2) {
00364       for (i1 = 0 ; i1 < N1 ; ++i1) {
00365 
00366         vl_qs_type sc_best = 0  ;
00367         /* j1/j2 best are the best indicies for each i */
00368         vl_qs_type j1_best = i1 ;
00369         vl_qs_type j2_best = i2 ;
00370 
00371         int j1min = VL_MAX(i1 - R, 0   ) ;
00372         int j1max = VL_MIN(i1 + R, N1-1) ;
00373         int j2min = VL_MAX(i2 - R, 0   ) ;
00374         int j2max = VL_MIN(i2 + R, N2-1) ;
00375 
00376         for (j2 = j2min ; j2 <= j2max ; ++ j2) {
00377           for (j1 = j1min ; j1 <= j1max ; ++ j1) {
00378 
00379             vl_qs_type Qij = - n [j1 + j2 * N1] * E [i1 + i2 * N1] ;
00380             int k ;
00381 
00382             Qij -= 2 * j1 * M [i1 + i2 * N1 + (N1*N2) * 0] ;
00383             Qij -= 2 * j2 * M [i1 + i2 * N1 + (N1*N2) * 1] ;
00384             for (k = 0 ; k < K ; ++k) {
00385               Qij -= 2 *
00386                 I [j1 + j2 * N1 + (N1*N2) * k] *
00387                 M [i1 + i2 * N1 + (N1*N2) * (k + 2)] ;
00388             }
00389 
00390             if (Qij > sc_best) {
00391               sc_best = Qij ;
00392               j1_best = j1 ;
00393               j2_best = j2 ;
00394             }
00395           }
00396         }
00397 
00398         /* parents_i is the linear index of j which is the best pair
00399          * dists_i is the score of the best match
00400          */
00401         parents [i1 + N1 * i2] = j1_best + N1 * j2_best ;
00402         dists[i1 + N1 * i2] = sc_best ;
00403       }
00404     }
00405 
00406   } else {
00407 
00408     /* Quickshift assigns each i to the closest j which has an increase in the
00409      * density (E). If there is no j s.t. Ej > Ei, then dists_i == inf (a root
00410      * node in one of the trees of merges).
00411      */
00412     for (i2 = 0 ; i2 < N2 ; ++i2) {
00413       for (i1 = 0 ; i1 < N1 ; ++i1) {
00414 
00415         vl_qs_type E0 = E [i1 + N1 * i2] ;
00416         vl_qs_type d_best = VL_QS_INF ;
00417         vl_qs_type j1_best = i1   ;
00418         vl_qs_type j2_best = i2   ;
00419 
00420         int j1min = VL_MAX(i1 - tR, 0   ) ;
00421         int j1max = VL_MIN(i1 + tR, N1-1) ;
00422         int j2min = VL_MAX(i2 - tR, 0   ) ;
00423         int j2max = VL_MIN(i2 + tR, N2-1) ;
00424 
00425         for (j2 = j2min ; j2 <= j2max ; ++ j2) {
00426           for (j1 = j1min ; j1 <= j1max ; ++ j1) {
00427             if (E [j1 + N1 * j2] > E0) {
00428               vl_qs_type Dij = vl_quickshift_distance(I,N1,N2,K, i1,i2, j1,j2) ;
00429               if (Dij <= tau2 && Dij < d_best) {
00430                 d_best = Dij ;
00431                 j1_best = j1 ;
00432                 j2_best = j2 ;
00433               }
00434             }
00435           }
00436         }
00437 
00438         /* parents is the index of the best pair */
00439         /* dists_i is the minimal distance, inf implies no Ej > Ei within
00440          * distance tau from the point */
00441         parents [i1 + N1 * i2] = j1_best + N1 * j2_best ;
00442         dists[i1 + N1 * i2] = sqrt(d_best) ;
00443       }
00444     }
00445   }
00446 
00447   if (M) vl_free(M) ;
00448   if (n) vl_free(n) ;
00449 }
00450 
00456 void vl_quickshift_delete(VlQS * q)
00457 {
00458   if (q) {
00459     if (q->parents) vl_free(q->parents);
00460     if (q->dists)   vl_free(q->dists);
00461     if (q->density) vl_free(q->density);
00462 
00463     vl_free(q);
00464   }
00465 }


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51