Changeset 19059 for trunk/psModules/src/imcombine/pmSubtraction.c
- Timestamp:
- Aug 13, 2008, 5:25:55 PM (18 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/imcombine/pmSubtraction.c (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imcombine/pmSubtraction.c
r18962 r19059 21 21 #include "pmSubtractionStamps.h" 22 22 #include "pmSubtractionEquation.h" 23 #include "pmSubtractionThreads.h" 23 24 24 25 #include "pmSubtraction.h" … … 28 29 #define PIXEL_LIST_BUFFER 100 // Number of entries to add to pixel list at a time 29 30 #define MIN_SAMPLE_STATS 7 // Minimum number to use sample statistics; otherwise use quartiles 31 30 32 31 33 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// … … 213 215 region.y0 - size, region.y1 + size); // Add a border 214 216 215 // Casting away const so psImageSubset can add the child 217 // Casting away const 218 psMutexLock((psImage*)image); 216 219 psImage *subImage = psImageSubset((psImage*)image, border); // Subimage to convolve 220 psMutexUnlock((psImage*)image); 221 222 // Casting away const 223 psMutexLock((psImage*)mask); 217 224 psImage *subMask = mask ? psImageSubset((psImage*)mask, border) : NULL; // Subimage mask 225 psMutexUnlock((psImage*)mask); 226 218 227 psImage *convolved = psImageConvolveFFT(NULL, subImage, subMask, maskVal, kernel); // Convolution 228 229 psMutexLock((psImage*)image); 219 230 psFree(subImage); 231 psMutexUnlock((psImage*)image); 232 233 psMutexLock((psImage*)mask); 220 234 psFree(subMask); 235 psMutexUnlock((psImage*)mask); 221 236 222 237 // Now, we have to chop off the borders, and stick it in where it belongs 238 // No locking because we own this one 223 239 psImage *subConv = psImageSubset(convolved, psRegionSet(size, -size, size, -size)); // Cut off the edges 240 241 psMutexLock(target); 224 242 psImage *subTarget = psImageSubset(target, region); // Target for this subregion 243 psMutexUnlock(target); 225 244 if (background != 0.0) { 226 245 psBinaryOp(subTarget, subConv, "+", psScalarAlloc(background, PS_TYPE_F32)); … … 233 252 psFree(subConv); 234 253 psFree(convolved); 254 psMutexLock(target); 235 255 psFree(subTarget); 256 psMutexUnlock(target); 236 257 return; 237 258 } … … 285 306 // Use Fast Fourier Transform to do the convolution 286 307 // This provides a big speed-up for large kernels 308 287 309 convolveFFT(convImage, image, subMask, maskVal, *kernelImage, region, background, kernels->size); 288 310 if (weight) { … … 711 733 712 734 735 // XXX Put kernelImage, kernelWeight and polyValues on thread-dependent data 736 static bool subtractionConvolvePatch(int numCols, int numRows, int x0, int y0, 737 pmReadout *out1, pmReadout *out2, psImage *convMask, 738 const pmReadout *ro1, const pmReadout *ro2, const psImage *subMask, 739 psMaskType blank, psMaskType maskSource, psMaskType maskTarget, 740 const psRegion *region, const pmSubtractionKernels *kernels, 741 bool doBG, bool useFFT) 742 { 743 int size = kernels->size; // Half-size of kernel 744 int xMin = region->x0, xMax = region->x1, yMin = region->y0, yMax = region->y1; // Bounds of patch 745 746 // Size to use when calculating normalised coordinates (different from actual size when convolving 747 // subimage) 748 int xNormSize = (kernels->numCols > 0 ? kernels->numCols : numCols); 749 int yNormSize = (kernels->numRows > 0 ? kernels->numRows : numRows); 750 751 // Normalised coordinates 752 float yNorm = 2.0 * (float)(yMin + y0 + size + 1 - yNormSize/2.0) / (float)yNormSize; // Normalised coord 753 float xNorm = 2.0 * (float)(xMin + x0 + size + 1 - xNormSize/2.0) / (float)xNormSize; // Normalised coord 754 755 psKernel *kernelImage = NULL; // Kernel for the images 756 psKernel *kernelWeight = NULL; // Kernel for the weight maps 757 758 // Only generate polynomial values every kernel footprint, since we have already assumed 759 // (with the stamps) that it does not vary rapidly on this scale. 760 psImage *polyValues = p_pmSubtractionPolynomial(NULL, kernels->spatialOrder, 761 xNorm, yNorm); // Pre-calculated polynomial values 762 float background = doBG ? p_pmSubtractionSolutionBackground(kernels, polyValues) : 0.0; // Background term 763 764 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 765 convolveRegion(out1->image, out1->weight, &kernelImage, &kernelWeight, ro1->image, ro1->weight, 766 subMask, maskSource, kernels, polyValues, background, *region, useFFT, 767 false); 768 } 769 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 770 convolveRegion(out2->image, out2->weight, &kernelImage, &kernelWeight, ro2->image, ro2->weight, 771 subMask, maskSource, kernels, polyValues, background, *region, useFFT, 772 kernels->mode == PM_SUBTRACTION_MODE_DUAL); 773 } 774 775 psFree(kernelImage); 776 psFree(kernelWeight); 777 psFree(polyValues); 778 779 // Propagate the mask 780 if (subMask) { 781 for (int y = yMin; y < yMax; y++) { 782 for (int x = xMin; x < xMax; x++) { 783 if (subMask->data.PS_TYPE_MASK_DATA[y][x] & maskTarget) { 784 convMask->data.PS_TYPE_MASK_DATA[y][x] |= blank; 785 } 786 } 787 } 788 } 789 790 return true; 791 } 792 793 bool pmSubtractionConvolveThread(const psThreadJob *job) 794 { 795 PS_ASSERT_THREAD_JOB_NON_NULL(job, false); 796 797 psArray *args = job->args; // Arguments 798 int numCols = PS_SCALAR_VALUE(args->data[0], S32); // Number of columns 799 int numRows = PS_SCALAR_VALUE(args->data[1], S32); // Number of rows 800 int x0 = PS_SCALAR_VALUE(args->data[2], S32); // Offset in x 801 int y0 = PS_SCALAR_VALUE(args->data[3], S32); // Offset in x 802 pmReadout *out1 = args->data[4]; // Output readout 1 803 pmReadout *out2 = args->data[5]; // Output readout 2 804 psImage *convMask = args->data[6]; // Output convolved mask 805 const pmReadout *ro1 = args->data[7]; // Input readout 1 806 const pmReadout *ro2 = args->data[8]; // Input readout 2 807 const psImage *subMask = args->data[9]; // Subtraction mask 808 psMaskType blank = PS_SCALAR_VALUE(args->data[10], U8); // Output mask value 809 psMaskType maskSource = PS_SCALAR_VALUE(args->data[11], U8); // Mask value corresponding to source image 810 psMaskType maskTarget = PS_SCALAR_VALUE(args->data[12], U8); // Mask value corresponding to target image 811 const psRegion *region = args->data[13]; // Region to convolve 812 const pmSubtractionKernels *kernels = args->data[14]; // Kernels 813 bool doBG = PS_SCALAR_VALUE(args->data[15], U8); // Do background subtraction? 814 bool useFFT = PS_SCALAR_VALUE(args->data[16], U8); // Use FFT for convolution? 815 816 return subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, 817 ro1, ro2, subMask, blank, maskSource, maskTarget, 818 region, kernels, doBG, useFFT); 819 } 713 820 714 821 bool pmSubtractionConvolve(pmReadout *out1, pmReadout *out2, const pmReadout *ro1, const pmReadout *ro2, … … 767 874 } 768 875 876 bool threaded = pmSubtractionThreaded(); // Running threaded? 877 769 878 // Outputs 770 879 psImage *convImage1 = NULL, *convWeight1 = NULL; // Convolved image and weight from input 1 … … 773 882 if (!convImage1) { 774 883 convImage1 = out1->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 884 if (threaded) { 885 psMutexInit(convImage1); 886 } 775 887 } 776 888 if (weight1) { 777 889 if (!out1->weight) { 778 890 out1->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32); 891 if (threaded) { 892 psMutexInit(out1->weight); 893 } 779 894 } 780 895 convWeight1 = out1->weight; … … 787 902 if (!convImage2) { 788 903 convImage2 = out2->image = psImageAlloc(numCols, numRows, PS_TYPE_F32); 904 if (threaded) { 905 psMutexInit(convImage2); 906 } 789 907 } 790 908 if (weight2) { 791 909 if (!out2->weight) { 792 910 out2->weight = psImageAlloc(numCols, numRows, PS_TYPE_F32); 911 if (threaded) { 912 psMutexInit(out2->weight); 913 } 793 914 } 794 915 convWeight2 = out2->weight; … … 833 954 yMax = PS_MIN(region->y1, yMax); 834 955 } 835 836 // Size to use when calculating normalised coordinates (different from actual size when convolving837 // subimage)838 int xNormSize = (kernels->numCols > 0 ? kernels->numCols : numCols);839 int yNormSize = (kernels->numRows > 0 ? kernels->numRows : numRows);840 956 841 957 psMaskType maskSource; // Mask these pixels when convolving … … 858 974 } 859 975 976 #if 0 977 // XXX Use thread-specific data to store these 860 978 psImage *polyValues = NULL; // Pre-calculated polynomial values 861 979 psKernel *kernelImage = NULL; // Kernel for the images 862 980 psKernel *kernelWeight = NULL; // Kernel for the weight maps 981 #endif 863 982 864 983 for (int j = yMin; j < yMax; j += fullSize) { 865 984 int ySubMax = PS_MIN(j + fullSize, yMax); // Range for subregion of interest 866 float yNorm = 2.0 * (float)(j + y0 + size + 1 - yNormSize/2.0) /867 (float)yNormSize; // Normalised coordinate868 985 for (int i = xMin; i < xMax; i += fullSize) { 869 986 int xSubMax = PS_MIN(i + fullSize, xMax); // Range for subregion of interest 870 float xNorm = 2.0 * (float)(i + x0 + size + 1 - xNormSize/2.0) / 871 (float)xNormSize; // Normalised coordinate 872 873 // Only generate polynomial values every kernel footprint, since we have already assumed 874 // (with the stamps) that it does not vary rapidly on this scale. 875 polyValues = p_pmSubtractionPolynomial(polyValues, kernels->spatialOrder, xNorm, yNorm); 876 float background = doBG ? p_pmSubtractionSolutionBackground(kernels, polyValues) : 877 0.0; // Background term 878 psRegion subRegion = psRegionSet(i, xSubMax, j, ySubMax); // Sub-region to convolve 879 880 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 881 convolveRegion(convImage1, convWeight1, &kernelImage, &kernelWeight, image1, weight1, 882 subMask, maskSource, kernels, polyValues, background, subRegion, useFFT, 883 false); 987 988 psRegion *subRegion = psRegionAlloc(i, xSubMax, j, ySubMax); // Bounds of subtraction 989 if (threaded) { 990 psThreadJob *job = psThreadJobAlloc("PSMODULES_SUBTRACTION_CONVOLVE"); 991 psArray *args = job->args; 992 PS_ARRAY_ADD_SCALAR(args, numCols, PS_TYPE_S32); 993 PS_ARRAY_ADD_SCALAR(args, numRows, PS_TYPE_S32); 994 PS_ARRAY_ADD_SCALAR(args, x0, PS_TYPE_S32); 995 PS_ARRAY_ADD_SCALAR(args, y0, PS_TYPE_S32); 996 psArrayAdd(args, 1, out1); 997 psArrayAdd(args, 1, out2); 998 psArrayAdd(args, 1, convMask); 999 psArrayAdd(args, 1, (pmReadout*)ro1); // Casting away const 1000 psArrayAdd(args, 1, (pmReadout*)ro2); // Casting away const 1001 psArrayAdd(args, 1, (psImage*)subMask); // Casting away const 1002 PS_ARRAY_ADD_SCALAR(args, blank, PS_TYPE_U8); 1003 PS_ARRAY_ADD_SCALAR(args, maskSource, PS_TYPE_U8); 1004 PS_ARRAY_ADD_SCALAR(args, maskTarget, PS_TYPE_U8); 1005 psArrayAdd(args, 1, subRegion); 1006 psArrayAdd(args, 1, (pmSubtractionKernels*)kernels); // Casting away const 1007 PS_ARRAY_ADD_SCALAR(args, doBG, PS_TYPE_U8); 1008 PS_ARRAY_ADD_SCALAR(args, useFFT, PS_TYPE_U8); 1009 1010 if (!psThreadJobAddPending(job)) { 1011 psFree(job); 1012 return false; 1013 } 1014 psFree(job); 1015 } else { 1016 subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, subMask, 1017 blank, maskSource, maskTarget, subRegion, kernels, doBG, useFFT); 884 1018 } 885 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 886 convolveRegion(convImage2, convWeight2, &kernelImage, &kernelWeight, image2, weight2, 887 subMask, maskSource, kernels, polyValues, background, subRegion, useFFT, 888 kernels->mode == PM_SUBTRACTION_MODE_DUAL); 889 } 890 891 // Propagate the mask 892 if (subMask) { 893 for (int y = j; y < ySubMax; y++) { 894 for (int x = i; x < xSubMax; x++) { 895 if (subMask->data.PS_TYPE_MASK_DATA[y][x] & maskTarget) { 896 convMask->data.PS_TYPE_MASK_DATA[y][x] |= blank; 897 } 898 } 899 } 900 } 901 } 902 } 903 psFree(kernelImage); 904 psFree(kernelWeight); 905 psFree(polyValues); 1019 psFree(subRegion); 1020 } 1021 } 1022 1023 if (!psThreadPoolWait(true)) { 1024 psError(PS_ERR_UNKNOWN, false, "Error waiting for threads."); 1025 return false; 1026 } 906 1027 907 1028 // Copy anything that wasn't convolved
Note:
See TracChangeset
for help on using the changeset viewer.
