Changeset 14455 for trunk/psModules/src/imcombine/pmSubtraction.c
- Timestamp:
- Aug 9, 2007, 10:25:52 AM (19 years ago)
- File:
-
- 1 edited
-
trunk/psModules/src/imcombine/pmSubtraction.c (modified) (33 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imcombine/pmSubtraction.c
r14420 r14455 4 4 * @author GLG, MHPCC 5 5 * 6 * @version $Revision: 1.3 3$ $Name: not supported by cvs2svn $7 * @date $Date: 2007-08-0 7 19:02:55$6 * @version $Revision: 1.34 $ $Name: not supported by cvs2svn $ 7 * @date $Date: 2007-08-09 20:25:52 $ 8 8 * 9 9 * Copyright 2004-2007 Institute for Astronomy, University of Hawaii … … 30 30 // Private (file-static) functions 31 31 ////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 33 // Return the number of polynomial terms there are for a given order 34 static inline long polyTerms(int order // Order of polynomial 35 ) 36 { 37 return (order + 1) * (order + 2) / 2; 38 } 32 39 33 40 // Given a stamp coordinates (x,y), generate a matrix where the elements (i,j) are x^i * y^j … … 160 167 case PM_SUBTRACTION_KERNEL_ISIS: { \ 161 168 psKernel *preCalc = (KERNELS)->preCalc->data[i]; /* Precalculated values */ \ 162 psKernel *subKernel = (KERNELS)->preCalc->data[(KERNELS)->subIndex]; /* Kernel to subtract */ \163 169 for (int v = -size; v <= size; v++) { \ 164 170 for (int u = -size; u <= size; u++) { \ 165 171 (TARGET)->kernel[v][u] += value * FUNC(preCalc->kernel[v][u]); \ 166 /* Subtract (0,0) kernel from other kernels to preserve photometric scaling */ \ 167 if ((KERNELS)->spatialOrder > 0 && i != (KERNELS)->subIndex) { \ 168 (TARGET)->kernel[v][u] += subValue * FUNC(subKernel->kernel[v][u]); \ 169 } \ 172 /* Photometric scaling is already built in to the precalculated kernel */ \ 170 173 } \ 171 174 } \ … … 207 210 ) 208 211 { 209 int numKernels = solution->n - 1;// Number of kernel basis functions212 int numKernels = kernels->num; // Number of kernel basis functions 210 213 assert(kernels->u->n == numKernels); 211 214 assert(kernels->v->n == numKernels); 212 assert(kernels->xOrder->n == numKernels);213 assert( kernels->yOrder->n == numKernels);215 int spatialOrder = kernels->spatialOrder; // Maximum spatial polynomial order 216 assert(solution->n == numKernels * polyTerms(spatialOrder) + polyTerms(kernels->bgOrder)); 214 217 215 218 // Ensure the subIndex for POIS kernels is what is expected 216 219 assert((kernels->type != PM_SUBTRACTION_KERNEL_POIS && 217 220 kernels->type != PM_SUBTRACTION_KERNEL_SPAM && 218 kernels->type != PM_SUBTRACTION_KERNEL_FRIES ) ||219 (kernels->u->data.S32[kernels->subIndex] == 0 && kernels->v->data.S32[kernels->subIndex] == 0&&220 kernels-> xOrder->data.S32[kernels->subIndex] == 0 &&221 kernels->yOrder->data.S32[kernels->subIndex] == 0));221 kernels->type != PM_SUBTRACTION_KERNEL_FRIES && 222 kernels->type != PM_SUBTRACTION_KERNEL_GUNK && 223 kernels->type != PM_SUBTRACTION_KERNEL_RINGS) || 224 (kernels->u->data.S32[kernels->subIndex] == 0 && kernels->v->data.S32[kernels->subIndex] == 0)); 222 225 223 226 int size = kernels->size; // Kernel half-size … … 228 231 229 232 for (int i = 0; i < numKernels; i++) { 230 int xOrder = kernels->xOrder->data.S32[i]; // Polynomial order in x 231 int yOrder = kernels->yOrder->data.S32[i]; // Polynomial order in y 232 float value = weightFunc(polyValues->data.F64[yOrder][xOrder] * 233 solution->data.F64[i]); // Value to sum 234 float subValue = weightFunc(-solution->data.F64[i]); // Value to subtract (actually add, because of -) 233 double value = 0.0; // Value of kernel coefficient 234 for (int yOrder = 0, index = i; yOrder <= spatialOrder; yOrder++) { 235 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; xOrder++, index += numKernels) { 236 value += polyValues->data.F64[yOrder][xOrder] * solution->data.F64[index]; 237 } 238 } 239 235 240 switch (kernels->type) { 236 241 case PM_SUBTRACTION_KERNEL_POIS: { 237 242 int u = kernels->u->data.S32[i]; // Offset in x 238 243 int v = kernels->v->data.S32[i]; // Offset in y 239 kernel->kernel[v][u] += value;244 kernel->kernel[v][u] += weightFunc(value); 240 245 if (kernels->spatialOrder > 0 && i != kernels->subIndex) { 241 246 // The (0,0) element is subtracted from most kernels to preserve photometric scaling 242 kernel->kernel[0][0] += subValue;247 kernel->kernel[0][0] += weightFunc(- value); 243 248 } 244 249 break; … … 253 258 254 259 // Normalising sum of kernel component to unity 255 value /=weightFunc((uStop - uStart) * (vStop - vStart));260 float norm = 1.0 / weightFunc((uStop - uStart) * (vStop - vStart)); 256 261 257 262 for (int v = vStart; v <= vStop; v++) { 258 263 for (int u = uStart; u <= uStop; u++) { 259 kernel->kernel[v][u] += value; 264 kernel->kernel[v][u] += norm * weightFunc(value); 265 if (kernels->spatialOrder > 0 && i != kernels->subIndex) { 266 // The (0,0) element is subtracted from most kernels to preserve photometric scaling 267 kernel->kernel[0][0] += weightFunc(- value); 268 } 260 269 } 261 }262 if (kernels->spatialOrder > 0 && i != kernels->subIndex) {263 /* The (0,0) element is subtracted from most kernels to preserve photometric scaling */264 kernel->kernel[0][0] += subValue;265 270 } 266 271 break; … … 270 275 // Using pre-calculated function 271 276 psKernel *preCalc = kernels->preCalc->data[i]; // Precalculated values 277 // Iterating over the kernel 272 278 for (int v = -size; v <= size; v++) { 273 279 for (int u = -size; u <= size; u++) { 274 kernel->kernel[v][u] += value * weightFunc(preCalc->kernel[v][u]); 280 kernel->kernel[v][u] += weightFunc(preCalc->kernel[v][u] * value); 281 // Photometric scaling is built into the preCalc kernel --- no subtraction! 275 282 } 276 283 } 277 284 } else { 278 285 // Using delta function 286 bool subtract = (kernels->spatialOrder > 0 && i != kernels->subIndex); // Subtract (0,0)? 279 287 int u = kernels->u->data.S32[i]; // Offset in x 280 288 int v = kernels->v->data.S32[i]; // Offset in y 281 kernel->kernel[v][u] += value; 282 } 283 // The (0,0) kernel is subtracted from other kernels to preserve photometric scaling 284 if (kernels->spatialOrder > 0 && i != kernels->subIndex) { 285 kernel->kernel[0][0] += subValue; 286 } 287 break; 288 } 289 case PM_SUBTRACTION_KERNEL_ISIS: { 290 psKernel *preCalc = kernels->preCalc->data[i];// Precalculated values 291 psKernel *subKernel = kernels->preCalc->data[kernels->subIndex]; // Kernel to subtract 292 for (int v = -size; v <= size; v++) { 293 for (int u = -size; u <= size; u++) { 294 kernel->kernel[v][u] += value * weightFunc(preCalc->kernel[v][u]); 295 // The (0,0) kernel is subtracted from other kernels to preserve photometric scaling 296 if (kernels->spatialOrder > 0 && i != kernels->subIndex) { 297 kernel->kernel[v][u] += subValue * weightFunc(subKernel->kernel[v][u]); 298 } 289 kernel->kernel[v][u] += weightFunc(value); 290 if (subtract) { 291 // The (0,0) element is subtracted from most kernels to preserve photometric scaling 292 kernel->kernel[0][0] += weightFunc(- value); 299 293 } 300 294 } 301 295 break; 302 296 } 297 case PM_SUBTRACTION_KERNEL_ISIS: { 298 psKernel *preCalc = kernels->preCalc->data[i]; // Precalculated values 299 // Iterating over the kernel 300 for (int v = -size; v <= size; v++) { 301 for (int u = -size; u <= size; u++) { 302 kernel->kernel[v][u] += weightFunc(preCalc->kernel[v][u] * value); 303 // Photometric scaling is built into the preCalc kernel --- no subtraction! 304 } 305 } 306 break; 307 } 303 308 case PM_SUBTRACTION_KERNEL_RINGS: { 304 309 if (i == kernels->subIndex) { 305 kernel->kernel[0][0] += value;310 kernel->kernel[0][0] += weightFunc(value); 306 311 break; 307 312 } … … 311 316 psVector *poly = preCalc->data[2]; // Polynomial values 312 317 int num = uCoords->n; // Number of pixels 313 value /= weightFunc(num); // Normalising sum of kernel component to unity 318 314 319 for (int j = 0; j < num; j++) { 315 320 int u = uCoords->data.S32[j], v = vCoords->data.S32[j]; // Kernel coordinates 316 kernel->kernel[v][u] += value * weightFunc(poly->data.F32[j]);321 kernel->kernel[v][u] += weightFunc(value * poly->data.F32[j]); 317 322 } 318 319 // The (0,0) kernel is subtracted from other kernels to preserve photometric scaling 320 if (kernels->spatialOrder > 0) { 321 kernel->kernel[0][0] += subValue; 322 } 323 kernel->kernel[0][0] += weightFunc(- value * num); 323 324 break; 324 325 } … … 336 337 int index, // Kernel basis function index 337 338 int x, int y, // Pixel around which to convolve 338 const psImage *image, // Image to convolve 339 const psImage *polyValues // Spatial polynomial values 339 const psImage *image // Image to convolve 340 340 ) 341 341 { 342 int xOrder = kernels->xOrder->data.S32[index]; // Polynomial order in x343 int yOrder = kernels->yOrder->data.S32[index]; // Polynomial order in y344 double polyValue = polyValues->data.F64[yOrder][xOrder]; // Value of spatial polynomial345 346 342 switch (kernels->type) { 347 343 case PM_SUBTRACTION_KERNEL_POIS: { … … 349 345 int u = kernels->u->data.S32[index]; // Offset in x 350 346 int v = kernels->v->data.S32[index]; // Offset in y 351 double value = polyValue *image->data.F32[y + v][x + u]; // Value of convolution347 float value = image->data.F32[y + v][x + u]; // Value of convolution 352 348 if (kernels->spatialOrder > 0 && index != kernels->subIndex) { 353 349 // The (0,0) element is subtracted from most kernels to preserve photometric scaling … … 366 362 for (int v = vStart; v <= vStop; v++) { 367 363 for (int u = uStart; u <= uStop; u++) { 368 sum += polyValue *image->data.F32[y + v][x + u];364 sum += image->data.F32[y + v][x + u]; 369 365 } 370 366 } … … 377 373 } 378 374 case PM_SUBTRACTION_KERNEL_GUNK: { 379 double value; // The value to return380 375 if (index < kernels->inner) { 381 376 // Using pre-calculated function … … 388 383 } 389 384 } 390 value = polyValue * sum; 391 } else { 392 // Using delta function 393 int u = kernels->u->data.S32[index]; // Offset in x 394 int v = kernels->v->data.S32[index]; // Offset in y 395 value = polyValue * image->data.F32[y + v][x + u]; // Value of convolution 396 } 385 return sum; 386 } 387 // Using delta function 388 int u = kernels->u->data.S32[index]; // Offset in x 389 int v = kernels->v->data.S32[index]; // Offset in y 390 float value = image->data.F32[y + v][x + u]; // Value of convolution 397 391 // The (0,0) delta function is subtracted from most kernels to preserve photometric scaling 398 392 if (kernels->spatialOrder > 0 && index != kernels->subIndex) { … … 403 397 case PM_SUBTRACTION_KERNEL_ISIS: { 404 398 psKernel *kernel = kernels->preCalc->data[index]; // The convolution kernel 405 psKernel *subKernel = kernels->preCalc->data[kernels->subIndex]; // Kernel to subtract406 399 int size = kernels->size; // Kernel half-size 407 400 double sum = 0.0; // Accumulated sum from convolution 408 double sub = 0.0; // Accumulated sum to subtract409 401 for (int v = -size; v <= size; v++) { 410 402 for (int u = -size; u <= size; u++) { 411 403 sum += kernel->kernel[v][u] * image->data.F32[y + v][x + u]; 412 // The (0,0) kernel is subtracted from other kernels to preserve photometric scaling 413 if (kernels->spatialOrder > 0 && index != kernels->subIndex) { 414 sub += subKernel->kernel[v][u] * image->data.F32[y + v][x + u]; 415 } 404 // Photometric scaling is already built in to the precalculated kernel 416 405 } 417 406 } 418 return polyValue * sum - sub;407 return sum; 419 408 } 420 409 case PM_SUBTRACTION_KERNEL_RINGS: { 421 410 if (index == kernels->subIndex) { 422 return image->data.F32[ 0][0];411 return image->data.F32[y][x]; 423 412 } 424 413 psArray *preCalc = kernels->preCalc->data[index]; // Precalculated data … … 432 421 sum += image->data.F32[y + v][x + u] * poly->data.F32[j]; 433 422 } 434 sum /= (double)num; // Normalising sum of kernel component to unity435 423 // The (0,0) kernel is subtracted from other kernels to preserve photometric scaling 436 return polyValue * sum - image->data.F32[0][0];424 return sum - num * image->data.F32[y][x]; 437 425 } 438 426 default: … … 592 580 PS_ASSERT_PTR_NON_NULL(kernels, false); 593 581 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, false); 594 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->xOrder, false);595 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->yOrder, false);596 582 if (weight) { 597 583 PS_ASSERT_IMAGE_NON_NULL(weight, false); … … 599 585 PS_ASSERT_IMAGE_TYPE(weight, PS_TYPE_F32, false); 600 586 } 601 if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) {602 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->preCalc, false);603 }604 587 PS_ASSERT_INT_NONNEGATIVE(footprint, false); 605 588 … … 609 592 610 593 int spatialOrder = kernels->spatialOrder; // Maximum order of spatial variation 611 int numKernels = kernels->u->n; // Number of kernel basis functions 612 int numParams = numKernels + 1; // Total number of parameters to solve for: coefficient of each kernel 613 // basis function, and a constant background offset. 614 int bgIndex = numKernels; // Index in matrix for the background 615 psVector *convolutions = psVectorAlloc(numKernels, PS_TYPE_F64); // Convolutions for each kernel 594 int numKernels = kernels->num; // Number of kernel basis functions 595 int numSpatial = polyTerms(spatialOrder); // Number of spatial variations 596 int numBackground = polyTerms(kernels->bgOrder); // Number of background terms 597 598 // Total number of parameters to solve for: coefficient of each kernel basis function, multipled by the 599 // number of coefficients for the spatial polynomial, and a constant background offset. 600 int numParams = numKernels * numSpatial + numBackground; 601 int bgIndex = numParams - numBackground; // Index in matrix for the background 602 psVector *convolutions = psVectorAlloc(numKernels * numSpatial, PS_TYPE_F64); // Convolutions 616 603 617 604 // We iterate over each stamp, allocate the matrix and vectors if … … 637 624 psVectorInit(stampVector, 0.0); 638 625 639 // Pre-evaluated spatial polynomial values 640 psImage *polyValues = spatialPolyValues(spatialOrder, 641 2.0 * (float)(stamp->x - numCols/2.0) / (float)numCols, 642 2.0 * (float)(stamp->y - numRows/2.0) / (float)numRows); 626 float xNorm = 2.0 * (float)(stamp->x - numCols/2.0) / (float)numCols; // Normalised x coord 627 float yNorm = 2.0 * (float)(stamp->y - numRows/2.0) / (float)numRows; // Normalised y coord 628 psImage *polyValues = spatialPolyValues(spatialOrder, xNorm, yNorm); // Spatial polynomial terms 643 629 644 630 for (int y = stamp->y - footprint; y <= stamp->y + footprint; y++) { … … 648 634 649 635 // Generate the convolutions 650 for (int i = 0; i < numKernels; i++) { 651 convolutions->data.F64[i] = convolvePixel(kernels, i, x, y, reference, polyValues); 636 for (int j = 0; j < numKernels; j++) { 637 double value = convolvePixel(kernels, j, x, y, reference); // Value from convolution 638 // Generate the pseudo-convolutions from the spatial polynomial terms 639 for (int yOrder = 0, index = j; yOrder <= spatialOrder; yOrder++) { 640 for (int xOrder = 0; xOrder <= spatialOrder - yOrder; 641 xOrder++, index += numKernels) { 642 convolutions->data.F64[index] = value * polyValues->data.F64[yOrder][xOrder]; 643 } 644 } 652 645 } 653 646 654 647 // Generate the least-squares matrix and vector 655 648 // Upper diagonal only 656 for (int i = 0; i < numKernels; i++) {657 for (int j = i; j < numKernels; j++) {649 for (int i = 0; i < bgIndex; i++) { 650 for (int j = i; j < bgIndex; j++) { 658 651 stampMatrix->data.F64[i][j] += convolutions->data.F64[i] * 659 652 convolutions->data.F64[j] * invNoise2; … … 674 667 // Fill in lower diagonal of symmetric matrix, while checking for bad values 675 668 bool bad = false; // Are there bad values? 676 for (int i = 0; i < numKernels; i++) {669 for (int i = 0; i < bgIndex; i++) { 677 670 for (int j = 0; j < i; j++) { 678 671 stampMatrix->data.F64[i][j] = stampMatrix->data.F64[j][i]; … … 694 687 if (bad) { 695 688 stamp->status = PM_SUBTRACTION_STAMP_REJECTED; 696 psTrace("psModules.imcombine", 3, "Rejecting stamp %d because of bad equation\n", i); 689 psTrace("psModules.imcombine", 3, "Rejecting stamp %d (%d,%d) because of bad equation\n", 690 i, stamp->x, stamp->y); 697 691 } else { 698 692 stamp->status = PM_SUBTRACTION_STAMP_USED; … … 807 801 PS_ASSERT_VECTOR_TYPE(solution, PS_TYPE_F64, -1); 808 802 PS_ASSERT_PTR_NON_NULL(kernels, -1); 809 PS_ASSERT_VECTOR_SIZE(kernels->u, solution->n - 1, -1); 803 PS_ASSERT_VECTOR_SIZE(solution, kernels->num * polyTerms(kernels->spatialOrder) + 804 polyTerms(kernels->bgOrder), -1); 805 PS_ASSERT_VECTOR_SIZE(kernels->u, kernels->num, -1); 810 806 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, -1); 811 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->xOrder, -1);812 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->yOrder, -1);813 if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) {814 PS_ASSERT_ARRAY_NON_EMPTY(kernels->preCalc, -1);815 PS_ASSERT_ARRAY_SIZE(kernels->preCalc, solution->n - 1, -1);816 }817 807 818 808 // Measure deviations … … 836 826 int xStamp = stamp->x, yStamp = stamp->y; // Coordinates of stamp 837 827 838 // Precalulate polynomial values 839 psImage *polyValues = spatialPolyValues(kernels->spatialOrder, 840 2.0 * (float)(stamp->x - numCols/2.0) / (float)numCols, 841 2.0 * (float)(stamp->y - numRows/2.0) / (float)numRows); 828 float xNorm = 2.0 * (float)(stamp->x - numCols/2.0) / (float)numCols; // Normalised x coord 829 float yNorm = 2.0 * (float)(stamp->y - numRows/2.0) / (float)numRows; // Normalised y coord 830 psImage *polyValues = spatialPolyValues(kernels->spatialOrder, xNorm, yNorm); // Polynomial terms 842 831 843 832 #ifdef USE_FUNCTIONS_INSTEAD_OF_MACROS … … 878 867 } 879 868 deviations->data.F32[i] = sqrt(stats->sampleMean / 2.0); 880 psTrace("psModules.imcombine", 1, "Deviation for stamp %d: %f\n", i, deviations->data.F32[i]); 869 psTrace("psModules.imcombine", 1, "Deviation for stamp %d (%d,%d): %f\n", 870 i, stamp->x, stamp->y, deviations->data.F32[i]); 881 871 totalSquareDev += PS_SQR(deviations->data.F32[i]); 882 872 numStamps++; … … 896 886 if (stamp->status == PM_SUBTRACTION_STAMP_USED && deviations->data.F32[i] > limit) { 897 887 // Mask out the stamp in the image so you it's not found again 898 psTrace("psModules.imcombine", 3, "Rejecting stamp %d \n", i);888 psTrace("psModules.imcombine", 3, "Rejecting stamp %d (%d,%d)\n", i, stamp->x, stamp->y); 899 889 numRejected++; 900 890 for (int y = stamp->y - footprint; y <= stamp->y + footprint; y++) { … … 922 912 PS_ASSERT_VECTOR_NON_NULL(solution, NULL); 923 913 PS_ASSERT_PTR_NON_NULL(kernels, NULL); 914 PS_ASSERT_VECTOR_SIZE(solution, kernels->num * polyTerms(kernels->spatialOrder) + 915 polyTerms(kernels->bgOrder), NULL); 924 916 PS_ASSERT_FLOAT_WITHIN_RANGE(x, -1.0, 1.0, NULL); 925 917 PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL); 926 PS_ASSERT_VECTOR_SIZE(kernels->u, solution->n - 1, false);918 PS_ASSERT_VECTOR_SIZE(kernels->u, kernels->num, false); 927 919 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, NULL); 928 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->xOrder, NULL);929 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->yOrder, NULL);930 if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) {931 PS_ASSERT_ARRAY_NON_NULL(kernels->preCalc, NULL);932 PS_ASSERT_ARRAY_SIZE(kernels->preCalc, solution->n - 1, NULL);933 }934 920 935 921 // Precalulate polynomial values … … 958 944 PS_ASSERT_VECTOR_NON_NULL(solution, NULL); 959 945 PS_ASSERT_PTR_NON_NULL(kernels, NULL); 946 PS_ASSERT_VECTOR_SIZE(solution, kernels->num * polyTerms(kernels->spatialOrder) + 947 polyTerms(kernels->bgOrder), NULL); 960 948 PS_ASSERT_FLOAT_WITHIN_RANGE(x, -1.0, 1.0, NULL); 961 949 PS_ASSERT_FLOAT_WITHIN_RANGE(y, -1.0, 1.0, NULL); 962 PS_ASSERT_VECTOR_SIZE(kernels->u, solution->n - 1, false);950 PS_ASSERT_VECTOR_SIZE(kernels->u, kernels->num, false); 963 951 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, NULL); 964 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->xOrder, NULL);965 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->yOrder, NULL);966 if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) {967 PS_ASSERT_ARRAY_NON_NULL(kernels->preCalc, NULL);968 PS_ASSERT_ARRAY_SIZE(kernels->preCalc, solution->n - 1, NULL);969 }970 952 971 953 psArray *images = psArrayAlloc(solution->n - 1); // Images of each kernel to return … … 987 969 bool pmSubtractionConvolve(psImage **outImage, psImage **outWeight, psImage **outMask, 988 970 const psImage *inImage, const psImage *inWeight, const psImage *subMask, 989 psMaskType blank, const psVector *solution, const pmSubtractionKernels *kernels) 971 psMaskType blank, const psRegion *region, const psVector *solution, 972 const pmSubtractionKernels *kernels) 990 973 { 991 974 PS_ASSERT_IMAGE_NON_NULL(inImage, false); … … 1022 1005 PS_ASSERT_VECTOR_TYPE(solution, PS_TYPE_F64, false); 1023 1006 PS_ASSERT_PTR_NON_NULL(kernels, false); 1024 PS_ASSERT_VECTOR_SIZE(kernels->u, solution->n - 1, false); 1007 PS_ASSERT_VECTOR_SIZE(solution, kernels->num * polyTerms(kernels->spatialOrder) + 1008 polyTerms(kernels->bgOrder), -1); 1009 PS_ASSERT_VECTOR_SIZE(kernels->u, kernels->num, false); 1025 1010 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, false); 1026 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->xOrder, false); 1027 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->yOrder, false); 1028 if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) { 1029 PS_ASSERT_ARRAY_NON_NULL(kernels->preCalc, false); 1030 PS_ASSERT_ARRAY_SIZE(kernels->preCalc, solution->n - 1, false); 1031 } 1032 1033 int size = kernels->size; // Half-size of kernel 1011 if (region) { 1012 if (psRegionIsNaN(*region)) { 1013 psString string = psRegionToString(*region); 1014 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Input region (%s) contains NAN values", string); 1015 psFree(string); 1016 return false; 1017 } 1018 if (region->x0 < 0 || region->x1 > inImage->numCols || 1019 region->y0 < 0 || region->y1 > inImage->numRows) { 1020 psString string = psRegionToString(*region); 1021 psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Input region (%s) does not fit in image (%dx%d)", 1022 string, inImage->numCols, inImage->numRows); 1023 psFree(string); 1024 return false; 1025 } 1026 } 1027 1034 1028 float background = solution->data.F64[solution->n-1]; // The difference in background 1035 1029 int numCols = inImage->numCols, numRows = inImage->numRows; // Image dimensions … … 1057 1051 } 1058 1052 1053 int size = kernels->size; // Half-size of kernel 1054 int fullSize = 2 * size + 1; // Full size of kernel 1059 1055 psImage *polyValues = NULL; // Pre-calculated polynomial values 1060 int fullSize = 2 * size + 1; // Full size of kernel1061 1056 1062 1057 psKernel *kernelImage = NULL; // Kernel for the image 1063 1058 psKernel *kernelWeight = NULL; // Kernel for the weight map 1064 1059 1065 for (int j = size; j < inImage->numRows - size; j += fullSize) { 1066 for (int i = size; i < inImage->numCols - size; i += fullSize) { 1060 // Get region for convolution: [xMin:xMax,yMin:yMax] 1061 int xMin = size, xMax = numCols - size; 1062 int yMin = size, yMax = numRows - size; 1063 if (region) { 1064 xMin = PS_MAX(region->x0, xMin); 1065 xMax = PS_MIN(region->x1, xMax); 1066 yMin = PS_MAX(region->y0, yMin); 1067 yMax = PS_MIN(region->y1, yMax); 1068 } 1069 1070 for (int j = yMin; j < yMax; j += fullSize) { 1071 for (int i = xMin; i < xMax; i += fullSize) { 1067 1072 1068 1073 // Only generate polynomial values every kernel footprint, since we have already assumed … … 1085 1090 #endif 1086 1091 1087 for (int y = j; y < PS_MIN(j + fullSize, numRows - size); y++) {1088 for (int x = i; x < PS_MIN(i + fullSize, numCols - size); x++) {1092 for (int y = j; y < PS_MIN(j + fullSize, yMax); y++) { 1093 for (int x = i; x < PS_MIN(i + fullSize, xMax); x++) { 1089 1094 // Check and propagate the kernel footprint, if required 1090 1095 if (subMask && (subMask->data.PS_TYPE_MASK_DATA[y][x] & … … 1123 1128 psFree(polyValues); 1124 1129 1125 // Mark the non-convolved part as blank 1126 for (int y = size; y < inImage->numRows - size; y++) { 1130 return true; 1131 } 1132 1133 bool pmSubtractionBorder(psImage *image, psImage *weight, psImage *mask, 1134 const pmSubtractionKernels *kernels, psMaskType blank) 1135 { 1136 PS_ASSERT_IMAGE_NON_NULL(image, false); 1137 PS_ASSERT_IMAGE_TYPE(image, PS_TYPE_F32, false); 1138 if (mask) { 1139 PS_ASSERT_IMAGE_NON_NULL(mask, false); 1140 PS_ASSERT_IMAGES_SIZE_EQUAL(mask, image, false); 1141 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, false); 1142 } 1143 if (weight) { 1144 PS_ASSERT_IMAGE_NON_NULL(weight, false); 1145 PS_ASSERT_IMAGES_SIZE_EQUAL(weight, image, false); 1146 PS_ASSERT_IMAGE_TYPE(weight, PS_TYPE_F32, false); 1147 } 1148 1149 int numCols = image->numCols, numRows = image->numRows; // Image dimensions 1150 1151 int size = kernels->size; // Half-size of kernel 1152 for (int y = size; y < numRows - size; y++) { 1127 1153 for (int x = 0; x < size; x++) { 1128 markBlank( convImage, convMask, convWeight, x, y, blank);1154 markBlank(image, mask, weight, x, y, blank); 1129 1155 } 1130 1156 for (int x = numCols - size; x < numCols; x++) { 1131 markBlank( convImage, convMask, convWeight, x, y, blank);1157 markBlank(image, mask, weight, x, y, blank); 1132 1158 } 1133 1159 } 1134 1160 for (int y = 0; y < size; y++) { 1135 1161 for (int x = 0; x < numCols; x++) { 1136 markBlank( convImage, convMask, convWeight, x, y, blank);1162 markBlank(image, mask, weight, x, y, blank); 1137 1163 } 1138 1164 } 1139 1165 for (int y = numRows - size; y < numRows; y++) { 1140 1166 for (int x = 0; x < numCols; x++) { 1141 markBlank( convImage, convMask, convWeight, x, y, blank);1167 markBlank(image, mask, weight, x, y, blank); 1142 1168 } 1143 1169 }
Note:
See TracChangeset
for help on using the changeset viewer.
