Changeset 4417
- Timestamp:
- Jun 28, 2005, 1:23:55 PM (21 years ago)
- Location:
- trunk/psModules/src
- Files:
-
- 2 edited
-
pmImageSubtract.c (modified) (37 diffs)
-
pmImageSubtract.h (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/pmImageSubtract.c
r4322 r4417 1 1 /** @file ImageSubtract.c 2 * 3 * This file will ... 4 * 5 * @author Paul Price, IfA (original prototype) 6 * @author GLG, MHPCC 7 * 8 * @version $Revision: 1.10 $ $Name: not supported by cvs2svn $ 9 * @date $Date: 2005-06-20 23:21:05 $ 10 * 11 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 12 * 13 * XXX: sync with iFa on this: 14 * The (x, y) (row, col) issue is becoming a problem. In this file, and I 15 * think, the rest of psLib and psModules, the following conventions are used: 16 * 17 * 1) x will correspond to the column, and y will correspond to the row. 18 * 2) When used in function prototypes, the column (and hence x) appears 19 * first. 20 * 3) When used to index 2-D arrays, obviously, the row (and hence, y) 21 * appears first. (2 and 3 are the source of confusion). 22 * 4) When (u, v) are used in certain structures. 23 * u corresponds to x 24 * v corresponds to y 25 * 5) When element (a, b) is casually referred to in comments, or 26 * documentation it is unclear where a is the row, or the column. 27 * 6) A convention on loop index variables (i, j) would be convenient. 28 * Currently, sometimes i corresponds to the column (x), 29 * usually it corresponds to the row (y). 30 * 31 * XXX: The following variables are used an interpreted this way: 32 * kernelSize: Means that the actual kernel is a square (1 + 2 * kernelSize) per side. 33 * border: When accessing an image, a swath of pixels this wide is ignored. 34 * footprint: When accessing a stample, a square of pixels, footprint pixels per side, 35 * are looked at. We must ensure that (footprint+kernelSize) pixels exist 36 * around the center. 37 */ 2 * 3 * This file will contain code which creates a set of kernel basis 4 * functions, solves for their solution, and applies them to an image. 5 * 6 * @author Paul Price, IfA (original prototype) 7 * @author GLG, MHPCC 8 * 9 * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-06-28 23:23:55 $ 11 * 12 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii 13 * 14 * XXX: sync with IfA on this: 15 * The (x, y) (row, col) issue is becoming a problem. In this file, and I 16 * think, the rest of psLib and psModules, the following conventions are used: 17 * 18 * 1) x will correspond to the column, and y will correspond to the row. 19 * 2) When used in function prototypes, the column (and hence x) appears 20 * first. 21 * 3) When used to index 2-D arrays, obviously, the row (and hence, y) 22 * appears first. (2 and 3 are the source of confusion). 23 * 4) When (u, v) are used in certain structures. 24 * u corresponds to x 25 * v corresponds to y 26 * 5) When element (a, b) is casually referred to in comments, or 27 * documentation it is unclear where a is the row, or the column. 28 * 6) A convention on loop index variables (i, j) would be convenient. 29 * Currently, sometimes i corresponds to the column (x), 30 * usually it corresponds to the row (y). 31 * 32 * XXX: The following variables are used an interpreted this way: 33 * kernelSize: Means that the actual kernel is a square (1 + 2 * kernelSize) per side. 34 * border: When accessing an image, a swath of pixels this wide is ignored. 35 * footprint: When accessing a stample, a square of pixels, footprint pixels per side, 36 * are looked at. We must ensure that (footprint+kernelSize) pixels exist 37 * around the center. 38 */ 38 39 39 40 #include<stdio.h> … … 43 44 #include "pmImageSubtract.h" 44 45 45 // XXX: Put this is psConstants.h46 #define PS_ASSERT_INT_LESS_THAN(VAR1, VAR2, RVAL) \47 if (!(VAR1 < VAR2)) { \48 psError(PS_ERR_UNKNOWN, true, \49 "Error: %s is not less than %s (%d, %d)", #VAR1, #VAR2, VAR1, VAR2); \50 return(RVAL); \51 }52 53 46 /******************************************************************************* 54 47 Private alloc/free functions. 55 56 XXX: It's not clear if the SubtractionKernels alloc/free functions are doable. 48 XXX: It's not clear if the SubtractionKernels alloc/free functions are feasable. 57 49 ******************************************************************************/ 58 50 void p_pmStampFree(pmStamp *stamp) … … 90 82 } 91 83 92 psSubtractionKernels *p_pmSubtractionKernelsAlloc( psS32numBasisFunctions,84 psSubtractionKernels *p_pmSubtractionKernelsAlloc(int numBasisFunctions, 93 85 pmSubtractionKernelsType type) 94 86 { … … 106 98 int spatialOrder) 107 99 { 100 psTrace("ImageSubtract.pmSubtractionKernelsAllocPOIS", 1, 101 "Calling pmSubtractionKernelsAllocPOIS(%d, %d)\n", size, spatialOrder); 108 102 PS_ASSERT_INT_POSITIVE(size, NULL); 109 103 PS_ASSERT_INT_POSITIVE(spatialOrder, NULL); … … 152 146 153 147 // 154 // Iterate over (u,v). Generate a set of kernels for each (u, v).148 // Iterate over (u,v). Generate a set of kernels for each (u, v). 155 149 // 156 150 for (psS32 v = -yKernelHalfSize; v <= yKernelHalfSize; v++) { … … 176 170 } 177 171 172 psTrace("ImageSubtract.pmSubtractionKernelsAllocPOIS", 1, 173 "Exiting pmSubtractionKernelsAllocPOIS(%d, %d)\n", size, spatialOrder); 178 174 return(tmp); 179 175 } … … 181 177 /******************************************************************************* 182 178 XXX: Get the types correct (u, v, xOrder, yOrder). 183 184 XXX: For the various spatial orders, verify that the preCalc data does not185 vary with the (x^i * y^j) since that comes from the image coordinates when the186 kernel is convolved with it.187 179 188 180 XXX: Code review this. … … 193 185 int spatialOrder) 194 186 { 187 PS_ASSERT_VECTOR_NON_NULL(sigmas, NULL); 188 PS_ASSERT_VECTOR_NON_NULL(orders, NULL); 189 psTrace("ImageSubtract.pmSubtractionKernelsAllocISIS", 1, 190 "Calling pmSubtractionKernelsAllocISIS(%d, %d, %d, %d)\n", 191 sigmas->n, orders->n, size, spatialOrder); 195 192 PS_ASSERT_INT_POSITIVE(size, NULL); 196 193 PS_ASSERT_INT_POSITIVE(spatialOrder, NULL); 197 PS_ASSERT_VECTOR_NON_NULL(sigmas, NULL);198 194 PS_ASSERT_VECTOR_TYPE(sigmas, PS_TYPE_F32, NULL); 199 PS_ASSERT_VECTOR_NON_NULL(orders, NULL);200 195 PS_ASSERT_VECTOR_TYPE(orders, PS_TYPE_S32, NULL); 201 196 // 202 // Calculate the number of basis functions (nBF) , and others.197 // Calculate the number of basis functions (nBF). 203 198 // 204 199 psS32 numSigmas = sigmas->n; … … 283 278 (2.0 * PS_SQR(sigmas->data.F32[sigPtr])); 284 279 currPreCalc->data.F32[v+size][u+size] = 285 exp(exponent) * pow(uScaled, orderXTerm) * pow(vScaled, orderYTerm); 280 exp(-exponent) * 281 pow(uScaled, orderXTerm) * 282 pow(vScaled, orderYTerm); 286 283 } 287 284 } … … 298 295 } 299 296 297 psTrace("ImageSubtract.pmSubtractionKernelsAllocISIS", 1, 298 "Exiting pmSubtractionKernelsAllocISIS(%d, %d, %d, %d)\n", 299 sigmas->n, orders->n, size, spatialOrder); 300 300 return(tmp); 301 301 } … … 310 310 311 311 XXX: Do we need to care about case where yNum/xNum does not evenly divide the 312 nnumber of rows/columns in the mage?312 nnumber of rows/columns in the image? 313 313 ******************************************************************************/ 314 314 psArray *pmSubtractionFindStamps(psArray *stamps, ///< Output stamps, or NULL … … 322 322 ) 323 323 { 324 psTrace("ImageSubtract.pmSubtractionFindStamps", 1, 325 "Calling pmSubtractionFindStamps(%d, %f, %d, %d, %d)\n", 326 maskVal, threshold, xNum, yNum, border); 324 327 PS_ASSERT_IMAGE_NON_NULL(image, NULL); 325 328 PS_ASSERT_IMAGE_NON_EMPTY(image, NULL); … … 360 363 // 361 364 // XXX: Must handle cases where image size is not an even multiple of xNum or yNum 365 // they are currently ignored. 362 366 // 363 367 psS32 num = 0; … … 440 444 } 441 445 } 446 psTrace("ImageSubtract.pmSubtractionFindStamps", 1, 447 "Exiting pmSubtractionFindStamps(%d, %f, %d, %d, %d)\n", 448 maskVal, threshold, xNum, yNum, border); 442 449 return(stamps); 443 450 } … … 455 462 psF32 y) 456 463 { 464 psTrace("ImageSubtract.GenSpatialOrder", 5, 465 "Calling GenSpatialOrder(%d, %f, %f)\n", spatialOrder, x, y); 466 457 467 psImage *polyValues = psImageAlloc(spatialOrder+1, spatialOrder+1, PS_TYPE_F64); 458 468 … … 468 478 } 469 479 480 psTrace("ImageSubtract.GenSpatialOrder", 5, 481 "Exiting GenSpatialOrder(%d, %f, %f)\n", spatialOrder, x, y); 482 470 483 return(polyValues); 471 484 } … … 473 486 474 487 /******************************************************************************* 475 GeneralKernelConvolve(input, kernels, kernelID, col, row): This routine488 IsisKernelConvolve(input, kernels, kernelID, col, row): This routine 476 489 convolves a single kernel basis function with a pixel in an image. 477 478 XXX: merge this code with the other convolution code in this file. 479 480 XXX: Must we ensure that the pixels being accessed are inside the image? Is 481 there any garantee that the kernelSize, footprint stuff will be set correctly 482 to ensure no seg faults. 483 ******************************************************************************/ 484 static psF32 GeneralKernelConvolve(const psImage *input, 485 const psSubtractionKernels *kernels, 486 psS32 kernelID, 487 psS32 col, 488 psS32 row) 489 { 490 ******************************************************************************/ 491 static psF32 IsisKernelConvolve(const psImage *input, 492 const psSubtractionKernels *kernels, 493 psS32 kernelID, 494 psS32 col, 495 psS32 row) 496 { 497 498 499 psTrace("ImageSubtract.IsisKernelConvolve", 5, 500 "Calling IsisKernelConvolve(%d, %d, %d)\n", kernelID, col, row); 490 501 psS32 spatialOrder = kernels->p_spatialOrder; 491 502 psS32 kernelSize = kernels->p_size; … … 496 507 psF32 imageX = (((psF32) col) - numColsHalf) / numColsHalf; // Normalised position 497 508 psF32 imageY = (((psF32) row) - numRowsHalf) / numRowsHalf; // Normalised position 509 498 510 psImage *polyValues = GenSpatialOrder(spatialOrder, imageX, imageY); 499 psF32 polyVal = polyValues->data.F32[yOrder][xOrder]; 511 512 psF64 polyVal = polyValues->data.F64[yOrder][xOrder]; 500 513 501 514 psImage *preCalc = (psImage *) kernels->preCalc->data[kernelID]; 515 516 // XXX: Are the following asserts really necessary? 517 PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(row-kernelSize, 0, NAN); 518 PS_ASSERT_INT_LESS_THAN(row+kernelSize, input->numRows, NAN); 519 PS_ASSERT_INT_LARGER_THAN_OR_EQUAL(col-kernelSize, 0, NAN); 520 PS_ASSERT_INT_LESS_THAN(col+kernelSize, input->numCols, NAN); 502 521 psF32 conv = 0.0; 503 522 for (psS32 yy = -kernelSize ; yy < kernelSize ; yy++) { … … 510 529 psFree(polyValues); 511 530 531 psTrace("ImageSubtract.IsisKernelConvolve", 5, 532 "Exiting IsisKernelConvolve(%d, %d, %d)\n", kernelID, col, row); 512 533 return(conv); 513 534 } 514 535 515 516 517 518 536 /******************************************************************************* 519 XXX: Should we assert that the footprint is equal to the kernel size, or does 520 they have nothing in common. 537 ConvolvePixelPois(input, mask, badStampMaskVal, solution, kernels, col, row): 538 539 This routine takes a single pixel in the psImage input and convolves it with 540 the set of kernel basis functions and their appropriate weights in solution. 541 It returns the value of the convolved pixel. 542 543 XXX: Static structure for polyValues? 544 ******************************************************************************/ 545 static psF32 ConvolvePixelPois(const psImage *input, 546 const psImage *mask, 547 psU32 badStampMaskVal, 548 const psVector *solution, 549 const psSubtractionKernels *kernels, 550 psS32 col, 551 psS32 row) 552 { 553 psTrace("ImageSubtract.ConvolvePixelPois", 5, 554 "Calling ConvolvePixelPois(%d, %d)\n", col, row); 555 psS32 nBF = kernels->u->n; 556 psF32 numColsHalf = 0.5 * (psF32) input->numCols; 557 psF32 numRowsHalf = 0.5 * (psF32) input->numRows; 558 psF32 background = solution->data.F64[solution->n-1]; 559 psS32 spatialOrder = kernels->p_spatialOrder; 560 psF32 conv = background; // Initial convolved value 561 562 if ((mask == NULL) || !(mask->data.U8[row][col] & badStampMaskVal)) { 563 psF32 imageX = (((psF32) col) - numColsHalf) / numColsHalf; // Normalised position 564 psF32 imageY = (((psF32) row) - numRowsHalf) / numRowsHalf; // Normalised position 565 psImage *polyValues = GenSpatialOrder(spatialOrder, imageX, imageY); 566 567 // Iterate over the kernel basis functions 568 for (psS32 k = 0; k < nBF; k++) { 569 psS32 u = (psS32) kernels->u->data.F32[k]; 570 psS32 v = (psS32) kernels->v->data.F32[k]; 571 572 // XXX: What's the story with this? 573 #if 0 574 575 psS32 xOrder = (psS32) kernels->xOrder->data.F32[k]; 576 psS32 yOrder = (psS32) kernels->yOrder->data.F32[k]; 577 psF64 polyVal = polyValues->data.F64[yOrder][xOrder]; 578 #else 579 580 psF32 polyVal = 1.0; 581 #endif 582 583 // XXX: Why this? 584 if (k == 0) { 585 conv += solution->data.F64[k] * input->data.F32[row - v][col - u] * polyVal; 586 } else { 587 conv += solution->data.F64[k] * 588 (input->data.F32[row - v][col - u] * polyVal - input->data.F32[row][col]); 589 } 590 } 591 psFree(polyValues); 592 } 593 594 psTrace("ImageSubtract.ConvolvePixelPois", 5, 595 "Exiting ConvolvePixelPois(%d, %d)\n", col, row); 596 return(conv); 597 } 598 599 600 601 /******************************************************************************* 602 ConvolvePixelIsis(input, mask, badStampMaskVal, solution, kernels, col, row): 603 604 This routine takes a single pixel in the psImage input and convolves it with 605 the set of kernel basis functions and their appropriate weights in solution. 606 It returns the value of the convolved pixel. 607 608 XXX: Static structure for polyValues? 609 ******************************************************************************/ 610 static psF32 ConvolvePixelIsis(const psImage *input, 611 const psImage *mask, 612 psU32 badStampMaskVal, 613 const psVector *solution, 614 const psSubtractionKernels *kernels, 615 psS32 col, 616 psS32 row) 617 { 618 psTrace("ImageSubtract.ConvolvePixelIsis", 5, 619 "Calling ConvolvePixelIsis(%d, %d)\n", col, row); 620 psF32 background = solution->data.F64[solution->n-1]; 621 psF32 conv = background; // Initial convolved value 622 623 if ((mask == NULL) || !(mask->data.U8[row][col] & badStampMaskVal)) { 624 // Iterate over the kernel basis functions 625 for (psS32 k = 0; k < kernels->u->n; k++) { 626 conv += IsisKernelConvolve(input, kernels, k, col, row); 627 } 628 } 629 630 psTrace("ImageSubtract.ConvolvePixelIsis", 5, 631 "Exiting ConvolvePixelIsis(%d, %d)\n", col, row); 632 return(conv); 633 } 634 635 /******************************************************************************* 636 ConvolveImage(input, mask, badStampMaskVal, solution, kernels): convolves an 637 arbitrary image with either an ISIS or POIS set of kernel basis functions. 638 ******************************************************************************/ 639 static psImage *ConvolveImage(const psImage *input, 640 const psImage *mask, 641 psU32 badStampMaskVal, 642 const psVector *solution, 643 const psSubtractionKernels *kernels) 644 { 645 psTrace("ImageSubtract.ConvolveImage", 5, "Calling ConvolveImage()\n"); 646 PS_ASSERT_IMAGE_NON_NULL(input, NULL); 647 PS_ASSERT_IMAGE_NON_EMPTY(input, NULL); 648 PS_ASSERT_IMAGE_TYPE(input, PS_TYPE_F32, NULL); 649 if (mask != NULL) { 650 PS_ASSERT_IMAGES_SIZE_EQUAL(input, mask, NULL); 651 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_U8, NULL); 652 } 653 PS_ASSERT_VECTOR_NON_NULL(solution, NULL); 654 PS_ASSERT_VECTOR_TYPE(solution, PS_TYPE_F64, NULL); 655 PS_ASSERT_PTR_NON_NULL(kernels, NULL); 656 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, NULL); 657 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->xOrder, NULL); 658 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->yOrder, NULL); 659 if (kernels->preCalc != NULL) { 660 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->preCalc, NULL); 661 } else { 662 if (kernels->type != PM_SUBTRACTION_KERNEL_POIS) { 663 psError(PS_ERR_BAD_PARAMETER_NULL, true, 664 "Unallowable operation: kernels->preCalc == NULL and kernels->type != PM_SUBTRACTION_KERNEL_POIS.\n"); 665 return(NULL); 666 } 667 } 668 psS32 nBF = kernels->u->n; 669 PS_ASSERT_VECTOR_SIZE(solution, nBF+1, NULL); 670 671 psS32 numCols = input->numCols; 672 psS32 numRows = input->numRows; 673 psS32 kernelSize = kernels->p_size; 674 675 psImage *convolved = psImageAlloc(numCols, numRows, PS_TYPE_F32); 676 677 for (psS32 y = kernelSize; y < numRows - kernelSize; y++) { 678 for (psS32 x = kernelSize; x < numCols - kernelSize; x++) { 679 if (kernels->type == PM_SUBTRACTION_KERNEL_POIS) { 680 convolved->data.F32[y][x] = ConvolvePixelPois(input, mask, badStampMaskVal, 681 solution, kernels, x, y); 682 } else if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) { 683 convolved->data.F32[y][x] = ConvolvePixelIsis(input, mask, badStampMaskVal, 684 solution, kernels, x, y); 685 } else { 686 psLogMsg(__func__, PS_LOG_WARN, "WARNING: unknown kernel type. Returning NULL\n"); 687 return(NULL); 688 } 689 } 690 } 691 692 // 693 // Pad the rest of the convolved image with 0.0 694 // 695 for (psS32 y = kernelSize; y < numRows - kernelSize; y++) { 696 for (psS32 x = 0; x < kernelSize; x++) { 697 convolved->data.F32[y][x] = 0.0; 698 } 699 for (psS32 x = numCols - kernelSize; x < numCols; x++) { 700 convolved->data.F32[y][x] = 0.0; 701 } 702 } 703 for (psS32 y = 0; y < kernelSize; y++) { 704 for (psS32 x = 0; x < numCols; x++) { 705 convolved->data.F32[y][x] = 0.0; 706 } 707 } 708 for (psS32 y = numRows - kernelSize; y < numRows; y++) { 709 for (psS32 x = 0; x < numCols; x++) { 710 convolved->data.F32[y][x] = 0.0; 711 } 712 } 713 714 psTrace("ImageSubtract.ConvolveImage", 5, "Exiting ConvolveImage()\n"); 715 return convolved; 716 } 717 718 719 720 721 722 /******************************************************************************* 723 XXX: We should assert that the (footprint, kernelSize, imageSize) stuff 724 ensures that all data is accessed in bounds? 521 725 ******************************************************************************/ 522 726 bool pmSubtractionCalculateEquation(psArray *stamps, ///< The stamps for which to calculate the equation, … … 527 731 ) 528 732 { 733 psTrace("ImageSubtract.pmSubtractionCalculateEquation", 1, 734 "Calling pmSubtractionCalculateEquation()\n"); 529 735 PS_ASSERT_PTR_NON_NULL(stamps, false); 530 736 PS_ASSERT_IMAGE_NON_NULL(reference, false); … … 623 829 psTrace("pmSubtractionCalculateEquation", 5, "subCalcEqn(): stamp %d: generated spatial order terms.\n", s); 624 830 625 // 626 // Iterate over all pixels surrounding this stamp. 627 // 628 for (psS32 y = stamp->y - footprint; y < stamp->y + footprint; y++) { 629 for (psS32 x = stamp->x - footprint; x < stamp->x + footprint; x++) { 630 631 psF32 invNoise2 = 1.0/reference->data.F32[y][x]; // The inverse of the noise, squared. 632 633 // XXX: Think about a better decomposition of the computation 634 // based on whether the kernels are ISIS or POIS. 635 636 psTrace("pmSubtractionCalculateEquation", 5, "subCalcEqn(): pixel (%d, %d).\n", y, x); 637 if (kernels->type == PM_SUBTRACTION_KERNEL_POIS) { 831 if (kernels->type == PM_SUBTRACTION_KERNEL_POIS) { 832 // 833 // Iterate over all pixels surrounding this stamp. 834 // 835 for (psS32 y = stamp->y - footprint; y < stamp->y + footprint; y++) { 836 for (psS32 x = stamp->x - footprint; x < stamp->x + footprint; x++) { 837 psTrace("pmSubtractionCalculateEquation", 5, "subCalcEqn(): pixel (%d, %d).\n", y, x); 838 839 // The inverse of the noise, squared. 840 psF32 invNoise2 = 1.0/reference->data.F32[y][x]; 841 638 842 // 639 843 // Iterate over the first convolution */ … … 647 851 // 648 852 // First convolution. This will set the value for the stampVector. 649 //650 853 // 651 854 // XXX: verify the [y-v2][x-u2] subscript. This generated errors in … … 705 908 stampMatrix->data.F64[bgIndex][bgIndex] += invNoise2; 706 909 stampVector->data.F64[bgIndex] += input->data.F32[y][x] * invNoise2; 707 708 } else if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) { 910 } 911 } 912 } else if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) { 913 // 914 // Iterate over all pixels surrounding this stamp. 915 // 916 // XXX: Why isn't there a polyValues term here? 917 // 918 919 for (psS32 y = stamp->y - footprint; y < stamp->y + footprint; y++) { 920 for (psS32 x = stamp->x - footprint; x < stamp->x + footprint; x++) { 921 psTrace("pmSubtractionCalculateEquation", 5, "subCalcEqn(): pixel (%d, %d).\n", y, x); 922 psF32 invNoise2 = 1.0/reference->data.F32[y][x]; // The inverse of the noise, squared. 923 709 924 for (psS32 k1 = 0; k1 < numKernels; k1++) { 710 psF32 conv1 = GeneralKernelConvolve(reference, kernels, k1, x, y);925 psF32 conv1 = IsisKernelConvolve(reference, kernels, k1, x, y); 711 926 712 927 for (psS32 k2 = k1; k2 < numKernels; k2++) { 713 928 //printf("(k1, k2) is (%d, %d)\n", k1, k2); 714 psF32 conv2 = GeneralKernelConvolve(reference, kernels, k2, x, y);715 stampMatrix->data.F64[k1][k2] += conv1 * conv2 * invNoise2;929 psF32 conv2 = IsisKernelConvolve(reference, kernels, k2, x, y); 930 stampMatrix->data.F64[k1][k2]+= conv1 * conv2 * invNoise2; 716 931 } 717 stampVector->data.F64[k1] += input->data.F32[y][x] * conv1 * invNoise2;932 stampVector->data.F64[k1]+= input->data.F32[y][x] * conv1 * invNoise2; 718 933 stampMatrix->data.F64[k1][bgIndex] += conv1 * invNoise2; 719 934 } 720 } else { 721 psLogMsg(__func__, PS_LOG_WARN, "WARNING: unknown kernel->type.\n"); 722 return(false); 723 } // if-else on kernel type. 724 } // y-loop for all pixels. 725 } // x-loop for all pixels. 935 stampMatrix->data.F64[bgIndex][bgIndex] += invNoise2; 936 stampVector->data.F64[bgIndex] += input->data.F32[y][x] * invNoise2; 937 } 938 } 939 } else { 940 psLogMsg(__func__, PS_LOG_WARN, "WARNING: unknown kernel->type.\n"); 941 return(false); 942 } 726 943 psFree(polyValues); 944 945 // XXX: Generate psTrace() 946 if (0) { 947 for (psS32 s = 0; s < stamps->n; s++) { 948 pmStamp *stamp = (pmStamp *) stamps->data[s]; 949 if (stamp->status == PM_STAMP_RECALC) { 950 psVector *stampVector = stamp->vector; 951 printf("COOL: stamp %d vector:\n", s); 952 PS_VECTOR_PRINT_F64(stampVector); 953 } 954 } 955 } 727 956 728 957 // … … 756 985 } 757 986 } 987 psTrace("ImageSubtract.pmSubtractionCalculateEquation", 1, 988 "Exiting pmSubtractionCalculateEquation()\n"); 758 989 return(true); 759 990 } … … 763 994 764 995 /******************************************************************************* 765 XXX: Assert correct vector matrix sizes.766 996 ******************************************************************************/ 767 997 psVector *pmSubtractionSolveEquation(psVector *solution, ///< Solution vector, or NULL … … 769 999 ) 770 1000 { 1001 psTrace("ImageSubtract.pmSubtractionSolveEquation", 1, 1002 "Calling pmSubtractionSolveEquation()\n"); 771 1003 PS_ASSERT_PTR_NON_NULL(stamps, NULL); 772 1004 psS32 size = -1; … … 802 1034 // 803 1035 // XXX: Test these functions with size=-1. This caused seg faults during test. 1036 // This should be done in the psImage.c and psVector.c test files. It 1037 // should never occur here. 804 1038 // 805 1039 psImage *sumMatrix = psImageAlloc(size, size, PS_TYPE_F64); … … 829 1063 } 830 1064 } 831 1065 psVector *permutation = NULL; 832 1066 // XXX: Check output from these routines. 833 psVector *permutation = NULL; 1067 1068 // XXX: psTrace() 1069 if (1) { 1070 PS_IMAGE_PRINT_F64(sumMatrix); 1071 } 1072 834 1073 psImage *luMatrix = psMatrixLUD(NULL, &permutation, sumMatrix); 1074 if (luMatrix == NULL) { 1075 psError(PS_ERR_UNKNOWN, true, "Failed to LU-Decompose the matrix.\n"); 1076 psFree(sumMatrix); 1077 psFree(sumVector); 1078 psFree(luMatrix); 1079 psFree(permutation); 1080 return(NULL); 1081 } 1082 // XXX: psTrace() 1083 if (1) { 1084 PS_IMAGE_PRINT_F64(luMatrix); 1085 } 1086 835 1087 solution = psMatrixLUSolve(solution, luMatrix, sumVector, permutation); 1088 // XXX: psTrace() 1089 if (1) { 1090 PS_VECTOR_PRINT_F64(solution); 1091 } 1092 if (solution == NULL) { 1093 psError(PS_ERR_UNKNOWN, true, "Failed to solve the matrix.\n"); 1094 psFree(sumMatrix); 1095 psFree(sumVector); 1096 psFree(luMatrix); 1097 psFree(permutation); 1098 return(NULL); 1099 } 836 1100 837 1101 psFree(sumMatrix); … … 840 1104 psFree(permutation); 841 1105 1106 psTrace("ImageSubtract.pmSubtractionSolveEquation", 1, 1107 "Exiting pmSubtractionSolveEquation()\n"); 842 1108 return(solution); 843 }844 845 846 /*******************************************************************************847 ConvolvePixelPois(input, mask, badStampMaskVal, solution, kernels, col, row):848 849 This routine takes a single pixel in the psImage input and convolves it with850 the set of kernel basis functions and their appropriate weights in solution.851 It returns the value of the convolved pixel.852 853 XXX: Static structure for polyValues?854 ******************************************************************************/855 static psF32 ConvolvePixelPois(const psImage *input,856 const psImage *mask,857 psU32 badStampMaskVal,858 const psVector *solution,859 const psSubtractionKernels *kernels,860 psS32 col,861 psS32 row)862 {863 psS32 nBF = kernels->u->n;864 psF32 numColsHalf = 0.5 * (psF32) input->numCols;865 psF32 numRowsHalf = 0.5 * (psF32) input->numRows;866 psF32 background = solution->data.F64[solution->n-1];867 psS32 spatialOrder = kernels->p_spatialOrder;868 psF32 conv = background; // Initial convolved value869 870 if ((mask == NULL) || !(mask->data.U8[row][col] & badStampMaskVal)) {871 psF32 imageX = (((psF32) col) - numColsHalf) / numColsHalf; // Normalised position872 psF32 imageY = (((psF32) row) - numRowsHalf) / numRowsHalf; // Normalised position873 psImage *polyValues = GenSpatialOrder(spatialOrder, imageX, imageY);874 875 // Iterate over the kernel basis functions876 for (psS32 k = 0; k < nBF; k++) {877 psS32 u = (psS32) kernels->u->data.F32[k];878 psS32 v = (psS32) kernels->v->data.F32[k];879 880 // XXX: What's the story with this?881 #if 0882 883 psS32 xOrder = (psS32) kernels->xOrder->data.F32[k];884 psS32 yOrder = (psS32) kernels->yOrder->data.F32[k];885 psF32 polyVal = polyValues->data.F32[yOrder][xOrder];886 #else887 888 psF32 polyVal = 1.0;889 #endif890 891 // XXX: Why this?892 if (k == 0) {893 conv += solution->data.F64[k] * input->data.F32[row - v][col - u] * polyVal;894 } else {895 conv += solution->data.F64[k] *896 (input->data.F32[row - v][col - u] * polyVal - input->data.F32[row][col]);897 }898 }899 psFree(polyValues);900 }901 902 return(conv);903 }904 905 906 907 /*******************************************************************************908 ConvolvePixelIsis(input, mask, badStampMaskVal, solution, kernels, col, row):909 910 This routine takes a single pixel in the psImage input and convolves it with911 the set of kernel basis functions and their appropriate weights in solution.912 It returns the value of the convolved pixel.913 914 XXX: Static structure for polyValues?915 ******************************************************************************/916 static psF32 ConvolvePixelIsis(const psImage *input,917 const psImage *mask,918 psU32 badStampMaskVal,919 const psVector *solution,920 const psSubtractionKernels *kernels,921 psS32 col,922 psS32 row)923 {924 psS32 nBF = kernels->u->n;925 psF32 numColsHalf = 0.5 * (psF32) input->numCols;926 psF32 numRowsHalf = 0.5 * (psF32) input->numRows;927 psF32 background = solution->data.F64[solution->n-1];928 psS32 spatialOrder = kernels->p_spatialOrder;929 psS32 kernelSize = kernels->p_size;930 psF32 conv = background; // Initial convolved value931 932 if ((mask == NULL) || !(mask->data.U8[row][col] & badStampMaskVal)) {933 psF32 imageX = (((psF32) col) - numColsHalf) / numColsHalf; // Normalised position934 psF32 imageY = (((psF32) row) - numRowsHalf) / numRowsHalf; // Normalised position935 psImage *polyValues = GenSpatialOrder(spatialOrder, imageX, imageY);936 937 // Iterate over the kernel basis functions938 for (psS32 k = 0; k < nBF; k++) {939 psS32 xOrder = (psS32) kernels->xOrder->data.F32[k];940 psS32 yOrder = (psS32) kernels->yOrder->data.F32[k];941 psF32 polyVal = polyValues->data.F32[yOrder][xOrder];942 943 psImage *preCalc = (psImage *) kernels->preCalc->data[k];944 for (psS32 yy = -kernelSize ; yy < kernelSize ; yy++) {945 for (psS32 xx = -kernelSize ; xx < kernelSize ; xx++) {946 // XXX: Should I do something special for the k==0 kernel?947 conv += solution->data.F64[k] *948 input->data.F32[yy+row][xx+col] *949 preCalc->data.F32[yy+kernelSize][xx+kernelSize] *950 polyVal;951 }952 }953 }954 psFree(polyValues);955 }956 957 return(conv);958 }959 960 /*******************************************************************************961 ConvolveImage(input, mask, badStampMaskVal, solution, kernels): convolves an962 arbitrary image with either an ISIS or POIS set of kernel basis functions.963 ******************************************************************************/964 static psImage *ConvolveImage(const psImage *input,965 const psImage *mask,966 psU32 badStampMaskVal,967 const psVector *solution,968 const psSubtractionKernels *kernels)969 {970 PS_ASSERT_IMAGE_NON_NULL(input, NULL);971 PS_ASSERT_IMAGE_NON_EMPTY(input, NULL);972 PS_ASSERT_IMAGE_TYPE(input, PS_TYPE_F32, NULL);973 if (mask != NULL) {974 PS_ASSERT_IMAGES_SIZE_EQUAL(input, mask, NULL);975 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_U8, NULL);976 }977 PS_ASSERT_VECTOR_NON_NULL(solution, NULL);978 PS_ASSERT_VECTOR_TYPE(solution, PS_TYPE_F64, NULL);979 PS_ASSERT_PTR_NON_NULL(kernels, NULL);980 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->v, NULL);981 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->xOrder, NULL);982 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->yOrder, NULL);983 if (kernels->preCalc != NULL) {984 PS_ASSERT_VECTORS_SIZE_EQUAL(kernels->u, kernels->preCalc, NULL);985 } else {986 if (kernels->type != PM_SUBTRACTION_KERNEL_POIS) {987 psError(PS_ERR_BAD_PARAMETER_NULL, true,988 "Unallowable operation: kernels->preCalc == NULL and kernels->type != PM_SUBTRACTION_KERNEL_POIS.\n");989 return(NULL);990 }991 }992 psS32 nBF = kernels->u->n;993 PS_ASSERT_VECTOR_SIZE(solution, nBF+1, NULL);994 995 psS32 numCols = input->numCols;996 psS32 numRows = input->numRows;997 psS32 kernelSize = kernels->p_size;998 999 psImage *convolved = psImageAlloc(numCols, numRows, PS_TYPE_F32);1000 1001 for (psS32 y = kernelSize; y < numRows - kernelSize; y++) {1002 for (psS32 x = kernelSize; x < numCols - kernelSize; x++) {1003 if (kernels->type == PM_SUBTRACTION_KERNEL_POIS) {1004 convolved->data.F32[y][x] = ConvolvePixelPois(input, mask, badStampMaskVal,1005 solution, kernels, x, y);1006 } else if (kernels->type == PM_SUBTRACTION_KERNEL_ISIS) {1007 convolved->data.F32[y][x] = ConvolvePixelIsis(input, mask, badStampMaskVal,1008 solution, kernels, x, y);1009 } else {1010 psLogMsg(__func__, PS_LOG_WARN, "WARNING: unknown kernel type. Returning NULL\n");1011 return(NULL);1012 }1013 }1014 }1015 1016 //1017 // Pad the rest of the convolved image with 0.01018 //1019 for (psS32 y = kernelSize; y < numRows - kernelSize; y++) {1020 for (psS32 x = 0; x < kernelSize; x++) {1021 convolved->data.F32[y][x] = 0.0;1022 }1023 for (psS32 x = numCols - kernelSize; x < numCols; x++) {1024 convolved->data.F32[y][x] = 0.0;1025 }1026 }1027 for (psS32 y = 0; y < kernelSize; y++) {1028 for (psS32 x = 0; x < numCols; x++) {1029 convolved->data.F32[y][x] = 0.0;1030 }1031 }1032 for (psS32 y = numRows - kernelSize; y < numRows; y++) {1033 for (psS32 x = 0; x < numCols; x++) {1034 convolved->data.F32[y][x] = 0.0;1035 }1036 }1037 1038 return convolved;1039 1109 } 1040 1110 … … 1052 1122 const psVector *solution) 1053 1123 { 1124 psTrace("ImageSubtract.CalculateDeviations", 5, 1125 "Calling CalculateDeviations()\n"); 1054 1126 PS_ASSERT_PTR_NON_NULL(stamps, NULL); 1055 1127 if (deviations != NULL) { … … 1115 1187 psImage *subStampTrim = psImageSubset((psImage *) subStamp, myReg); 1116 1188 psImage *maskStampTrim = psImageSubset((psImage *) maskStamp, myReg); 1117 // Copy image to workaround bug 305 1118 // XXX: Modify. This bug is now fixed. 1119 // psImage *tempImage = psImageCopy(NULL, subStampTrim, PS_TYPE_F32); 1120 // psImage *tempMask = psImageCopy(NULL, maskStampTrim, PS_TYPE_U8); 1121 // (void)psImageStats(stats, tempImage, tempMask, badStampMaskVal); 1122 (void)psImageStats(stats, subStampTrim, maskStampTrim, badStampMaskVal); 1189 psImageStats(stats, subStampTrim, maskStampTrim, badStampMaskVal); 1123 1190 1124 1191 deviations->data.F32[s] = stats->sampleMean * (psF32)footprint * (psF32)footprint * 4.0; … … 1136 1203 psFree(subStamp); 1137 1204 1205 psTrace("ImageSubtract.CalculateDeviations", 5, 1206 "Exiting CalculateDeviations()\n"); 1138 1207 return deviations; 1139 1208 } … … 1152 1221 ) 1153 1222 { 1223 psTrace("ImageSubtract.pmSubtractionRejectStamps", 5, 1224 "Calling pmSubtractionRejectStamps()\n"); 1154 1225 PS_ASSERT_PTR_NON_NULL(stamps, false); 1155 1226 PS_ASSERT_IMAGE_NON_NULL(refImage, false); … … 1225 1296 1226 1297 psFree(deviations); 1298 psTrace("ImageSubtract.pmSubtractionRejectStamps", 5, 1299 "Exiting pmSubtractionRejectStamps()\n"); 1227 1300 return(true); 1228 1301 } … … 1237 1310 ) 1238 1311 { 1312 psTrace("ImageSubtract.pmSubtractionKernelImage", 5, 1313 "Calling pmSubtractionKernelImage()\n"); 1239 1314 PS_ASSERT_VECTOR_NON_NULL(solution, NULL); 1240 1315 PS_ASSERT_PTR_NON_NULL(kernels, NULL); … … 1280 1355 psS32 xOrder = (psS32) kernels->xOrder->data.F32[k]; 1281 1356 psS32 yOrder = (psS32) kernels->yOrder->data.F32[k]; 1282 psF 32 polyVal = polyValues->data.F32[yOrder][xOrder];1357 psF64 polyVal = polyValues->data.F64[yOrder][xOrder]; 1283 1358 1284 1359 // XXX: Verify that this is correct. … … 1304 1379 1305 1380 out->data.F32[kernelSize - v][kernelSize - u]+= 1306 solution->data.F64[k] * polyValues->data.F 32[yOrder][xOrder];1381 solution->data.F64[k] * polyValues->data.F64[yOrder][xOrder]; 1307 1382 } 1308 1383 } 1309 1384 psFree(polyValues); 1310 1385 1386 psTrace("ImageSubtract.pmSubtractionKernelImage", 5, 1387 "Exiting pmSubtractionKernelImage()\n"); 1311 1388 return(out); 1312 1389 } -
trunk/psModules/src/pmImageSubtract.h
r4322 r4417 1 1 /** @file ImageSubtract.h 2 2 * 3 * This file will ... 3 * This file will contain code which creates a set of kernel basis 4 * functions, solves for their solution, and applies them to an image. 4 5 * 6 * @author Paul Price, IfA (original prototype) 5 7 * @author GLG, MHPCC 6 8 * 7 * @version $Revision: 1. 2$ $Name: not supported by cvs2svn $8 * @date $Date: 2005-06-2 0 23:21:05 $9 * @version $Revision: 1.3 $ $Name: not supported by cvs2svn $ 10 * @date $Date: 2005-06-28 23:23:55 $ 9 11 * 10 12 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 26 28 typedef enum { 27 29 PM_SUBTRACTION_KERNEL_POIS, ///< POIS kernel --- delta functions 28 PM_SUBTRACTION_KERNEL_ISIS ///< ISIS kernel --- gaussians modified by polynomials30 PM_SUBTRACTION_KERNEL_ISIS ///< ISIS kernel --- gaussians modified by polynomials 29 31 } pmSubtractionKernelsType; 30 32 … … 32 34 { 33 35 pmSubtractionKernelsType type; ///< Type ofKernels --- allowing the use of multiple kernels 34 psVector *u, *v; ///< Offset (for POIS) or polynomial order (for ISIS)35 psVector *sigma; ///< Width of Gaussian (for ISIS)36 psVector *xOrder, *yOrder; ///< Spatial Polynomial order (for all)37 int subIndex; ///< Index of kernel to be subtracted to maintain flux conservation38 psArray *preCalc; ///< Array of images containing pre-calculated kernel (to36 psVector *u, *v; ///< Offset (for POIS) or polynomial order (for ISIS) 37 psVector *sigma; ///< Width of Gaussian (for ISIS) 38 psVector *xOrder, *yOrder; ///< Spatial Polynomial order (for all) 39 int subIndex; ///< Index of kernel to be subtracted to maintain flux conservation 40 psArray *preCalc; ///< Array of images containing pre-calculated kernel (to 39 41 ///< accelerate ISIS; don't use for POIS) 40 psS32 p_size; ///< The halfsize of the kernel41 psS32 p_spatialOrder; ///< The spatial order of the kernels42 psS32 p_size; ///< The halfsize of the kernel 43 psS32 p_spatialOrder; ///< The spatial order of the kernels 42 44 } 43 45 psSubtractionKernels; … … 52 54 53 55 typedef enum { 54 PM_STAMP_INIT, ///< Initial state55 PM_STAMP_USED, ///< Use this stamp56 PM_STAMP_REJECTED, ///< This stamp has been rejected57 PM_STAMP_RECALC, ///< Having been reset, this stamp is to be recalculated58 PM_STAMP_NONE ///< No stamp in this region56 PM_STAMP_INIT, ///< Initial state 57 PM_STAMP_USED, ///< Use this stamp 58 PM_STAMP_REJECTED, ///< This stamp has been rejected 59 PM_STAMP_RECALC, ///< Having been reset, this stamp is to be recalculated 60 PM_STAMP_NONE ///< No stamp in this region 59 61 } pmStampStatus; 60 62
Note:
See TracChangeset
for help on using the changeset viewer.
