Changeset 19164 for trunk/psModules/src/imcombine/pmSubtraction.c
- Timestamp:
- Aug 22, 2008, 12:45:36 PM (18 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/imcombine/pmSubtraction.c (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imcombine/pmSubtraction.c
r19148 r19164 249 249 psImage *subConv = psImageSubset(convolved, psRegionSet(size, -size, size, -size)); // Cut off the edges 250 250 251 if (threaded) { 252 psMutexLock(target); 253 } 254 psImage *subTarget = psImageSubset(target, region); // Target for this subregion 255 if (threaded) { 256 psMutexUnlock(target); 257 } 251 int xMin = region.x0, xMax = region.x1, yMin = region.y0, yMax = region.y1; // Bounds of region 258 252 if (background != 0.0) { 259 psBinaryOp(subTarget, subConv, "+", psScalarAlloc(background, PS_TYPE_F32)); 253 for (int yTarget = yMin, ySource = size; yTarget < yMax; yTarget++, ySource++) { 254 for (int xTarget = xMin, xSource = size; xTarget < xMax; xTarget++, xSource++) { 255 target->data.F32[yTarget][xTarget] = convolved->data.F32[ySource][xSource] + background; 256 } 257 } 260 258 } else { 261 int numBytes = subTarget->numCols* PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes to copy262 for (int y = 0; y < subTarget->numRows; y++) {263 memcpy( subTarget->data.F32[y], subConv->data.F32[y], numBytes);259 int numBytes = (xMax - xMin) * PSELEMTYPE_SIZEOF(PS_TYPE_F32); // Number of bytes to copy 260 for (int yTarget = yMin, ySource = size; yTarget < yMax; yTarget++, ySource++) { 261 memcpy(&target->data.F32[yTarget][xMin], &convolved->data.F32[ySource][size], numBytes); 264 262 } 265 263 } 266 264 psFree(subConv); 267 265 psFree(convolved); 268 if (threaded) {269 psMutexLock(target);270 }271 psFree(subTarget);272 if (threaded) {273 psMutexUnlock(target);274 }275 266 276 267 return; … … 291 282 for (int v = -size; v <= size; v++) { 292 283 for (int u = -size; u <= size; u++) { 293 target->data.F32[y][x] += kernel->kernel[v][u] * 294 image->data.F32[y - v][x - u]; 284 target->data.F32[y][x] += kernel->kernel[v][u] * image->data.F32[y - v][x - u]; 295 285 } 296 286 } … … 303 293 static inline void convolveRegion(psImage *convImage, // Convolved image (output) 304 294 psImage *convWeight, // Convolved weight map (output), or NULL 295 psImage *convMask, // Convolve mask (output), or NULL 305 296 psKernel **kernelImage, // Convolution kernel for the image 306 297 psKernel **kernelWeight, // Convolution kernel for the weight map, or NULL … … 308 299 psImage *weight, // Weight map to convolve, or NULL 309 300 psImage *subMask, // Subtraction mask 310 psMaskType maskVal, // Mask value to apply in convolution311 301 const pmSubtractionKernels *kernels, // Kernels 312 302 psImage *polyValues, // Polynomial values 313 303 float background, // Background value to apply 314 304 psRegion region, // Region to convolve 305 float poorFrac, // Fraction for "poor" 315 306 bool useFFT, // Use FFT to convolve? 316 307 bool wantDual // Want the dual convolution? … … 318 309 { 319 310 *kernelImage = solvedKernel(*kernelImage, kernels, polyValues, wantDual); 320 if (weight ) {311 if (weight || subMask) { 321 312 *kernelWeight = varianceKernel(*kernelWeight, *kernelImage); 322 313 } 323 314 315 psMaskType maskSource; // Mask these values when 316 psMaskType maskTarget; // Set this mask value when convolving 317 if (kernels->mode == PM_SUBTRACTION_MODE_1 || (kernels->mode == PM_SUBTRACTION_MODE_DUAL && !wantDual)) { 318 maskSource = PM_SUBTRACTION_MASK_BAD_1; 319 maskTarget = PM_SUBTRACTION_MASK_CONVOLVE_BAD_1; 320 } else { 321 maskSource = PM_SUBTRACTION_MASK_BAD_2; 322 maskTarget = PM_SUBTRACTION_MASK_CONVOLVE_BAD_2; 323 } 324 325 // Convolve the image and weight 324 326 if (useFFT) { 325 327 // Use Fast Fourier Transform to do the convolution 326 328 // This provides a big speed-up for large kernels 327 328 convolveFFT(convImage, image, subMask, maskVal, *kernelImage, region, background, kernels->size); 329 convolveFFT(convImage, image, subMask, maskSource, *kernelImage, region, background, kernels->size); 329 330 if (weight) { 330 convolveFFT(convWeight, weight, subMask, mask Val, *kernelWeight, region, 0.0, kernels->size);331 convolveFFT(convWeight, weight, subMask, maskSource, *kernelWeight, region, 0.0, kernels->size); 331 332 } 332 333 } else { … … 334 335 if (weight) { 335 336 convolveDirect(convWeight, weight, *kernelWeight, region, 0.0, kernels->size); 337 } 338 } 339 340 // Convolve the mask for bad pixels 341 if (subMask && convMask) { 342 psKernel *kernel = *kernelWeight; // Kernel of interest 343 int xMin = kernel->xMin, xMax = kernel->xMax, yMin = kernel->yMin, yMax = kernel->yMax; // Bounds 344 345 // Determine the thresholds 346 double sumKernel2 = 0.0; // Sum of the kernel-squared 347 for (int y = yMin; y <= yMax; y++) { 348 for (int x = xMin; x <= xMax; x++) { 349 sumKernel2 += kernel->kernel[y][x]; 350 } 351 } 352 float threshold = sumKernel2 * poorFrac; // Threshold between poor and bad 353 354 // Get bounds of threshold region 355 // Start with the entire kernel, and keep reducing the size of the box until it drops below threshold 356 int box = kernels->size; // Size of box with bad pixels 357 for (double sumBox = sumKernel2; box > 0; box--) { 358 for (int x = -box; x <= box; x++) { 359 sumBox -= kernel->kernel[-box][x] + kernel->kernel[box][x]; 360 } 361 for (int y = -box + 1; y <= box - 1; y++) { 362 // Note: not doing corners 363 sumBox -= kernel->kernel[y][-box] + kernel->kernel[y][box]; 364 } 365 if (sumBox < threshold) { 366 break; 367 } 368 } 369 370 if (box > 0) { 371 bool threaded = pmSubtractionThreaded(); // Are we running threaded? 372 if (threaded) { 373 psMutexLock(subMask); 374 } 375 psImage *image = psImageSubset(subMask, psRegionSet(region.x0 + xMin, region.x1 + xMax, 376 region.y0 + yMin, region.y1 + yMax)); 377 if (threaded) { 378 psMutexUnlock(subMask); 379 } 380 381 psImage *convolved = psImageConvolveMask(NULL, image, maskSource, maskTarget, 382 -box, box, -box, box); // Convolved subtraction mask 383 384 if (threaded) { 385 psMutexLock(subMask); 386 } 387 psFree(image); 388 if (threaded) { 389 psMutexUnlock(subMask); 390 } 391 392 int colMin = region.x0, colMax = region.x1, rowMin = region.y0, rowMax = region.y1; // Bounds 393 int numBytes = (colMax - colMin) * PSELEMTYPE_SIZEOF(PS_TYPE_MASK); // Number of bytes to copy 394 395 // Since we're copying back into the source, we need to lock 396 if (threaded) { 397 psMutexLock(subMask); 398 } 399 for (int yTarget = rowMin, ySource = -yMin; yTarget < rowMax; yTarget++, ySource++) { 400 memcpy(&subMask->data.PS_TYPE_MASK_DATA[yTarget][colMin], 401 &convolved->data.PS_TYPE_MASK_DATA[ySource][-xMin], numBytes); 402 } 403 if (threaded) { 404 psMutexUnlock(subMask); 405 } 406 407 // No need to lock: we own this 408 psFree(convolved); 336 409 } 337 410 } … … 753 826 754 827 // XXX Put kernelImage, kernelWeight and polyValues on thread-dependent data 755 static bool subtractionConvolvePatch(int numCols, int numRows, int x0, int y0, 756 pmReadout *out1, pmReadout *out2, psImage *convMask, 757 const pmReadout *ro1, const pmReadout *ro2, psImage *subMask, 758 psMaskType blank, psMaskType maskSource, psMaskType maskTarget, 759 const psRegion *region, const pmSubtractionKernels *kernels, 760 bool doBG, bool useFFT) 828 static bool subtractionConvolvePatch(int numCols, int numRows, // Size of image 829 int x0, int y0, // Offsets for image 830 pmReadout *out1, pmReadout *out2, // Output readouts 831 psImage *convMask, // Output convolved mask 832 const pmReadout *ro1, const pmReadout *ro2, // Input readouts 833 psImage *subMask, // Input subtraction mask 834 psMaskType maskBad, // Mask value to give bad pixels 835 psMaskType maskPoor, // Mask value to give poor pixels 836 float poorFrac, // Fraction for "poor" 837 const psRegion *region, // Patch to convolve 838 const pmSubtractionKernels *kernels, // Kernels 839 bool doBG, // Add in background when convolving? 840 bool useFFT // Use FFT to do the convolution? 841 ) 761 842 { 762 843 int size = kernels->size; // Half-size of kernel … … 782 863 783 864 if (kernels->mode == PM_SUBTRACTION_MODE_1 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 784 convolveRegion(out1->image, out1->weight, &kernelImage, &kernelWeight, ro1->image, ro1->weight,785 subMask, maskSource, kernels, polyValues, background, *region, useFFT,786 false);865 convolveRegion(out1->image, out1->weight, convMask, &kernelImage, &kernelWeight, 866 ro1->image, ro1->weight, subMask, kernels, polyValues, background, 867 *region, poorFrac, useFFT, false); 787 868 } 788 869 if (kernels->mode == PM_SUBTRACTION_MODE_2 || kernels->mode == PM_SUBTRACTION_MODE_DUAL) { 789 convolveRegion(out2->image, out2->weight, &kernelImage, &kernelWeight, ro2->image, ro2->weight,790 subMask, maskSource, kernels, polyValues, background, *region, useFFT,791 kernels->mode == PM_SUBTRACTION_MODE_DUAL);870 convolveRegion(out2->image, out2->weight, convMask, &kernelImage, &kernelWeight, 871 ro2->image, ro2->weight, subMask, kernels, polyValues, background, 872 *region, poorFrac, useFFT, kernels->mode == PM_SUBTRACTION_MODE_DUAL); 792 873 } 793 874 … … 796 877 psFree(polyValues); 797 878 798 // Propagate the mask879 // Propagate the subtraction mask 799 880 if (subMask) { 800 881 psMaskType **target = convMask->data.PS_TYPE_MASK_DATA; // Target mask 801 882 psMaskType **source = subMask->data.PS_TYPE_MASK_DATA; // Source mask 802 883 884 psMaskType poor, bad; // Mask value for "poor" and "bad" pixels in subtraction mask 885 switch (kernels->mode) { 886 case PM_SUBTRACTION_MODE_1: 887 poor = PM_SUBTRACTION_MASK_CONVOLVE_1; 888 bad = PM_SUBTRACTION_MASK_CONVOLVE_BAD_1 | PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2; 889 break; 890 case PM_SUBTRACTION_MODE_2: 891 poor = PM_SUBTRACTION_MASK_CONVOLVE_2; 892 bad = PM_SUBTRACTION_MASK_CONVOLVE_BAD_2 | PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2; 893 break; 894 case PM_SUBTRACTION_MODE_DUAL: 895 poor = PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_CONVOLVE_1; 896 bad = PM_SUBTRACTION_MASK_CONVOLVE_BAD_1 | PM_SUBTRACTION_MASK_CONVOLVE_BAD_2 | 897 PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2; 898 break; 899 default: 900 psAbort("Unrecognised subtraction mode: %x", kernels->mode); 901 } 902 803 903 for (int y = yMin; y < yMax; y++) { 804 904 for (int x = xMin; x < xMax; x++) { 805 if (source[y][x] & maskTarget) { 806 target[y][x] |= blank; 905 // Pixels marked as "bad" shouldn't also be marked as "poor" 906 if (source[y][x] & bad) { 907 target[y][x] |= maskBad; 908 } else if (source[y][x] & poor){ 909 target[y][x] |= maskPoor; 807 910 } 808 911 } … … 848 951 const pmReadout *ro2 = args->data[8]; // Input readout 2 849 952 psImage *subMask = args->data[9]; // Subtraction mask 850 psMaskType blank = PS_SCALAR_VALUE(args->data[10], U8); // Output mask value851 psMaskType mask Source = PS_SCALAR_VALUE(args->data[11], U8); // Mask value corresponding to source image852 psMaskType maskTarget = PS_SCALAR_VALUE(args->data[12], U8); // Mask value corresponding to target image953 psMaskType maskBad = PS_SCALAR_VALUE(args->data[10], U8); // Output mask value for bad pixels 954 psMaskType maskPoor = PS_SCALAR_VALUE(args->data[11], U8); // Output mask value for poor pixels 955 float poorFrac = PS_SCALAR_VALUE(args->data[12], F32); // Fraction for "poor" 853 956 const psRegion *region = args->data[13]; // Region to convolve 854 957 const pmSubtractionKernels *kernels = args->data[14]; // Kernels … … 856 959 bool useFFT = PS_SCALAR_VALUE(args->data[16], U8); // Use FFT for convolution? 857 960 858 return subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, 859 ro1, ro2, subMask, blank, maskSource, maskTarget, 860 region, kernels, doBG, useFFT); 961 return subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, subMask, 962 maskBad, maskPoor, poorFrac, region, kernels, doBG, useFFT); 861 963 } 862 964 863 965 bool pmSubtractionConvolve(pmReadout *out1, pmReadout *out2, const pmReadout *ro1, const pmReadout *ro2, 864 psImage *subMask, psMaskType blank, const psRegion *region, 865 const pmSubtractionKernels *kernels, bool doBG, bool useFFT) 966 psImage *subMask, psMaskType maskBad, psMaskType maskPoor, float poorFrac, 967 const psRegion *region, const pmSubtractionKernels *kernels, 968 bool doBG, bool useFFT) 866 969 { 867 970 int numCols = 0, numRows = 0; // Image dimensions … … 998 1101 yMin = PS_MAX(region->y0, yMin); 999 1102 yMax = PS_MIN(region->y1, yMax); 1000 }1001 1002 psMaskType maskSource; // Mask these pixels when convolving1003 psMaskType maskTarget; // Mark these pixels as bad when propagating the subtractionMask1004 switch (kernels->mode) {1005 case PM_SUBTRACTION_MODE_1:1006 maskSource = PM_SUBTRACTION_MASK_BAD_1;1007 maskTarget = PM_SUBTRACTION_MASK_BAD_2 | PM_SUBTRACTION_MASK_CONVOLVE_1;1008 break;1009 case PM_SUBTRACTION_MODE_2:1010 maskSource = PM_SUBTRACTION_MASK_BAD_2;1011 maskTarget = PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_CONVOLVE_2;1012 break;1013 case PM_SUBTRACTION_MODE_DUAL:1014 maskSource = PM_SUBTRACTION_MASK_BAD_1 | PM_SUBTRACTION_MASK_BAD_2;1015 maskTarget = PM_SUBTRACTION_MASK_CONVOLVE_1 | PM_SUBTRACTION_MASK_CONVOLVE_2;1016 break;1017 default:1018 psAbort("Unsupported subtraction mode: %x", kernels->mode);1019 1103 } 1020 1104 … … 1045 1129 psArrayAdd(args, 1, (pmReadout*)ro2); // Casting away const 1046 1130 psArrayAdd(args, 1, (psImage*)subMask); // Casting away const 1047 PS_ARRAY_ADD_SCALAR(args, blank, PS_TYPE_U8);1048 PS_ARRAY_ADD_SCALAR(args, mask Source, PS_TYPE_U8);1049 PS_ARRAY_ADD_SCALAR(args, maskTarget, PS_TYPE_U8);1131 PS_ARRAY_ADD_SCALAR(args, maskBad, PS_TYPE_U8); 1132 PS_ARRAY_ADD_SCALAR(args, maskPoor, PS_TYPE_U8); 1133 PS_ARRAY_ADD_SCALAR(args, poorFrac, PS_TYPE_F32); 1050 1134 psArrayAdd(args, 1, subRegion); 1051 1135 psArrayAdd(args, 1, (pmSubtractionKernels*)kernels); // Casting away const … … 1060 1144 } else { 1061 1145 subtractionConvolvePatch(numCols, numRows, x0, y0, out1, out2, convMask, ro1, ro2, subMask, 1062 blank, maskSource, maskTarget, subRegion, kernels, doBG, useFFT);1146 maskBad, maskPoor, poorFrac, subRegion, kernels, doBG, useFFT); 1063 1147 } 1064 1148 psFree(subRegion);
Note:
See TracChangeset
for help on using the changeset viewer.
