00001
00007
00008
00009
00010
00011
00012
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
00165
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 ;
00274
00275 if (q->medoid) {
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
00285
00286
00287
00288
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
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
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
00324
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
00329 vl_qs_type Fij = - exp(- Dij / (2*sigma*sigma)) ;
00330
00331
00332 E [i1 + N1 * i2] -= Fij ;
00333
00334 if (M) {
00335
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 }
00346 }
00347
00348 }
00349 }
00350
00351
00352
00353
00354
00355 if (q->medoid) {
00356
00357
00358
00359
00360
00361
00362
00363 for (i2 = 0 ; i2 < N2 ; ++i2) {
00364 for (i1 = 0 ; i1 < N1 ; ++i1) {
00365
00366 vl_qs_type sc_best = 0 ;
00367
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
00399
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
00409
00410
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
00439
00440
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 }