imopv.c
Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00008 All rights reserved.
00009 
00010 This file is part of the VLFeat library and is made available under
00011 the terms of the BSD license (see the COPYING file).
00012 */
00013 
00035 #ifndef VL_IMOPV_INSTANTIATING
00036 
00037 #include "imopv.h"
00038 #include "imopv_sse2.h"
00039 #include "mathop.h"
00040 
00041 #define FLT VL_TYPE_FLOAT
00042 #define VL_IMOPV_INSTANTIATING
00043 #include "imopv.c"
00044 
00045 #define FLT VL_TYPE_DOUBLE
00046 #define VL_IMOPV_INSTANTIATING
00047 #include "imopv.c"
00048 
00049 #define FLT VL_TYPE_UINT32
00050 #define VL_IMOPV_INSTANTIATING
00051 #include "imopv.c"
00052 
00053 #define FLT VL_TYPE_INT32
00054 #define VL_IMOPV_INSTANTIATING
00055 #include "imopv.c"
00056 
00057 /* VL_IMOPV_INSTANTIATING */
00058 #endif
00059 
00060 #if defined(VL_IMOPV_INSTANTIATING) || defined(__DOXYGEN__)
00061 
00062 #include "float.th"
00063 
00064 /* ---------------------------------------------------------------- */
00065 /*                                                Image Convolution */
00066 /* ---------------------------------------------------------------- */
00067 
00068 #if (FLT == VL_TYPE_FLOAT || FLT == VL_TYPE_DOUBLE)
00069 
00119 VL_EXPORT void
00120 VL_XCAT(vl_imconvcol_v, SFX)
00121 (T* dst, vl_size dst_stride,
00122  T const* src,
00123  vl_size src_width, vl_size src_height, vl_size src_stride,
00124  T const* filt, vl_index filt_begin, vl_index filt_end,
00125  int step, unsigned int flags)
00126 {
00127   vl_index x = 0 ;
00128   vl_index y ;
00129   vl_index dheight = (src_height - 1) / step + 1 ;
00130   vl_bool transp = flags & VL_TRANSPOSE ;
00131   vl_bool zeropad = (flags & VL_PAD_MASK) == VL_PAD_BY_ZERO ;
00132 
00133   /* dispatch to accelerated version */
00134 #ifndef VL_DISABLE_SSE2
00135   if (vl_cpu_has_sse2() && vl_get_simd_enabled()) {
00136     VL_XCAT3(_vl_imconvcol_v,SFX,_sse2)
00137     (dst,dst_stride,
00138      src,src_width,src_height,src_stride,
00139      filt,filt_begin,filt_end,
00140      step,flags) ;
00141     return ;
00142   }
00143 #endif
00144 
00145   /* let filt point to the last sample of the filter */
00146   filt += filt_end - filt_begin ;
00147 
00148   while (x < (signed)src_width) {
00149     /* Calculate dest[x,y] = sum_p image[x,p] filt[y - p]
00150      * where supp(filt) = [filt_begin, filt_end] = [fb,fe].
00151      *
00152      * CHUNK_A: y - fe <= p < 0
00153      *          completes VL_MAX(fe - y, 0) samples
00154      * CHUNK_B: VL_MAX(y - fe, 0) <= p < VL_MIN(y - fb, height - 1)
00155      *          completes fe - VL_MAX(fb, height - y) + 1 samples
00156      * CHUNK_C: completes all samples
00157      */
00158     T const *filti ;
00159     vl_index stop ;
00160 
00161     for (y = 0 ; y < (signed)src_height ; y += step) {
00162       T acc = 0 ;
00163       T v = 0, c ;
00164       T const* srci ;
00165 
00166       filti = filt ;
00167       stop = filt_end - y ;
00168       srci = src + x - stop * src_stride ;
00169 
00170       if (stop > 0) {
00171         if (zeropad) {
00172           v = 0 ;
00173         } else {
00174           v = *(src + x) ;
00175         }
00176         while (filti > filt - stop) {
00177           c = *filti-- ;
00178           acc += v * c ;
00179           srci += src_stride ;
00180         }
00181       }
00182 
00183       stop = filt_end - VL_MAX(filt_begin, y - (signed)src_height + 1) + 1 ;
00184       while (filti > filt - stop) {
00185         v = *srci ;
00186         c = *filti-- ;
00187         acc += v * c ;
00188         srci += src_stride ;
00189       }
00190 
00191       if (zeropad) v = 0 ;
00192 
00193       stop = filt_end - filt_begin + 1 ;
00194       while (filti > filt - stop) {
00195         c = *filti-- ;
00196         acc += v * c ;
00197       }
00198 
00199       if (transp) {
00200         *dst = acc ; dst += 1 ;
00201       } else {
00202         *dst = acc ; dst += dst_stride ;
00203       }
00204     } /* next y */
00205     if (transp) {
00206       dst += 1 * dst_stride - dheight * 1 ;
00207     } else {
00208       dst += 1 * 1 - dheight * dst_stride ;
00209     }
00210     x += 1 ;
00211   } /* next x */
00212 }
00213 
00214 /* VL_TYPE_FLOAT, VL_TYPE_DOUBLE */
00215 #endif
00216 
00217 /* ---------------------------------------------------------------- */
00218 /*                                         Image distance transform */
00219 /* ---------------------------------------------------------------- */
00220 
00221 #if (FLT == VL_TYPE_FLOAT || FLT == VL_TYPE_DOUBLE)
00222 
00328 VL_EXPORT void
00329 VL_XCAT(vl_image_distance_transform_,SFX)
00330 (T const * image,
00331  vl_size numColumns,
00332  vl_size numRows,
00333  vl_size columnStride,
00334  vl_size rowStride,
00335  T * distanceTransform,
00336  vl_uindex * indexes,
00337  T coeff,
00338  T offset)
00339 {
00340   /* Each image pixel corresponds to a parabola. The algorithm scans
00341    such parabolas from left to right, keeping track of which
00342    parabolas belong to the lower envelope and in which interval. There are
00343    NUM active parabolas, FROM stores the beginning of the interval
00344    for which a certain parabola is part of the envoelope, and WHICH store
00345    the index of the parabola (that is, the pixel x from which the parabola
00346    originated).
00347    */
00348   vl_uindex x, y ;
00349   T * from = vl_malloc (sizeof(T) * (numColumns + 1)) ;
00350   T * base = vl_malloc (sizeof(T) * numColumns) ;
00351   vl_uindex * baseIndexes = vl_malloc (sizeof(vl_uindex) * numColumns) ;
00352   vl_uindex * which = vl_malloc (sizeof(vl_uindex) * numColumns) ;
00353   vl_uindex num = 0 ;
00354 
00355   for (y = 0 ; y < numRows ; ++y) {
00356     num = 0 ;
00357     for (x = 0 ; x < numColumns ; ++x) {
00358       T r = image[x  * columnStride + y * rowStride] ;
00359       T x2 = x * x ;
00360 #if (FLT == VL_TYPE_FLOAT)
00361       T from_ = - VL_INFINITY_F ;
00362 #else
00363       T from_ = - VL_INFINITY_D ;
00364 #endif
00365 
00366       /*
00367        Add next parabola (there are NUM so far). The algorithm finds
00368        intersection INTERS with the previously added parabola. If
00369        the intersection is on the right of the "starting point" of
00370        this parabola, then the previous parabola is kept, and the
00371        new one is added to its right. Otherwise the new parabola
00372        "eats" the old one, which gets deleted and the check is
00373        repeated with the parabola added before the deleted one.
00374        */
00375 
00376       while (num >= 1) {
00377         vl_uindex x_ = which[num - 1] ;
00378         T x2_ = x_ * x_ ;
00379         T r_ = image[x_ * columnStride + y * rowStride] ;
00380         T inters ;
00381         if (r == r_) {
00382           /* handles the case r = r_ = \pm inf */
00383           inters = (x + x_) / 2.0 + offset ;
00384         }
00385 #if (FLT == VL_TYPE_FLOAT)
00386         else if (coeff > VL_EPSILON_F)
00387 #else
00388         else if (coeff > VL_EPSILON_D)
00389 #endif
00390         {
00391           inters = ((r - r_) + coeff * (x2 - x2_)) / (x - x_) / (2*coeff) + offset ;
00392         } else {
00393           /* If coeff is very small, the parabolas are flat (= lines).
00394            In this case the previous parabola should be deleted if the current
00395            pixel has lower score */
00396 #if (FLT == VL_TYPE_FLOAT)
00397           inters = (r < r_) ? - VL_INFINITY_F : VL_INFINITY_F ;
00398 #else
00399           inters = (r < r_) ? - VL_INFINITY_D : VL_INFINITY_D ;
00400 #endif
00401         }
00402         if (inters <= from [num - 1]) {
00403           /* delete a previous parabola */
00404           -- num ;
00405         } else {
00406           /* accept intersection */
00407           from_ = inters ;
00408           break ;
00409         }
00410       }
00411 
00412       /* add a new parabola */
00413       which[num] = x ;
00414       from[num] = from_ ;
00415       base[num] = r ;
00416       if (indexes) baseIndexes[num] = indexes[x  * columnStride + y * rowStride] ;
00417       num ++ ;
00418     } /* next column */
00419 
00420 #if (FLT == VL_TYPE_FLOAT)
00421     from[num] = VL_INFINITY_F ;
00422 #else
00423     from[num] = VL_INFINITY_D ;
00424 #endif
00425 
00426     /* fill in */
00427     num = 0 ;
00428     for (x = 0 ; x < numColumns ; ++x) {
00429       double delta ;
00430       while (x >= from[num + 1]) ++ num ;
00431       delta = (double) x - (double) which[num] - offset ;
00432       distanceTransform[x  * columnStride + y * rowStride]
00433       = base[num] + coeff * delta * delta ;
00434       if (indexes) {
00435         indexes[x  * columnStride + y * rowStride]
00436         = baseIndexes[num] ;
00437       }
00438     }
00439   } /* next row */
00440 
00441   vl_free (from) ;
00442   vl_free (which) ;
00443   vl_free (base) ;
00444   vl_free (baseIndexes) ;
00445 }
00446 
00447 /* VL_TYPE_FLOAT, VL_TYPE_DOUBLE */
00448 #endif
00449 
00450 /* ---------------------------------------------------------------- */
00451 /*                         Image convolution by a triangular kernel */
00452 /* ---------------------------------------------------------------- */
00453 
00454 #if (FLT == VL_TYPE_FLOAT || FLT == VL_TYPE_DOUBLE)
00455 
00510 VL_EXPORT void
00511 VL_XCAT(vl_imconvcoltri_, SFX)
00512 (T * dest, vl_size destStride,
00513  T const * image,
00514  vl_size imageWidth, vl_size imageHeight, vl_size imageStride,
00515  vl_size filterSize,
00516  vl_size step, unsigned int flags)
00517 {
00518   vl_index x, y, dheight ;
00519   vl_bool transp = flags & VL_TRANSPOSE ;
00520   vl_bool zeropad = (flags & VL_PAD_MASK) == VL_PAD_BY_ZERO ;
00521   T scale = (T) (1.0 / ((double)filterSize * (double)filterSize)) ;
00522   T * buffer = vl_malloc (sizeof(T) * (imageHeight + filterSize)) ;
00523   buffer += filterSize ;
00524 
00525   if (imageHeight == 0) {
00526     return  ;
00527   }
00528 
00529   x = 0 ;
00530   dheight = (imageHeight - 1) / step + 1 ;
00531 
00532   while (x < (signed)imageWidth) {
00533     T const * imagei ;
00534     imagei = image + x + imageStride * (imageHeight - 1) ;
00535 
00536     /* We decompose the convolution by a triangluar signal as the convolution
00537      * by two rectangular signals. The rectangular convolutions are computed
00538      * quickly by computing the integral signals. Each rectangular convolution
00539      * introduces a delay, which is compensated by convolving each in opposite
00540      * directions.
00541      */
00542 
00543     /* integrate backward the column */
00544     buffer[imageHeight - 1] = *imagei ;
00545     for (y = (signed)imageHeight - 2 ; y >=  0 ; --y) {
00546       imagei -= imageStride ;
00547       buffer[y] = buffer[y + 1] + *imagei ;
00548     }
00549     if (zeropad) {
00550       for ( ; y >= - (signed)filterSize ; --y) {
00551         buffer[y] = buffer[y + 1] ;
00552       }
00553     } else {
00554       for ( ; y >= - (signed)filterSize ; --y) {
00555         buffer[y] = buffer[y + 1] + *imagei ;
00556       }
00557     }
00558 
00559     /* compute the filter forward */
00560     for (y = - (signed)filterSize ;
00561          y < (signed)imageHeight - (signed)filterSize ; ++y) {
00562       buffer[y] = buffer[y] - buffer[y + filterSize] ;
00563     }
00564     if (! zeropad) {
00565       for (y = (signed)imageHeight - (signed)filterSize ;
00566            y < (signed)imageHeight ;
00567            ++y) {
00568         buffer[y] = buffer[y] - buffer[imageHeight - 1]  *
00569         ((signed)imageHeight - (signed)filterSize - y) ;
00570       }
00571     }
00572 
00573     /* integrate forward the column */
00574     for (y = - (signed)filterSize + 1 ;
00575          y < (signed)imageHeight ; ++y) {
00576       buffer[y] += buffer[y - 1] ;
00577     }
00578 
00579     /* compute the filter backward */
00580     {
00581       vl_size stride = transp ? 1 : destStride ;
00582       dest += dheight * stride ;
00583       for (y = step * (dheight - 1) ; y >= 0 ; y -= step) {
00584         dest -= stride ;
00585         *dest = scale * (buffer[y] - buffer[y - (signed)filterSize]) ;
00586       }
00587       dest += transp ? destStride : 1 ;
00588     }
00589     x += 1 ;
00590   } /* next x */
00591   vl_free (buffer - filterSize) ;
00592 }
00593 
00594 /* VL_TYPE_FLOAT, VL_TYPE_DOUBLE */
00595 #endif
00596 
00597 /* ---------------------------------------------------------------- */
00598 /*                                               Gaussian Smoothing */
00599 /* ---------------------------------------------------------------- */
00600 
00601 #if (FLT == VL_TYPE_FLOAT || FLT == VL_TYPE_DOUBLE)
00602 
00620 static T*
00621 VL_XCAT(_vl_new_gaussian_fitler_,SFX)(vl_size *size, double sigma)
00622 {
00623   T* filter ;
00624   T mass = (T)1.0 ;
00625   vl_index i ;
00626   vl_size width = vl_ceil_d(sigma * 3.0) ;
00627   *size = 2 * width + 1 ;
00628 
00629   assert(size) ;
00630 
00631   filter = vl_malloc((*size) * sizeof(T)) ;
00632   filter[width] = 1.0 ;
00633   for (i = 1 ; i <= (signed)width ; ++i) {
00634     double x = (double)i / sigma ;
00635     double g = exp(-0.5 * x * x) ;
00636     mass += g + g ;
00637     filter[width-i] = g ;
00638     filter[width+i] = g ;
00639   }
00640   for (i = 0 ; i < (signed)(*size) ; ++i) {filter[i] /= mass ;}
00641   return filter ;
00642 }
00643 
00644 VL_EXPORT void
00645 VL_XCAT(vl_imsmooth_, SFX)
00646 (T * smoothed, vl_size smoothedStride,
00647  T const *image, vl_size width, vl_size height, vl_size stride,
00648  double sigmax, double sigmay)
00649 {
00650   T *filterx, *filtery, *buffer ;
00651   vl_size sizex, sizey ;
00652 
00653   filterx = VL_XCAT(_vl_new_gaussian_fitler_,SFX)(&sizex,sigmax) ;
00654   if (sigmax == sigmay) {
00655     filtery = filterx ;
00656     sizey = sizex ;
00657   } else {
00658     filtery = VL_XCAT(_vl_new_gaussian_fitler_,SFX)(&sizey,sigmay) ;
00659   }
00660   buffer = vl_malloc(width*height*sizeof(T)) ;
00661 
00662   VL_XCAT(vl_imconvcol_v,SFX) (buffer, height,
00663                                image, width, height, stride,
00664                                filtery,
00665                                -((signed)sizey-1)/2, ((signed)sizey-1)/2,
00666                                1, VL_PAD_BY_CONTINUITY | VL_TRANSPOSE) ;
00667 
00668   VL_XCAT(vl_imconvcol_v,SFX) (smoothed, smoothedStride,
00669                                buffer, height, width, height,
00670                                filterx,
00671                                -((signed)sizex-1)/2, ((signed)sizex-1)/2,
00672                                1, VL_PAD_BY_CONTINUITY | VL_TRANSPOSE) ;
00673 
00674   vl_free(buffer) ;
00675   vl_free(filterx) ;
00676   if (sigmax != sigmay) {
00677     vl_free(filtery) ;
00678   }
00679 }
00680 
00681 /* VL_TYPE_FLOAT, VL_TYPE_DOUBLE */
00682 #endif
00683 
00684 /* ---------------------------------------------------------------- */
00685 /*                                                   Image Gradient */
00686 /* ---------------------------------------------------------------- */
00687 
00688 #if (FLT == VL_TYPE_FLOAT || FLT == VL_TYPE_DOUBLE)
00689 
00722 VL_EXPORT void
00723 VL_XCAT(vl_imgradient_, SFX)
00724 (T * xGradient, T * yGradient,
00725  vl_size gradWidthStride, vl_size gradHeightStride,
00726  T const * image,
00727  vl_size imageWidth, vl_size imageHeight,
00728  vl_size imageStride)
00729 {
00730   /* Shortcuts */
00731   vl_index const xo = 1 ;
00732   vl_index const yo = imageStride ;
00733   vl_size const w = imageWidth;
00734   vl_size const h = imageHeight;
00735 
00736   T const *src, *end ;
00737   T *pgrad_x, *pgrad_y;
00738   vl_size y;
00739 
00740   src  = image ;
00741   pgrad_x = xGradient ;
00742   pgrad_y = yGradient ;
00743 
00744   /* first pixel of the first row */
00745   *pgrad_x = src[+xo] - src[0] ;
00746   pgrad_x += gradWidthStride;
00747   *pgrad_y = src[+yo] - src[0] ;
00748   pgrad_y += gradWidthStride;
00749   src++;
00750 
00751   /* middle pixels of the  first row */
00752   end = (src - 1) + w - 1 ;
00753   while (src < end) {
00754     *pgrad_x = 0.5 * (src[+xo] - src[-xo]) ;
00755     pgrad_x += gradWidthStride;
00756     *pgrad_y =        src[+yo] - src[0] ;
00757     pgrad_y += gradWidthStride;
00758     src++;
00759   }
00760 
00761   /* last pixel of the first row */
00762   *pgrad_x = src[0]   - src[-xo] ;
00763   pgrad_x += gradWidthStride;
00764   *pgrad_y = src[+yo] - src[0] ;
00765   pgrad_y += gradWidthStride;
00766   src++;
00767 
00768   xGradient += gradHeightStride;
00769   pgrad_x = xGradient;
00770   yGradient += gradHeightStride;
00771   pgrad_y = yGradient;
00772   image += yo;
00773   src = image;
00774 
00775   for (y = 1 ; y < h -1 ; ++y) {
00776 
00777     /* first pixel of the middle rows */
00778     *pgrad_x =        src[+xo] - src[0] ;
00779     pgrad_x += gradWidthStride;
00780     *pgrad_y = 0.5 * (src[+yo] - src[-yo]) ;
00781     pgrad_y += gradWidthStride;
00782     src++;
00783 
00784     /* middle pixels of the middle rows */
00785     end = (src - 1) + w - 1 ;
00786     while (src < end) {
00787       *pgrad_x = 0.5 * (src[+xo] - src[-xo]) ;
00788       pgrad_x += gradWidthStride;
00789       *pgrad_y = 0.5 * (src[+yo] - src[-yo]) ;
00790       pgrad_y += gradWidthStride;
00791       src++;
00792     }
00793 
00794     /* last pixel of the middle row */
00795     *pgrad_x =        src[0]   - src[-xo] ;
00796     pgrad_x += gradWidthStride;
00797     *pgrad_y = 0.5 * (src[+yo] - src[-yo]) ;
00798     pgrad_y += gradWidthStride;
00799     src++;
00800 
00801     xGradient += gradHeightStride;
00802     pgrad_x = xGradient;
00803     yGradient += gradHeightStride;
00804     pgrad_y = yGradient;
00805     image += yo;
00806     src = image;
00807   }
00808 
00809   /* first pixel of the last row */
00810   *pgrad_x = src[+xo] - src[0] ;
00811   pgrad_x += gradWidthStride;
00812   *pgrad_y = src[  0] - src[-yo] ;
00813   pgrad_y += gradWidthStride;
00814   src++;
00815 
00816   /* middle pixels of the last row */
00817   end = (src - 1) + w - 1 ;
00818   while (src < end) {
00819     *pgrad_x = 0.5 * (src[+xo] - src[-xo]) ;
00820     pgrad_x += gradWidthStride;
00821     *pgrad_y =        src[0]   - src[-yo] ;
00822     pgrad_y += gradWidthStride;
00823     src++;
00824   }
00825 
00826   /* last pixel of the last row */
00827   *pgrad_x = src[0]   - src[-xo] ;
00828   *pgrad_y = src[0]   - src[-yo] ;
00829 }
00830 /* VL_TYPE_FLOAT, VL_TYPE_DOUBLE */
00831 #endif
00832 
00833 
00872 #if (FLT == VL_TYPE_FLOAT || FLT == VL_TYPE_DOUBLE)
00873 
00874 VL_EXPORT void
00875 VL_XCAT(vl_imgradient_polar_, SFX)
00876 (T * gradientModulus, T * gradientAngle,
00877  vl_size gradientHorizontalStride, vl_size gradHeightStride,
00878  T const* image,
00879  vl_size imageWidth, vl_size imageHeight, vl_size imageStride)
00880 {
00881   /* Shortcuts */
00882   vl_index const xo = 1 ;
00883   vl_index const yo = imageStride ;
00884   vl_size const w = imageWidth;
00885   vl_size const h = imageHeight;
00886 
00887   T const *src, *end;
00888   T *pgrad_angl, *pgrad_ampl;
00889   T gx, gy ;
00890   vl_size y;
00891 
00892 #define SAVE_BACK                                                    \
00893 *pgrad_ampl = vl_fast_sqrt_f (gx*gx + gy*gy) ;                       \
00894 pgrad_ampl += gradientHorizontalStride ;                             \
00895 *pgrad_angl = vl_mod_2pi_f   (vl_fast_atan2_f (gy, gx) + 2*VL_PI) ;  \
00896 pgrad_angl += gradientHorizontalStride ;                             \
00897 ++src ;                                                              \
00898 
00899   src  = image ;
00900   pgrad_angl = gradientAngle ;
00901   pgrad_ampl = gradientModulus ;
00902 
00903   /* first pixel of the first row */
00904   gx = src[+xo] - src[0] ;
00905   gy = src[+yo] - src[0] ;
00906   SAVE_BACK ;
00907 
00908   /* middle pixels of the  first row */
00909   end = (src - 1) + w - 1 ;
00910   while (src < end) {
00911     gx = 0.5 * (src[+xo] - src[-xo]) ;
00912     gy =        src[+yo] - src[0] ;
00913     SAVE_BACK ;
00914   }
00915 
00916   /* last pixel of the first row */
00917   gx = src[0]   - src[-xo] ;
00918   gy = src[+yo] - src[0] ;
00919   SAVE_BACK ;
00920 
00921   gradientModulus += gradHeightStride;
00922   pgrad_ampl = gradientModulus;
00923   gradientAngle += gradHeightStride;
00924   pgrad_angl = gradientAngle;
00925   image += imageStride;
00926   src = image;
00927 
00928   for (y = 1 ; y < h -1 ; ++y) {
00929 
00930     /* first pixel of the middle rows */
00931     gx =        src[+xo] - src[0] ;
00932     gy = 0.5 * (src[+yo] - src[-yo]) ;
00933     SAVE_BACK ;
00934 
00935     /* middle pixels of the middle rows */
00936     end = (src - 1) + w - 1 ;
00937     while (src < end) {
00938       gx = 0.5 * (src[+xo] - src[-xo]) ;
00939       gy = 0.5 * (src[+yo] - src[-yo]) ;
00940       SAVE_BACK ;
00941     }
00942 
00943     /* last pixel of the middle row */
00944     gx =        src[0]   - src[-xo] ;
00945     gy = 0.5 * (src[+yo] - src[-yo]) ;
00946     SAVE_BACK ;
00947 
00948     gradientModulus += gradHeightStride;
00949     pgrad_ampl = gradientModulus;
00950     gradientAngle += gradHeightStride;
00951     pgrad_angl = gradientAngle;
00952     image += imageStride;
00953     src = image;
00954   }
00955 
00956   /* first pixel of the last row */
00957   gx = src[+xo] - src[0] ;
00958   gy = src[  0] - src[-yo] ;
00959   SAVE_BACK ;
00960 
00961   /* middle pixels of the last row */
00962   end = (src - 1) + w - 1 ;
00963   while (src < end) {
00964     gx = 0.5 * (src[+xo] - src[-xo]) ;
00965     gy =        src[0]   - src[-yo] ;
00966     SAVE_BACK ;
00967   }
00968 
00969   /* last pixel of the last row */
00970   gx = src[0]   - src[-xo] ;
00971   gy = src[0]   - src[-yo] ;
00972   SAVE_BACK ;
00973 
00974 }
00975 /* VL_TYPE_FLOAT, VL_TYPE_DOUBLE */
00976 #endif
00977 
00978 /* ---------------------------------------------------------------- */
00979 /*                                                   Integral Image */
00980 /* ---------------------------------------------------------------- */
00981 
01041 VL_EXPORT void
01042 VL_XCAT(vl_imintegral_, SFX)
01043 (T * integral, vl_size integralStride,
01044  T const * image,
01045  vl_size imageWidth, vl_size imageHeight, vl_size imageStride)
01046 {
01047   vl_uindex x, y ;
01048   T temp  = 0 ;
01049 
01050   if (imageHeight > 0) {
01051     for (x = 0 ; x < imageWidth ; ++ x) {
01052       temp += *image++ ;
01053       *integral++ = temp ;
01054     }
01055   }
01056 
01057   for (y = 1 ; y < imageHeight ; ++ y) {
01058     T * integralPrev ;
01059     integral += integralStride - imageWidth ;
01060     image += imageStride - imageWidth ;
01061     integralPrev = integral - integralStride ;
01062 
01063     temp = 0 ;
01064     for (x = 0 ; x < imageWidth ; ++ x) {
01065       temp += *image++ ;
01066       *integral++ = *integralPrev++ + temp ;
01067     }
01068   }
01069 }
01070 
01071 /* endif VL_IMOPV_INSTANTIATING */
01072 #undef FLT
01073 #undef VL_IMOPV_INSTANTIATING
01074 #endif


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