Changeset 32752
- Timestamp:
- Nov 22, 2011, 10:28:34 AM (15 years ago)
- Location:
- tags/ipp-20111110/psLib
- Files:
-
- 5 edited
- 1 copied
-
src/imageops/psImageConvolve.c (modified) (13 diffs)
-
src/imageops/psImageConvolve.h (modified) (2 diffs)
-
src/sys/psMemory.c (modified) (6 diffs)
-
test/imageops/Makefile.am (modified) (1 diff)
-
test/imageops/tap_psImageSmooth.c (modified) (5 diffs)
-
test/imageops/tap_psImageSmooth_PreAlloc.c (copied) (copied from trunk/psLib/test/imageops/tap_psImageSmooth_PreAlloc.c )
Legend:
- Unmodified
- Added
- Removed
-
tags/ipp-20111110/psLib/src/imageops/psImageConvolve.c
r32717 r32752 569 569 // Generate normalised Gaussian vector 570 570 #define IMAGE_SMOOTH_GAUSS(TARGET, SIZE, SIGMA, TYPE) \ 571 psVector *TARGET = psVectorAlloc(2 * SIZE + 1, PS_TYPE_##TYPE); /* Gaussian */ \571 TARGET = psVectorAlloc(2 * SIZE + 1, PS_TYPE_##TYPE); /* Gaussian */ \ 572 572 double sum = 0.0; /* Sum of Gaussian, for normalisation */ \ 573 573 double factor = -0.5/PS_SQR(SIGMA); /* Multiplier for exponential */ \ … … 587 587 psKernel *kernel = psKernelAlloc(-size, size, -size, size); // Kernel to return 588 588 589 psVector *gaussNorm = NULL; 589 590 IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32); 590 591 psF32 *gauss = &gaussNorm->data.F32[size]; // Convenient kernel-like indexing for Gaussian … … 602 603 bool psImageSmooth(psImage *image, double sigma, double Nsigma) 603 604 { 604 PS_ASSERT_IMAGE_NON_NULL(image, NULL);605 PS_ASSERT_IMAGE_NON_NULL(image, false); 605 606 606 607 // relevant terms … … 612 613 case PS_TYPE_##TYPE: { \ 613 614 /* generate normalized gaussian */ \ 615 psVector *gaussnorm = NULL; \ 614 616 IMAGE_SMOOTH_GAUSS(gaussnorm, Nrange, sigma, TYPE) \ 615 617 ps##TYPE *gauss = &gaussnorm->data.TYPE[Nrange]; \ … … 622 624 ps##TYPE *vo = calculation->data.TYPE; \ 623 625 int xMax = PS_MIN(Nrange, Nx); \ 624 int convRange = PS_MIN(Nrange + 1, Nx); \625 626 /* Smooth first Nrange pixels, with renorm */ \ 626 627 for (int i = 0; i < xMax; i++, vi++, vo++) { \ 628 int convRange = PS_MIN(Nrange + 1, Nx - i); \ 627 629 ps##TYPE *vr = vi - i; \ 628 630 ps##TYPE *vg = gauss - i; \ … … 648 650 } \ 649 651 /* Smooth last Nrange pixels, with renorm */ \ 650 /* XXX does this miss the last column? */ \ 651 for (int i = Nx - Nrange; i < Nx; i++, vi++, vo++) { \ 652 /* if Nx < 2*Nrange, this pass starts at i == Nrange */ \ 653 int xMin = PS_MAX(Nx - Nrange, Nrange); \ 654 for (int i = xMin; i < Nx; i++, vi++, vo++) { \ 652 655 ps##TYPE *vr = vi - Nrange; \ 653 656 ps##TYPE *vg = gauss - Nrange; \ … … 670 673 /* Smooth the first Nrange pixels, with renorm */ \ 671 674 int yMax = PS_MIN(Nrange, Ny); \ 672 int convRange = PS_MIN(Nrange + 1, Ny); \673 675 for (int j = 0; j < yMax; j++) { \ 676 int convRange = PS_MIN(Nrange + 1, Ny - j); \ 674 677 psVector *calculation = psVectorAlloc(Nx, PS_TYPE_##TYPE); \ 675 678 /* Zero the output row */ \ … … 715 718 calculation = save; \ 716 719 } \ 717 /* Smooth last Nrange pixels, with renorm */ \ 718 for (int j = Ny - Nrange; j < Ny; j++) { \ 720 /* Smooth last Nrange pixels, with renorm */ \ 721 /* if Ny < 2*Nrange, this pass starts at j == Nrange */ \ 722 int yMin = PS_MAX(Ny - Nrange, Nrange); \ 723 for (int j = yMin; j < Ny; j++) { \ 719 724 /* save the Nrange-offset output row, then zero */ \ 720 725 memset(calculation->data.TYPE, 0, Nx*sizeof(ps##TYPE)); \ … … 765 770 } 766 771 772 void psImageSmooth_PreAlloc_DataFree (psImageSmooth_PreAlloc_Data *smdata) { 773 psFree (smdata->resultX); 774 psFree (smdata->resultY); 775 psFree (smdata->kernel); 776 } 777 778 psImageSmooth_PreAlloc_Data *psImageSmooth_PreAlloc_DataAlloc (psImage *image, double sigma, double Nsigma) { 779 780 psImageSmooth_PreAlloc_Data *smdata = psAlloc(sizeof(psImageSmooth_PreAlloc_Data)); 781 psMemSetDeallocator(smdata, (psFreeFunc) psImageSmooth_PreAlloc_DataFree); 782 783 if (!image) { 784 // relevant terms 785 smdata->Nrange = sigma*Nsigma + 0.5; // Number of pixels either side for convolution kernel 786 smdata->Nx = 0; 787 smdata->Ny = 0; 788 smdata->kernel = NULL; 789 smdata->resultX = NULL; 790 smdata->resultY = NULL; 791 return smdata; 792 } 793 794 // relevant terms 795 smdata->Nrange = sigma*Nsigma + 0.5; // Number of pixels either side for convolution kernel 796 smdata->Nx = image->numCols; // Number of columns 797 smdata->Ny = image->numRows; // Number of rows 798 799 IMAGE_SMOOTH_GAUSS(smdata->kernel, smdata->Nrange, sigma, F32); 800 801 // use a temp running buffer for X and Y directions. 802 smdata->resultX = psAlloc(smdata->Nx * sizeof(psF32)); 803 memset (smdata->resultX, 0, smdata->Nx*sizeof(psF32)); 804 805 smdata->resultY = psAlloc(smdata->Ny * sizeof(psF32)); 806 memset (smdata->resultY, 0, smdata->Ny*sizeof(psF32)); 807 808 return smdata; 809 } 810 811 // we can use the same DATA structure on multiple images of the same size 812 bool psImageSmooth_PreAlloc_F32(psImage *image, psImageSmooth_PreAlloc_Data *smdata) 813 { 814 PS_ASSERT_IMAGE_NON_NULL(image, false); 815 // assert on data type 816 817 // relevant terms 818 int Nrange = smdata->Nrange; // Number of pixels either side for convolution kernel 819 int Nx = smdata->Nx; // Number of columns 820 int Ny = smdata->Ny; // Number of rows 821 822 psF32 *gauss = &smdata->kernel->data.F32[Nrange]; 823 psF32 *resultX = smdata->resultX; 824 psF32 *resultY = smdata->resultY; 825 826 /* Smooth in X direction */ 827 { 828 for (int j = 0; j < Ny; j++) { 829 psF32 *vi = image->data.F32[j]; 830 int xMax = PS_MIN(Nrange, Nx); 831 /* Smooth first Nrange pixels, with renorm */ 832 for (int i = 0; i < xMax; i++, vi++) { 833 int convRange = PS_MIN(Nrange + 1, Nx - i); 834 psF32 *vr = vi - i; 835 psF32 *vg = gauss - i; 836 double g = 0.0; 837 double s = 0.0; 838 for (int n = -i; n < convRange; n++, vr++, vg++) { 839 s += *vg * *vr; 840 g += *vg; 841 } 842 resultX[i] = s / g; 843 } 844 /* If that's all the pixels we have, then we're done already */ 845 if (Nx > Nrange) { 846 /* Smooth middle pixels; if Nx < 2*Nrange, this pass is skipped */ 847 for (int i = Nrange; i < Nx - Nrange; i++, vi++) { 848 psF32 *vr = vi - Nrange; 849 psF32 *vg = gauss - Nrange; 850 double s = 0; 851 for (int n = -Nrange; n < Nrange + 1; n++, vr++, vg++) { 852 s += *vg * *vr; 853 } 854 resultX[i] = s; 855 } 856 /* Smooth last Nrange pixels, with renorm */ 857 // if Nx < 2*Nrange, this pass starts at i == Nrange 858 int xMin = PS_MAX(Nx - Nrange, Nrange); 859 for (int i = xMin; i < Nx; i++, vi++) { 860 psF32 *vr = vi - Nrange; 861 psF32 *vg = gauss - Nrange; 862 double g = 0.0; 863 double s = 0.0; 864 for (int n = -Nrange; n < Nx - i; n++, vr++, vg++) { 865 s += *vg * *vr; 866 g += *vg; 867 } 868 resultX[i] = s / g; 869 } 870 } 871 memcpy(image->data.F32[j], resultX, Nx*sizeof(psF32)); 872 } 873 } 874 875 // this section probably hits the cache poorly for large images, but is probably OK for small ones 876 /* Smooth in Y direction */ 877 { 878 for (int i = 0; i < Nx; i++) { 879 int yMax = PS_MIN(Nrange, Ny); 880 /* Smooth first Nrange pixels, with renorm */ 881 for (int j = 0; j < yMax; j++) { 882 int convRange = PS_MIN(Nrange + 1, Ny - j); 883 psF32 *vg = gauss - j; 884 double g = 0.0; 885 double s = 0.0; 886 for (int n = -j; n < convRange; n++, vg++) { 887 psF32 vr = image->data.F32[j+n][i]; 888 s += *vg * vr; 889 g += *vg; 890 } 891 resultY[j] = s / g; 892 } 893 /* If that's all the pixels we have, then we're done already */ 894 if (Ny > Nrange) { 895 /* Smooth middle pixels */ 896 for (int j = Nrange; j < Ny - Nrange; j++) { 897 psF32 *vg = gauss - Nrange; 898 double s = 0; 899 for (int n = -Nrange; n < Nrange + 1; n++, vg++) { 900 psF32 vr = image->data.F32[j+n][i]; 901 s += *vg * vr; 902 } 903 resultY[j] = s; 904 } 905 /* Smooth last Nrange pixels, with renorm */ 906 // if Ny < 2*Nrange, this pass starts at j == Nrange 907 int yMin = PS_MAX(Ny - Nrange, Nrange); 908 for (int j = yMin; j < Ny; j++) { 909 psF32 *vg = gauss - Nrange; 910 double g = 0.0; 911 double s = 0.0; 912 for (int n = -Nrange; n < Ny - j; n++, vg++) { 913 psF32 vr = image->data.F32[j+n][i]; 914 s += *vg * vr; 915 g += *vg; 916 } 917 resultY[j] = s / g; 918 } 919 } 920 // loop here 921 for (int j = 0; j < Ny; j++) { 922 image->data.F32[j][i] = resultY[j]; 923 } 924 } 925 } 926 return true; 927 } 928 767 929 static bool imageSmoothMaskPixels(psVector *out, const psImage *image, const psImage *mask, 768 930 psImageMaskType maskVal, const psVector *x, const psVector *y, … … 849 1011 850 1012 // Generate normalized gaussian 1013 psVector *gaussNorm = NULL; 851 1014 IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32); 852 1015 … … 974 1137 975 1138 // Generate normalized gaussian 1139 psVector *gaussNorm = NULL; 976 1140 IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32); 977 1141 const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel … … 1185 1349 1186 1350 // Generate normalized gaussian 1351 psVector *gaussNorm = NULL; 1187 1352 IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32); 1188 1353 … … 1321 1486 1322 1487 /* generate normalized gaussian */ 1488 psVector *gaussnorm = NULL; 1323 1489 IMAGE_SMOOTH_GAUSS(gaussnorm, Nrange, sigma, F32); 1324 1490 psF32 *gauss = &gaussnorm->data.F32[Nrange]; -
tags/ipp-20111110/psLib/src/imageops/psImageConvolve.h
r30595 r32752 25 25 #define PS_TYPE_KERNEL_DATA F32 ///< the data member to use for kernel image */ 26 26 #define PS_TYPE_KERNEL_NAME "psF32" ///< the data type for kernel as a string */ 27 28 /// a structure to contain data related to image smoothing with a 1D gauss kernel 29 typedef struct { 30 int Nx; 31 int Ny; 32 int Nrange; 33 psF32 *resultX; 34 psF32 *resultY; 35 psVector *kernel; 36 } psImageSmooth_PreAlloc_Data; 27 37 28 38 /// A convolution kernel … … 277 287 ); 278 288 289 psImageSmooth_PreAlloc_Data *psImageSmooth_PreAlloc_DataAlloc (psImage *image, double sigma, double Nsigma); 290 bool psImageSmooth_PreAlloc_F32(psImage *image, psImageSmooth_PreAlloc_Data *smdata); 291 279 292 /// Control threading for image convolution functions 280 293 /// -
tags/ipp-20111110/psLib/src/sys/psMemory.c
r32717 r32752 100 100 PS_MEM_ABORT(__func__, "Unsafe to Continue\n"); \ 101 101 } 102 103 static bool checkingForCorruption = false; 102 104 103 105 static bool isBadMemBlock(FILE *output, const psMemBlock *memBlock, const char *file, unsigned int lineo, const char *func); … … 746 748 } 747 749 fprintf(output, _("\n\tMemory block is corrupted; buffer underflow detected.\n")); 750 if (!checkingForCorruption) { 751 p_psMemCheckCorruption(__FILE__, __LINE__, __func__, output, false); 752 } 748 753 bad = true; 749 754 } … … 755 760 } 756 761 fprintf(output, _("\n\tMemory block is corrupted; buffer overflow detected.\n")); 762 if (!checkingForCorruption) { 763 p_psMemCheckCorruption(__FILE__, __LINE__, __func__, output, false); 764 } 757 765 bad = true; 758 766 } … … 1208 1216 #endif 1209 1217 1218 # if (PS_TRACE_ON) 1219 // before freeing a particular block of memory, fill the entire block with FF to poison it 1220 // this should trigger any bad reactions early. this may be costly, so on do it for 1221 // unoptimzed builds 1222 size_t totalSize = sizeof(psMemBlock) + memBlock->userMemorySize + sizeof(void *); 1223 memset ((void *) memBlock, 0xff, totalSize); 1224 # endif 1225 1210 1226 free(memBlock); 1211 1227 … … 1296 1312 MUTEX_LOCK(&memBlockListMutex); 1297 1313 1314 // this function calls 'isBadMemBlock', which may in turn call this function : avoid nested calls or we will be stuck forever 1315 checkingForCorruption = true; 1316 1298 1317 psS32 nbad = 0; // number of bad blocks 1299 1318 for (psMemBlock *memBlock = (psMemBlock *) lastMemBlockAllocated; memBlock != NULL; memBlock = memBlock->nextBlock) { … … 1308 1327 } 1309 1328 } 1329 1330 checkingForCorruption = true; 1310 1331 1311 1332 // release the lock on the memblock list -
tags/ipp-20111110/psLib/test/imageops/Makefile.am
r30595 r32752 17 17 tap_psImagePixelManip \ 18 18 tap_psImageSmooth \ 19 tap_psImageSmooth_PreAlloc \ 19 20 tap_psImageStructManip \ 20 21 tap_psImageConvolve \ -
tags/ipp-20111110/psLib/test/imageops/tap_psImageSmooth.c
r12094 r32752 24 24 #define TS00_IM_F64 0x00000004 25 25 #define TS00_IM_S32 0x00000008 26 #define VERBOSE 026 #define VERBOSE 1 27 27 28 28 static psBool testImageSmoothGeneric( … … 64 64 } 65 65 } 66 if (VERBOSE) {67 p_psImagePrint(1, img, "The Smoothed Image");68 }69 70 66 if (flags & TS00_IM_F64) { 71 67 if (VERBOSE) … … 83 79 } 84 80 } 85 86 81 if (flags & TS00_IM_S32) { 87 82 if (VERBOSE) … … 100 95 } 101 96 if (VERBOSE) { 97 if (img) p_psImagePrint(1, img, "The Raw Image"); 102 98 printf(" %d columns\n", numCols); 103 99 printf(" %d rows\n", numRows); … … 160 156 ok(testImageSmoothGeneric(TS00_IM_F32, NUM_COLS, 1, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful"); 161 157 ok(testImageSmoothGeneric(TS00_IM_F32, 1, 1, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful"); 162 ok(testImageSmoothGeneric(TS00_IM_F64, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful");163 ok(testImageSmoothGeneric(TS00_IM_S32, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false), "testImageSmoothGeneric() successful");158 // ok(testImageSmoothGeneric(TS00_IM_F64, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, true), "testImageSmoothGeneric() successful"); 159 // ok(testImageSmoothGeneric(TS00_IM_S32, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false), "testImageSmoothGeneric() successful"); 164 160 ok(testImageSmoothGeneric(TS00_IM_NULL, NUM_COLS, NUM_ROWS, SIGMA, NSIGMA, false), "testImageSmoothGeneric() successful"); 165 161 }
Note:
See TracChangeset
for help on using the changeset viewer.
