Changeset 17295
- Timestamp:
- Apr 2, 2008, 2:26:17 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/psModules/src/imcombine/pmSubtractionMatch.c
r16630 r17295 19 19 20 20 #define KERNEL_MOSAIC 2 // Half-number of kernel instances in the mosaic image 21 #define BG_STAT PS_STAT_ROBUST_MEDIAN // Statistic to use for background 21 22 22 23 static bool useFFT = true; // Do convolutions using FFT … … 272 273 273 274 if (mode == PM_SUBTRACTION_MODE_UNSURE || mode == PM_SUBTRACTION_MODE_TARGET) { 274 pmSubtractionMode newMode = pmSubtractionOrder(stamps, footprint); // Subtraction mode 275 // Get backgrounds 276 psStats *bgStats = psStatsAlloc(BG_STAT); // Statistics for background 277 psRandom *rng = psRandomAlloc(PS_RANDOM_TAUS, 0); // Random number generator 278 psVector *buffer = NULL;// Buffer for stats 279 if (!psImageBackground(bgStats, &buffer, ro1->image, ro1->mask, maskBad, rng)) { 280 psError(PS_ERR_UNKNOWN, false, "Unable to measure background of image 1."); 281 psFree(bgStats); 282 psFree(rng); 283 psFree(buffer); 284 goto MATCH_ERROR; 285 } 286 float bg1 = psStatsGetValue(bgStats, BG_STAT); // Background for image 1 287 if (!psImageBackground(bgStats, &buffer, ro2->image, ro2->mask, maskBad, rng)) { 288 psError(PS_ERR_UNKNOWN, false, "Unable to measure background of image 2."); 289 psFree(bgStats); 290 psFree(rng); 291 psFree(buffer); 292 goto MATCH_ERROR; 293 } 294 float bg2 = psStatsGetValue(bgStats, BG_STAT); // Background for image 2 295 psFree(bgStats); 296 psFree(rng); 297 psFree(buffer); 298 299 pmSubtractionMode newMode = pmSubtractionOrder(stamps, bg1, bg2); // Subtraction mode to use 275 300 switch (newMode) { 276 301 case PM_SUBTRACTION_MODE_1: … … 529 554 } 530 555 531 // Calculate the second order moments for an image 532 static float subtractionOrderMoment(const psKernel *kernel, // Image for which to measure moments 533 int radius // Maximum radius 534 ) 556 557 // Determine a rough width (integer value) of the star in the image 558 // XXX Could improve this by using a user-provided list of floating-point widths (or an end point and 559 // increment). 560 static int subtractionOrderWidth(const psKernel *kernel, // Image 561 float bg, // Background in image 562 int size, // Maximum size 563 psArray **models, // Buffer of models 564 psVector **modelSums // Buffer of model sums 565 ) 535 566 { 536 assert(kernel && kernel->kernel); 537 538 int xMin = PS_MAX(kernel->xMin, -radius), xMax = PS_MIN(kernel->xMax, radius); // Bounds in x 539 int yMin = PS_MAX(kernel->yMin, -radius), yMax = PS_MIN(kernel->yMax, radius); // Bounds in y 540 541 float xCentroid = 0.0, yCentroid = 0.0; // Centroid (first moment) 542 float sum = 0.0; // Sum (zero-th moment) 543 for (int y = yMin; y <= yMax; y++) { 544 for (int x = xMin; x <= xMax; x++) { 545 xCentroid += kernel->kernel[y][x] * x; 546 yCentroid += kernel->kernel[y][x] * y; 547 sum += kernel->kernel[y][x]; 548 } 549 } 550 xCentroid /= sum; 551 yCentroid /= sum; 552 553 float eta20 = 0.0, eta02 = 0.0; // Second moments 554 for (int y = yMin; y <= yMax; y++) { 555 float yDiff = y - yCentroid; 556 for (int x = xMin; x <= xMax; x++) { 557 float xDiff = x - xCentroid; 558 eta20 += PS_SQR(xDiff) * kernel->kernel[y][x]; 559 eta02 += PS_SQR(yDiff) * kernel->kernel[y][x]; 560 } 561 } 562 563 // Normalise to calculate the scale-invariant 564 float sum2 = PS_SQR(sum); 565 eta20 /= sum2; 566 eta02 /= sum2; 567 // eta11 /= sum2; 568 569 return eta20 + eta02; 567 assert(kernel); 568 assert(models); 569 assert(modelSums); 570 571 int xMin = kernel->xMin, xMax = kernel->xMax; // Bounds in x 572 int yMin = kernel->yMin, yMax = kernel->yMax; // Bounds in y 573 574 // Generate models 575 if (!*models) { 576 assert(!*modelSums); 577 *models = psArrayAlloc(size); 578 *modelSums = psVectorAlloc(size, PS_TYPE_F64); 579 for (int sigma = 0; sigma < size; sigma++) { 580 psKernel *model = psKernelAlloc(xMin, xMax, yMin, yMax); // Gaussian model 581 float invSigma2 = 1.0 / (float)PS_SQR(1 + sigma); // Inverse sigma squared 582 double sumGG = 0.0; // Sum of square of Gaussian 583 for (int y = yMin; y <= yMax; y++) { 584 int y2 = PS_SQR(y); // y squared 585 for (int x = xMin; x <= xMax; x++) { 586 float rad2 = PS_SQR(x) + y2; // Radius squared 587 float value = expf(-rad2 * invSigma2); // Model value 588 model->kernel[y][x] = value; 589 sumGG += PS_SQR(value); 590 } 591 } 592 (*models)->data[sigma] = model; 593 (*modelSums)->data.F64[sigma] = sumGG; 594 } 595 } 596 597 // Fit gaussians of varying widths to the image, record the chi^2 598 psVector *chi2 = psVectorAlloc(size, PS_TYPE_F32); // chi^2 as a function of radius 599 for (int sigma = 0; sigma < size; sigma++) { 600 double sumFG = 0.0; // Sum for calculating the normalisation of the Gaussian 601 psKernel *model = (*models)->data[sigma]; // Model of interest 602 for (int y = yMin; y <= yMax; y++) { 603 for (int x = xMin; x <= xMax; x++) { 604 sumFG += model->kernel[y][x] * (kernel->kernel[y][x] - bg); 605 } 606 } 607 float norm = sumFG / (*modelSums)->data.F64[sigma]; // Normalisation for Gaussian 608 double sumDev2 = 0.0; // Sum of square deviations 609 for (int y = yMin; y <= yMax; y++) { 610 for (int x = xMin; x <= xMax; x++) { 611 float dev = kernel->kernel[y][x] - bg - norm * model->kernel[y][x]; // Deviation 612 sumDev2 += PS_SQR(dev); 613 } 614 } 615 chi2->data.F32[sigma] = sumDev2; 616 } 617 618 // Find the minimum chi^2 619 int bestIndex = -1; // Index of best chi^2 620 float bestChi2 = INFINITY; // Best chi^2 621 for (int i = 0; i < size; i++) { 622 if (chi2->data.F32[i] < bestChi2) { 623 bestChi2 = chi2->data.F32[i]; 624 bestIndex = i; 625 } 626 } 627 psFree(chi2); 628 629 return bestIndex + 1; 570 630 } 571 631 572 #if 0 573 // Calculate the deviations for a particular subtraction order 574 static psVector *subtractionOrderDeviation(float *sumKernel, // Sum of the kernel 575 pmSubtractionStampList *stamps, // Stamps to convolve 576 const pmSubtractionKernels *kernels, // Kernel basis functions 577 int footprint, // Stamp footprint 578 pmSubtractionMode mode // Mode of subtraction 579 ) 632 pmSubtractionMode pmSubtractionOrder(pmSubtractionStampList *stamps, float bg1, float bg2) 580 633 { 581 assert(stamps); 582 assert(footprint >= 0); 583 assert(mode == PM_SUBTRACTION_MODE_1 || mode == PM_SUBTRACTION_MODE_2); 584 585 if (!pmSubtractionCalculateEquation(stamps, kernels, footprint, mode)) { 586 psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation."); 587 return NULL; 588 } 589 590 psVector *solution = pmSubtractionSolveEquation(NULL, stamps); 591 if (!solution) { 592 psError(PS_ERR_UNKNOWN, false, "Unable to calculate least-squares equation."); 593 return NULL; 594 } 595 596 if (sumKernel) { 597 float sum = 0.0; // Sum of the kernel 598 psImage *image = pmSubtractionKernelImage(solution, kernels, 0.0, 0.0); // Image of kernel 599 for (int y = 0; y < image->numRows; y++) { 600 for (int x = 0; x < image->numCols; x++) { 601 sum += image->data.F32[y][x]; 602 } 603 } 604 psFree(image); 605 *sumKernel = sum; 606 } 607 608 psVector *deviations = pmSubtractionCalculateDeviations(stamps, solution, footprint, kernels, mode); 609 psFree(solution); 610 if (!deviations) { 611 psError(PS_ERR_UNKNOWN, false, "Unable to calculate deviations."); 612 return NULL; 613 } 614 615 return deviations; 616 } 617 #endif 618 619 pmSubtractionMode pmSubtractionOrder(pmSubtractionStampList *stamps, int radius) 620 { 621 PS_ASSERT_INT_POSITIVE(radius, PM_SUBTRACTION_MODE_ERR); 634 PM_ASSERT_SUBTRACTION_STAMP_LIST_NON_NULL(stamps, PM_SUBTRACTION_MODE_ERR); 622 635 623 636 psVector *mask = psVectorAlloc(stamps->num, PS_TYPE_MASK); // Mask for stamps 624 psVector *moments = psVectorAlloc(stamps->num, PS_TYPE_F32); // Moments 637 psVector *ratios = psVectorAlloc(stamps->num, PS_TYPE_F32); // Ratios of widths 638 psArray *models = NULL; // Gaussian models 639 psVector *modelSums = NULL; // Gaussian model sums 625 640 for (int i = 0; i < stamps->num; i++) { 626 641 pmSubtractionStamp *stamp = stamps->stamps->data[i]; // Stamp of interest … … 630 645 } 631 646 mask->data.PS_TYPE_MASK_DATA[i] = 0; 632 moments->data.F32[i] = subtractionOrderMoment(stamp->image1, radius) / 633 subtractionOrderMoment(stamp->image2, radius); 634 } 647 648 // Widths of stars 649 int width1 = subtractionOrderWidth(stamp->image1, bg1, stamps->footprint, &models, &modelSums); 650 int width2 = subtractionOrderWidth(stamp->image2, bg2, stamps->footprint, &models, &modelSums); 651 652 if (width1 == -1 || width2 == -2) { 653 ratios->data.F32[i] = NAN; 654 mask->data.PS_TYPE_MASK_DATA[i] = 0xff; 655 } else { 656 ratios->data.F32[i] = (float)width1 / (float)width2; 657 } 658 } 659 psFree(models); 660 psFree(modelSums); 635 661 636 662 psStats *stats = psStatsAlloc(PS_STAT_ROBUST_MEDIAN); 637 if (!psVectorStats(stats, moments, NULL, mask, 0xff)) {663 if (!psVectorStats(stats, ratios, NULL, mask, 0xff)) { 638 664 psError(PS_ERR_UNKNOWN, false, "Unable to calculate statistics for moments ratio."); 639 665 psFree(mask); 640 psFree( moments);666 psFree(ratios); 641 667 psFree(stats); 642 668 return PM_SUBTRACTION_MODE_ERR; 643 669 } 644 psFree( moments);670 psFree(ratios); 645 671 psFree(mask); 646 672 647 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Median ratio of second moments: %lf", stats->robustMedian);673 psLogMsg("psModules.imcombine", PS_LOG_INFO, "Median moment: %lf", stats->robustMedian); 648 674 pmSubtractionMode mode = (stats->robustMedian <= 1.0 ? PM_SUBTRACTION_MODE_1 : PM_SUBTRACTION_MODE_2); 649 675 psFree(stats);
Note:
See TracChangeset
for help on using the changeset viewer.
