Changeset 19895 for trunk/psLib/src/imageops/psImageConvolve.c
- Timestamp:
- Oct 3, 2008, 4:37:51 PM (18 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/imageops/psImageConvolve.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/imageops/psImageConvolve.c
r19298 r19895 7 7 /// @author Eugene Magnier, IfA 8 8 /// 9 /// @version $Revision: 1.7 6$ $Name: not supported by cvs2svn $10 /// @date $Date: 2008- 08-30 02:24:21 $9 /// @version $Revision: 1.77 $ $Name: not supported by cvs2svn $ 10 /// @date $Date: 2008-10-04 02:37:51 $ 11 11 /// 12 12 /// Copyright 2004-2007 Institute for Astronomy, University of Hawaii … … 33 33 34 34 #include "psImageConvolve.h" 35 36 #define MIN_GAUSS_FRAC 0.25 // Minimum Gaussian fraction to accept when smoothing 37 35 38 36 39 static bool threaded = false; // Run image convolution threaded? … … 642 645 } 643 646 647 // Smooth an image with masked pixels 648 // The calculation and calcMask images are *deliberately* backwards (row,col instead of col,row or 649 // [col][row] instead of [row][col]) to optimise the iteration over rows; such instances are marked "BW" 650 #define IMAGESMOOTH_MASK_CASE(TYPE) \ 651 case PS_TYPE_##TYPE: { \ 652 psImage *calculation = psImageAlloc(numRows, numCols, PS_TYPE_##TYPE); /* Calculation image; BW */ \ 653 psImage *calcMask = psImageAlloc(numRows, numCols, PS_TYPE_MASK); /* Mask for calculation image; BW */ \ 654 \ 655 /** Smooth in X direction **/ \ 656 for (int j = 0; j < numRows; j++) { \ 657 for (int i = 0; i < numCols; i++) { \ 658 int xMin = PS_MAX(i - size, 0); \ 659 int xMax = PS_MIN(i + size, xLast); \ 660 const psMaskType *maskData = &mask->data.PS_TYPE_MASK_DATA[j][xMin]; \ 661 const ps##TYPE *imageData = &image->data.TYPE[j][xMin]; \ 662 int uMin = - PS_MIN(i, size); /* Minimum kernel index */ \ 663 const psF32 *gaussData = &gauss[uMin]; \ 664 double sumIG = 0.0, sumG = 0.0; /* Sums for convolution */ \ 665 for (int x = xMin; x <= xMax; x++, maskData++, imageData++, gaussData++) { \ 666 if (*maskData & maskVal) { \ 667 continue; \ 668 } \ 669 sumIG += *imageData * *gaussData; \ 670 sumG += *gaussData; \ 671 } \ 672 if (sumG > MIN_GAUSS_FRAC) { \ 673 /* BW */ \ 674 calculation->data.TYPE[i][j] = sumIG / sumG; \ 675 calcMask->data.PS_TYPE_MASK_DATA[i][j] = 0; \ 676 } else { \ 677 /* BW */ \ 678 calcMask->data.PS_TYPE_MASK_DATA[i][j] = 0xFF; \ 679 } \ 680 } \ 681 } \ 682 \ 683 output = psImageRecycle(output, numCols, numRows, PS_TYPE_##TYPE); \ 684 \ 685 /** Smooth in Y direction **/ \ 686 for (int i = 0; i < numCols; i++) { \ 687 for (int j = 0; j < numRows; j++) { \ 688 int yMin = PS_MAX(j - size, 0); \ 689 int yMax = PS_MIN(j + size, yLast); \ 690 const psMaskType *maskData = &calcMask->data.PS_TYPE_MASK_DATA[i][yMin]; /* BW */ \ 691 const ps##TYPE *imageData = &calculation->data.TYPE[i][yMin]; /* BW */ \ 692 int vMin = - PS_MIN(j, size); /* Minimum kernel index */ \ 693 const psF32 *gaussData = &gauss[vMin]; \ 694 double sumIG = 0.0, sumG = 0.0; /* Sums for convolution */ \ 695 for (int y = yMin; y <= yMax; y++, maskData++, imageData++, gaussData++) { \ 696 if (*maskData) { \ 697 continue; \ 698 } \ 699 sumIG += *imageData * *gaussData; \ 700 sumG += *gaussData; \ 701 } \ 702 output->data.TYPE[j][i] = (sumG > MIN_GAUSS_FRAC) ? sumIG / sumG : NAN; \ 703 } \ 704 } \ 705 \ 706 psFree(calculation); \ 707 psFree(calcMask); \ 708 psFree(gaussNorm); \ 709 \ 710 return output; \ 711 } 712 713 714 715 psImage *psImageSmoothMask(psImage *output, 716 const psImage *image, 717 const psImage *mask, 718 psMaskType maskVal, 719 double sigma, 720 double numSigma) 721 { 722 PS_ASSERT_IMAGE_NON_NULL(image, NULL); 723 PS_ASSERT_IMAGE_NON_NULL(mask, NULL); 724 PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_MASK, NULL); 725 PS_ASSERT_IMAGES_SIZE_EQUAL(image, mask, NULL); 726 727 int numCols = image->numCols, numRows = image->numRows; // Size of image 728 int xLast = numCols - 1, yLast = numRows - 1; // Last index 729 730 // relevant terms 731 int size = sigma * numSigma + 0.5; // Half-size of kernel 732 int fullSize = 2*size + 1; // Total number of pixels in convolution kernel 733 734 // Generate normalized gaussian 735 psVector *gaussNorm = psVectorAlloc(fullSize + 1, PS_TYPE_F32); // Normalised Gaussian 736 { 737 double sum = 0.0; 738 double norm = -0.5/(sigma*sigma); 739 for (int i = 0, u = -size; i <= fullSize; i++, u++) { 740 float value = expf(norm*PS_SQR(u)); 741 gaussNorm->data.F32[i] = value; 742 sum += value; 743 } 744 sum = 1.0 / sum; 745 for (int i = 0; i <= fullSize; i++) { 746 gaussNorm->data.F32[i] *= sum; 747 } 748 } 749 const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel 750 751 switch (image->type.type) { 752 IMAGESMOOTH_MASK_CASE(F32); 753 IMAGESMOOTH_MASK_CASE(F64); 754 default: 755 psFree(gaussNorm); 756 char *typeStr; 757 PS_TYPE_NAME(typeStr,image->type.type); 758 psError(PS_ERR_BAD_PARAMETER_TYPE, true, 759 _("Specified psImage type, %s, is not supported."), 760 typeStr); 761 return false; 762 } 763 764 psAbort("Should never reach here."); 765 return false; 766 } 767 768 644 769 bool psImageSmoothMaskF32 (psImage *image, 645 770 psImage *mask, … … 695 820 g += *sg; 696 821 } 697 *vo = (g > 0.25) ? s / g : NAN;822 *vo = (g > MIN_GAUSS_FRAC) ? s / g : NAN; 698 823 } 699 824 memcpy(image->data.F32[j], calculation->data.F32, Nx*sizeof(psF32)); … … 740 865 psF32 *vs = outsum->data.F32; 741 866 for (int i = 0; i < Nx; i++, vo++, vs++) { 742 *vo = (*vs > 0.25) ? *vo / *vs : NAN;867 *vo = (*vs > MIN_GAUSS_FRAC) ? *vo / *vs : NAN; 743 868 } 744 869
Note:
See TracChangeset
for help on using the changeset viewer.
