00001
00006
00007
00008
00009
00010
00011
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
00058 #endif
00059
00060 #if defined(VL_IMOPV_INSTANTIATING) || defined(__DOXYGEN__)
00061
00062 #include "float.th"
00063
00064
00065
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
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
00146 filt += filt_end - filt_begin ;
00147
00148 while (x < (signed)src_width) {
00149
00150
00151
00152
00153
00154
00155
00156
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 }
00205 if (transp) {
00206 dst += 1 * dst_stride - dheight * 1 ;
00207 } else {
00208 dst += 1 * 1 - dheight * dst_stride ;
00209 }
00210 x += 1 ;
00211 }
00212 }
00213
00214
00215 #endif
00216
00217
00218
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
00341
00342
00343
00344
00345
00346
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
00368
00369
00370
00371
00372
00373
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
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
00394
00395
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
00404 -- num ;
00405 } else {
00406
00407 from_ = inters ;
00408 break ;
00409 }
00410 }
00411
00412
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 }
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
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 }
00440
00441 vl_free (from) ;
00442 vl_free (which) ;
00443 vl_free (base) ;
00444 vl_free (baseIndexes) ;
00445 }
00446
00447
00448 #endif
00449
00450
00451
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
00537
00538
00539
00540
00541
00542
00543
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
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
00574 for (y = - (signed)filterSize + 1 ;
00575 y < (signed)imageHeight ; ++y) {
00576 buffer[y] += buffer[y - 1] ;
00577 }
00578
00579
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 }
00591 vl_free (buffer - filterSize) ;
00592 }
00593
00594
00595 #endif
00596
00597
00598
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
00682 #endif
00683
00684
00685
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
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
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
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
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
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
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
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
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
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
00827 *pgrad_x = src[0] - src[-xo] ;
00828 *pgrad_y = src[0] - src[-yo] ;
00829 }
00830
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
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
00904 gx = src[+xo] - src[0] ;
00905 gy = src[+yo] - src[0] ;
00906 SAVE_BACK ;
00907
00908
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
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
00931 gx = src[+xo] - src[0] ;
00932 gy = 0.5 * (src[+yo] - src[-yo]) ;
00933 SAVE_BACK ;
00934
00935
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
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
00957 gx = src[+xo] - src[0] ;
00958 gy = src[ 0] - src[-yo] ;
00959 SAVE_BACK ;
00960
00961
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
00970 gx = src[0] - src[-xo] ;
00971 gy = src[0] - src[-yo] ;
00972 SAVE_BACK ;
00973
00974 }
00975
00976 #endif
00977
00978
00979
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
01072 #undef FLT
01073 #undef VL_IMOPV_INSTANTIATING
01074 #endif