IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
May 3, 2010, 8:50:52 AM (16 years ago)
Author:
eugene
Message:

updates from trunk

Location:
branches/simtest_nebulous_branches
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/simtest_nebulous_branches

  • branches/simtest_nebulous_branches/psLib/src/imageops/psImageConvolve.c

    r24272 r27840  
    246246    return kernel;
    247247}
     248
     249bool psKernelTruncate(psKernel *kernel, float frac)
     250{
     251    PS_ASSERT_KERNEL_NON_NULL(kernel, false);
     252    PS_ASSERT_FLOAT_LARGER_THAN_OR_EQUAL(frac, 0.0, false);
     253    PS_ASSERT_FLOAT_LESS_THAN(frac, 1.0, false);
     254
     255    if (frac == 0.0) {
     256        // Nothing to do
     257        return true;
     258    }
     259
     260    int xMin = kernel->xMin, xMax = kernel->xMax, yMin = kernel->yMin, yMax = kernel->yMax; // Bounds
     261    int maxSize = PS_MAX(PS_MAX(PS_MAX(-xMin, xMax), -yMin), yMax); // Maximum size
     262
     263    // Determine the threshold
     264    // Summing absolute values because large negative deviations have power as well
     265    double sumKernel = 0.0;             // Sum of the kernel
     266    for (int y = yMin; y <= yMax; y++) {
     267        for (int x = xMin; x <= xMax; x++) {
     268            sumKernel += fabsf(kernel->kernel[y][x]);
     269        }
     270    }
     271
     272    float threshold = sumKernel * (1.0 - frac); // Threshold for truncation
     273
     274    // Find truncation size
     275    int truncate = 0;                     // Truncation radius
     276    for (int radius = 1; truncate == 0 && radius < maxSize; radius++) {
     277        int uMin = PS_MAX(-radius, xMin);
     278        int uMax = PS_MIN(radius, xMax);
     279        int vMin = PS_MAX(-radius, yMin);
     280        int vMax = PS_MIN(radius, yMax);
     281        int r2 = PS_SQR(radius);
     282        double sum = 0.0;
     283        for (int v = vMin; v <= vMax; v++) {
     284            int v2 = PS_SQR(v);
     285            for (int u = uMin; u <= uMax; u++) {
     286                int u2 = PS_SQR(u);
     287                if (u2 + v2 <= r2) {
     288                    sum += fabsf(kernel->kernel[v][u]);
     289                }
     290            }
     291        }
     292        if (sum > threshold) {
     293            // This is the truncation radius
     294            truncate = radius;
     295        }
     296    }
     297    if (truncate == maxSize) {
     298        // No truncation possible
     299        return true;
     300    }
     301
     302    // Truncate the kernel
     303    {
     304        int uMin = PS_MAX(-truncate, xMin);
     305        int uMax = PS_MIN(truncate, xMax);
     306        int vMin = PS_MAX(-truncate, yMin);
     307        int vMax = PS_MIN(truncate, yMax);
     308        int r2 = PS_SQR(truncate);
     309        for (int v = vMin; v <= vMax; v++) {
     310            int v2 = PS_SQR(v);
     311            for (int u = uMin; u <= uMax; u++) {
     312                int u2 = PS_SQR(u);
     313                if (u2 + v2 > r2) {
     314                    kernel->kernel[v][u] = 0.0;
     315                }
     316            }
     317        }
     318    }
     319    kernel->xMin = PS_MAX(-truncate, kernel->xMin);
     320    kernel->xMax = PS_MIN(truncate, kernel->xMax);
     321    kernel->yMin = PS_MAX(-truncate, kernel->yMin);
     322    kernel->yMax = PS_MIN(truncate, kernel->yMax);
     323
     324    return true;
     325    }
     326
     327
    248328
    249329psImage *psImageConvolveDirect(psImage *out, const psImage *in, const psKernel *kernel)
     
    678758}
    679759
     760static bool imageSmoothMaskPixels(psVector *out, const psImage *image, const psImage *mask,
     761                                  psImageMaskType maskVal, const psVector *x, const psVector *y,
     762                                  const psVector *gaussNorm, float minGauss, int size, int start, int stop)
     763{
     764    const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel
     765    int numCols = image->numCols, numRows = image->numRows; // Size of image
     766    int xLast = numCols - 1, yLast = numRows - 1; // Last index
     767    for (int i = start; i < stop; i++) {
     768        int xPix = x->data.S32[i], yPix = y->data.S32[i]; // Pixel coordinates for smoothing
     769
     770        int yMin = PS_MAX(yPix - size, 0);
     771        int yMax = PS_MIN(yPix + size, yLast);
     772        int xMin = PS_MAX(xPix - size, 0);
     773        int xMax = PS_MIN(xPix + size, xLast);
     774
     775        const float *yGauss = &gauss[yMin - yPix];
     776
     777        double ySumIG = 0.0, ySumG = 0.0;
     778        for (int v = yMin; v <= yMax; v++, yGauss++) {
     779            const float *xGauss = &gauss[xMin - xPix];
     780            double xSumIG = 0.0, xSumG = 0.0;
     781            const psImageMaskType *maskData = &mask->data.PS_TYPE_IMAGE_MASK_DATA[v][xMin];
     782            const psF32 *imageData = &image->data.F32[v][xMin];
     783            for (int u = xMin; u <= xMax; u++, xGauss++, imageData++, maskData++) {
     784                if (*maskData & maskVal) {
     785                    continue;
     786                }
     787                xSumIG += *imageData * *xGauss;
     788                xSumG += *xGauss;
     789            }
     790            if (xSumG > minGauss) {
     791                ySumIG += xSumIG * *yGauss;
     792                ySumG += xSumG * *yGauss;
     793            }
     794        }
     795
     796        out->data.F32[i] = ySumG > minGauss ? ySumIG / ySumG : NAN;
     797    }
     798
     799    return true;
     800}
     801
     802static bool psImageSmoothMaskPixelsThread(psThreadJob *job)
     803{
     804    PS_ASSERT_THREAD_JOB_NON_NULL(job, false);
     805    psAssert(job->args, "programming error: no job arguments");
     806    psAssert(job->args->n == 11, "programming error: wrong number of job arguments");
     807
     808    psVector *out = job->args->data[0]; // Output vector
     809    const psImage *image  = job->args->data[1]; // Input image
     810    const psImage *mask   = job->args->data[2]; // Input mask
     811    psImageMaskType maskVal = PS_SCALAR_VALUE(job->args->data[3], PS_TYPE_IMAGE_MASK_DATA);
     812    const psVector *x = job->args->data[4];
     813    const psVector *y = job->args->data[5];
     814    const psVector *gaussNorm = job->args->data[6];
     815    float minGauss = PS_SCALAR_VALUE(job->args->data[7], F32);
     816    int size = PS_SCALAR_VALUE(job->args->data[8], S32);
     817    int start = PS_SCALAR_VALUE(job->args->data[9], S32);
     818    int stop = PS_SCALAR_VALUE(job->args->data[10], S32);
     819    return imageSmoothMaskPixels(out, image, mask, maskVal, x, y, gaussNorm,
     820                                 minGauss, size, start, stop);
     821}
     822
     823
     824psVector *psImageSmoothMaskPixels(const psImage *image, const psImage *mask, psImageMaskType maskVal,
     825                                  const psVector *x, const psVector *y,
     826                                  float sigma, float numSigma, float minGauss)
     827{
     828    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
     829    PS_ASSERT_IMAGE_NON_NULL(mask, NULL);
     830    PS_ASSERT_IMAGE_TYPE(mask, PS_TYPE_IMAGE_MASK, NULL);
     831    PS_ASSERT_IMAGES_SIZE_EQUAL(image, mask, NULL);
     832    PS_ASSERT_VECTOR_NON_NULL(x, NULL);
     833    PS_ASSERT_VECTOR_TYPE(x, PS_TYPE_S32, NULL);
     834    PS_ASSERT_VECTOR_NON_NULL(y, NULL);
     835    PS_ASSERT_VECTOR_TYPE(y, PS_TYPE_S32, NULL);
     836    PS_ASSERT_VECTORS_SIZE_EQUAL(x, y, NULL);
     837
     838    int size = sigma * numSigma + 0.5;  // Half-size of kernel
     839
     840    int num = x->n;                     // Number of pixels to smooth
     841    psVector *out = psVectorAlloc(num, PS_TYPE_F32); // Output results
     842
     843    // Generate normalized gaussian
     844    IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32);
     845
     846    // Columns
     847    if (threaded) {
     848        int numThreads = psThreadPoolSize(); // Number of threads
     849        int delta = (numThreads) ? num / numThreads + 1 : num; // Block of cols to do at once
     850        for (int start = 0; start < num; start += delta) {
     851            int stop = PS_MIN(start + delta, num);  // End of block
     852
     853            psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS");
     854            psArrayAdd(job->args, 1, out);
     855            psArrayAdd(job->args, 1, (psImage*)image);
     856            psArrayAdd(job->args, 1, (psImage*)mask);
     857            PS_ARRAY_ADD_SCALAR(job->args, maskVal, PS_TYPE_IMAGE_MASK);
     858            psArrayAdd(job->args, 1, (psVector*)x);
     859            psArrayAdd(job->args, 1, (psVector*)y);
     860            psArrayAdd(job->args, 1, gaussNorm);
     861            PS_ARRAY_ADD_SCALAR(job->args, minGauss, PS_TYPE_F32);
     862            PS_ARRAY_ADD_SCALAR(job->args, size, PS_TYPE_S32);
     863            PS_ARRAY_ADD_SCALAR(job->args, start, PS_TYPE_S32);
     864            PS_ARRAY_ADD_SCALAR(job->args, stop, PS_TYPE_S32);
     865            if (!psThreadJobAddPending(job)) {
     866                psFree(job);
     867                psFree(gaussNorm);
     868                psFree(out);
     869                return NULL;
     870            }
     871            psFree(job);
     872        }
     873    } else if (!imageSmoothMaskPixels(out, image, mask, maskVal, x, y,
     874                                      gaussNorm, minGauss, size, 0, num)) {
     875        psError(PS_ERR_UNKNOWN, false, "Unable to smooth pixels.");
     876        psFree(gaussNorm);
     877        psFree(out);
     878        return NULL;
     879    }
     880
     881    if (threaded && !psThreadPoolWait(true)) {
     882        psError(PS_ERR_UNKNOWN, false, "Error waiting for threads.");
     883        psFree(gaussNorm);
     884        psFree(out);
     885        return NULL;
     886    }
     887
     888    psFree(gaussNorm);
     889    return out;
     890}
     891
     892
    680893// Smooth an image with masked pixels
    681894// The calculation and calcMask images are *deliberately* backwards (row,col instead of col,row or
     
    13251538    if (threaded) {
    13261539        int numThreads = psThreadPoolSize(); // Number of threads
    1327         int deltaRows = (numThreads) ? numRows / numThreads : numRows; // Block of rows to do at once
     1540        int deltaRows = (numThreads) ? numRows / numThreads + 1 : numRows; // Block of rows to do at once
    13281541        for (int start = 0; start < numRows; start += deltaRows) {
    1329             int stop = PS_MIN (start + deltaRows, numRows);  // end of row block
     1542            int stop = PS_MIN(start + deltaRows, numRows);  // end of row block
    13301543
    13311544            psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_CONVOLVE_MASK");
     
    13631576    if (threaded) {
    13641577        int numThreads = psThreadPoolSize(); // Number of threads
    1365         int deltaCols = (numThreads) ? numCols / numThreads : numCols; // Block of cols to do at once
     1578        int deltaCols = (numThreads) ? numCols / numThreads + 1 : numCols; // Block of cols to do at once
    13661579        for (int start = 0; start < numCols; start += deltaCols) {
    1367             int stop = PS_MIN (start + deltaCols, numCols);  // end of col block
     1580            int stop = PS_MIN(start + deltaCols, numCols);  // end of col block
    13681581
    13691582            psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_CONVOLVE_MASK");
     
    14861699            psFree(task);
    14871700        }
     1701        {
     1702            psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS", 9);
     1703            task->function = &psImageSmoothMaskPixelsThread;
     1704            psThreadTaskAdd(task);
     1705            psFree(task);
     1706        }
    14881707    } else if (!set && threaded) {
    14891708        psThreadTaskRemove("PSLIB_IMAGE_CONVOLVE_MASK");
Note: See TracChangeset for help on using the changeset viewer.