IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 25337


Ignore:
Timestamp:
Sep 10, 2009, 6:41:31 PM (17 years ago)
Author:
Paul Price
Message:

Adding function to convolve particular pixels only.

Location:
branches/pap/psLib/src/imageops
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/pap/psLib/src/imageops/psImageConvolve.c

    r24272 r25337  
    678678}
    679679
     680static bool imageSmoothMaskPixels(psVector *out, const psImage *image, const psImage *mask,
     681                                  psImageMaskType maskVal, const psVector *x, const psVector *y,
     682                                  const psVector *gaussNorm, float minGauss, int size, int start, int stop)
     683{
     684    const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel
     685    int numCols = image->numCols, numRows = image->numRows; // Size of image
     686    int xLast = numCols - 1, yLast = numRows - 1; // Last index
     687    for (int i = start; i < stop; i++) {
     688        int xPix = x->data.S32[i], yPix = y->data.S32[i]; // Pixel coordinates for smoothing
     689
     690        int yMin = PS_MAX(yPix - size, 0);
     691        int yMax = PS_MIN(yPix + size, yLast);
     692        int xMin = PS_MAX(xPix - size, 0);
     693        int xMax = PS_MIN(xPix + size, xLast);
     694
     695        const float *yGauss = &gauss[yMin - yPix];
     696
     697        double ySumIG = 0.0, ySumG = 0.0;
     698        for (int v = yMin; v <= yMax; v++, yGauss++) {
     699            const float *xGauss = &gauss[xMin - xPix];
     700            double xSumIG = 0.0, xSumG = 0.0;
     701            const psImageMaskType *maskData = &mask->data.PS_TYPE_IMAGE_MASK_DATA[v][xMin];
     702            const psF32 *imageData = &image->data.F32[v][xMin];
     703            for (int u = xMin; u <= xMax; u++, xGauss++, imageData++, maskData++) {
     704                if (*maskData & maskVal) {
     705                    continue;
     706                }
     707                xSumIG += *imageData * *xGauss;
     708                xSumG += *xGauss;
     709            }
     710            if (xSumG > minGauss) {
     711                ySumIG += xSumIG * *yGauss;
     712                ySumG += xSumG * *yGauss;
     713            }
     714        }
     715
     716        out->data.F32[i] = ySumG > minGauss ? ySumIG / ySumG : NAN;
     717    }
     718
     719    return true;
     720}
     721
     722static bool psImageSmoothMaskPixelsThread(psThreadJob *job)
     723{
     724    PS_ASSERT_THREAD_JOB_NON_NULL(job, false);
     725    psAssert(job->args, "programming error: no job arguments");
     726    psAssert(job->args->n == 11, "programming error: wrong number of job arguments");
     727
     728    psVector *out = job->args->data[0]; // Output vector
     729    const psImage *image  = job->args->data[1]; // Input image
     730    const psImage *mask   = job->args->data[2]; // Input mask
     731    psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3], PS_TYPE_IMAGE_MASK_DATA);
     732    const psVector *x = job->args->data[4];
     733    const psVector *y = job->args->data[5];
     734    const psVector *gaussNorm = job->args->data[6];
     735    float minGauss = PS_SCALAR_VALUE(job->args->data[7], F32);
     736    int size = PS_SCALAR_VALUE(job->args->data[8], S32);
     737    int start = PS_SCALAR_VALUE(job->args->data[9], S32);
     738    int stop = PS_SCALAR_VALUE(job->args->data[10], S32);
     739    return imageSmoothMaskPixels(out, image, mask, maskVal, x, y, gaussNorm,
     740                                 minGauss, size, start, stop);
     741}
     742
     743
     744psVector *psImageSmoothMaskPixels(const psImage *image, const psImage *mask, psImageMaskType maskVal,
     745                                  const psVector *x, const psVector *y,
     746                                  float sigma, float numSigma, float minGauss)
     747{
     748    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
     749    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
     750    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_IMAGE_MASK, NULL);
     751    PS_ASSERT_IMAGES_SIZE_EQUAL(image, mask, NULL);
     752    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
     753    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_S32, NULL);
     754    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     755    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_S32, NULL);
     756    PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL);
     757
     758    int size = sigma * numSigma + 0.5;  // Half-size of kernel
     759
     760    int num = x->n;                     // Number of pixels to smooth
     761    psVector *out = psVectorAlloc(num, PS_TYPE_F32); // Output results
     762
     763    // Generate normalized gaussian
     764    IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32);
     765
     766    // Columns
     767    if (threaded) {
     768        int numThreads = psThreadPoolSize(); // Number of threads
     769        int delta = (numThreads) ? num / numThreads + 1 : num; // Block of cols to do at once
     770        for (int start = 0; start < num; start += delta) {
     771            int stop = PS_MIN(start + delta, num);  // End of block
     772
     773            psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS");
     774            psArrayAdd(job->args, 1, out);
     775            psArrayAdd(job->args, 1, (psImage*)image);
     776            psArrayAdd(job->args, 1, (psImage*)mask);
     777            PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK);
     778            psArrayAdd(job->args, 1, (psVector*)x);
     779            psArrayAdd(job->args, 1, (psVector*)y);
     780            psArrayAdd(job->args, 1, gaussNorm);
     781            PS_ARRAY_ADD_SCALAR(job->args, minGauss, PS_TYPE_F32);
     782            PS_ARRAY_ADD_SCALAR(job->args, size, PS_TYPE_S32);
     783            PS_ARRAY_ADD_SCALAR(job->args, start, PS_TYPE_S32);
     784            PS_ARRAY_ADD_SCALAR(job->args, stop, PS_TYPE_S32);
     785            if (!psThreadJobAddPending(job)) {
     786                psFree(job);
     787                psFree(gaussNorm);
     788                psFree(out);
     789                return NULL;
     790            }
     791            psFree(job);
     792        }
     793    } else if (!imageSmoothMaskPixels(out, image, mask, maskVal, x, y,
     794                                      gaussNorm, minGauss, size, 0, num)) {
     795        psError(PS_ERR_UNKNOWN, false, "Unable to smooth pixels.");
     796        psFree(gaussNorm);
     797        psFree(out);
     798        return NULL;
     799    }
     800
     801    if (threaded && !psThreadPoolWait(true)) {
     802        psError(PS_ERR_UNKNOWN, false, "Error waiting for threads.");
     803        psFree(gaussNorm);
     804        psFree(out);
     805        return NULL;
     806    }
     807
     808    psFree(gaussNorm);
     809    return out;
     810}
     811
     812
    680813// Smooth an image with masked pixels
    681814// The calculation and calcMask images are *deliberately* backwards (row,col instead of col,row or
     
    13251458    if (threaded) {
    13261459        int numThreads = psThreadPoolSize(); // Number of threads
    1327         int deltaRows = (numThreads) ? numRows / numThreads : numRows; // Block of rows to do at once
     1460        int deltaRows = (numThreads) ? numRows / numThreads + 1 : numRows; // Block of rows to do at once
    13281461        for (int start = 0; start < numRows; start += deltaRows) {
    1329             int stop = PS_MIN (start + deltaRows, numRows);  // end of row block
     1462            int stop = PS_MIN(start + deltaRows, numRows);  // end of row block
    13301463
    13311464            psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_CONVOLVE_MASK");
     
    13631496    if (threaded) {
    13641497        int numThreads = psThreadPoolSize(); // Number of threads
    1365         int deltaCols = (numThreads) ? numCols / numThreads : numCols; // Block of cols to do at once
     1498        int deltaCols = (numThreads) ? numCols / numThreads + 1 : numCols; // Block of cols to do at once
    13661499        for (int start = 0; start < numCols; start += deltaCols) {
    1367             int stop = PS_MIN (start + deltaCols, numCols);  // end of col block
     1500            int stop = PS_MIN(start + deltaCols, numCols);  // end of col block
    13681501
    13691502            psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_CONVOLVE_MASK");
     
    14861619            psFree(task);
    14871620        }
     1621        {
     1622            psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS", 9);
     1623            task->function = &psImageSmoothMaskPixelsThread;
     1624            psThreadTaskAdd(task);
     1625            psFree(task);
     1626        }
    14881627    } else if (!set && threaded) {
    14891628        psThreadTaskRemove("PSLIB_IMAGE_CONVOLVE_MASK");
  • branches/pap/psLib/src/imageops/psImageConvolve.h

    r24272 r25337  
    222222    );
    223223
     224/// Smooth particular pixels on an image, allowing for masked pixels
     225///
     226/// Applies a circularly symmetric Gaussian smoothing first in x and then in y
     227/// directions with just a vector.  This process is 2N faster than 2D convolutions (in general).
     228psVector *psImageSmoothMaskPixels(
     229    const psImage *image,               ///< Input image (F32)
     230    const psImage *mask,                ///< Mask image
     231    psImageMaskType maskVal,            ///< Value to mask
     232    const psVector *x,                  ///< x coordinates
     233    const psVector *y,                  ///< y coordinates
     234    float sigma,                        ///< Width of the smoothing kernel (pixels)
     235    float numSigma,                     ///< Size of the smoothing box (sigma)
     236    float minGauss                      ///< Minimum fraction of Gaussian to accept
     237    );
    224238
    225239psImage *psImageSmoothMask_Threaded(psImage *output,
Note: See TracChangeset for help on using the changeset viewer.