IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jul 3, 2013, 2:30:22 PM (13 years ago)
Author:
eugene
Message:

add new psMinimizeLMChi2 function with new convergence criterion; add threaded version of psImageSmoothNoMask

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/imageops/psImageConvolve.c

    r34724 r35767  
    12311231}
    12321232
     1233/*********************** smooth with mask, threaded version ***********************/
     1234
    12331235bool psImageSmoothMask_ScanRows_F32(psImage *calculation, psImage *calcMask, const psImage *image,
    12341236                                    const psImage *mask, psImageMaskType maskVal, psVector *gaussNorm,
     
    14841486
    14851487
     1488/*********************** smooth no-mask ***********************/
     1489
     1490bool psImageSmoothNoMask_ScanRows_F32(psImage *calculation, const psImage *image,
     1491                                      psVector *gaussNorm, float minGauss,
     1492                                      int size, int rowStart, int rowStop)
     1493{
     1494    const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel
     1495
     1496    int numCols = image->numCols;
     1497    int xLast = numCols - 1; // Last index
     1498
     1499    for (int j = rowStart; j < rowStop; j++) {
     1500        for (int i = 0; i < numCols; i++) {
     1501            int xMin = PS_MAX(i - size, 0);
     1502            int xMax = PS_MIN(i + size, xLast);
     1503            const psF32 *imageData = &image->data.F32[j][xMin];
     1504            int uMin = - PS_MIN(i, size); /* Minimum kernel index */
     1505            const psF32 *gaussData = &gauss[uMin];
     1506            double sumIG = 0.0, sumG = 0.0; /* Sums for convolution */
     1507            for (int x = xMin; x <= xMax; x++, imageData++, gaussData++) {
     1508                sumIG += *imageData * *gaussData;
     1509                sumG += *gaussData;
     1510            }
     1511            if (sumG > minGauss) {
     1512                /* BW */
     1513                calculation->data.F32[i][j] = sumIG / sumG;
     1514            }
     1515        }
     1516    }
     1517    return true;
     1518}
     1519
     1520bool psImageSmoothNoMask_ScanCols_F32(psImage *output, psImage *calculation,
     1521                                      psVector *gaussNorm, float minGauss,
     1522                                      int size, int colStart, int colStop)
     1523{
     1524    const psF32 *gauss = &gaussNorm->data.F32[size]; // Gaussian convolution kernel
     1525
     1526    int numRows = output->numRows;
     1527    int yLast = numRows - 1; // Last index
     1528
     1529    for (int i = colStart; i < colStop; i++) {
     1530        for (int j = 0; j < numRows; j++) {
     1531            int yMin = PS_MAX(j - size, 0);
     1532            int yMax = PS_MIN(j + size, yLast);
     1533            const psF32 *imageData = &calculation->data.F32[i][yMin]; /* BW */
     1534            int vMin = - PS_MIN(j, size); /* Minimum kernel index */
     1535            const psF32 *gaussData = &gauss[vMin];
     1536            double sumIG = 0.0, sumG = 0.0; /* Sums for convolution */
     1537            for (int y = yMin; y <= yMax; y++, imageData++, gaussData++) {
     1538                sumIG += *imageData * *gaussData;
     1539                sumG += *gaussData;
     1540            }
     1541            output->data.F32[j][i] = (sumG > minGauss) ? sumIG / sumG : NAN;
     1542        }
     1543    }
     1544    return true;
     1545}
     1546
     1547bool psImageSmoothNoMask_ScanRows_F32_Threaded(psThreadJob *job)
     1548{
     1549    PS_ASSERT_THREAD_JOB_NON_NULL(job, false);
     1550    psAssert (job->args, "programming error: job args not alloced?");
     1551    psAssert (job->args->n == 7, "programming error: job Nargs mismatch");
     1552
     1553    psImage *calculation  = job->args->data[0]; // calculation image
     1554    const psImage *image  = job->args->data[1]; // input image
     1555
     1556    psVector *gaussNorm   = job->args->data[2]; // gauss kernel
     1557    float minGauss        = PS_SCALAR_VALUE(job->args->data[3],F32);
     1558    int size              = PS_SCALAR_VALUE(job->args->data[4],S32);
     1559    int rowStart          = PS_SCALAR_VALUE(job->args->data[5],S32);
     1560    int rowStop           = PS_SCALAR_VALUE(job->args->data[6],S32);
     1561    return psImageSmoothNoMask_ScanRows_F32(calculation, image,
     1562                                          gaussNorm, minGauss, size,
     1563                                          rowStart, rowStop);
     1564}
     1565
     1566bool psImageSmoothNoMask_ScanCols_F32_Threaded(psThreadJob *job)
     1567{
     1568    PS_ASSERT_THREAD_JOB_NON_NULL(job, false);
     1569    psAssert (job->args, "programming error: job args not alloced?");
     1570    psAssert (job->args->n == 7, "programming error: job Nargs mismatch");
     1571
     1572    psImage *output       = job->args->data[0]; // input image
     1573    psImage *calculation  = job->args->data[1]; // calculation image
     1574
     1575    psVector *gaussNorm   = job->args->data[2]; // gauss kernel
     1576    float minGauss        = PS_SCALAR_VALUE(job->args->data[3],F32);
     1577    int size              = PS_SCALAR_VALUE(job->args->data[4],S32);
     1578    int colStart          = PS_SCALAR_VALUE(job->args->data[5],S32);
     1579    int colStop           = PS_SCALAR_VALUE(job->args->data[6],S32);
     1580    return psImageSmoothNoMask_ScanCols_F32(output, calculation,
     1581                                          gaussNorm, minGauss, size,
     1582                                          colStart, colStop);
     1583}
     1584
     1585psImage *psImageSmoothNoMask_Threaded(psImage *output, const psImage *image, float sigma, float numSigma, float minGauss)
     1586{
     1587    PS_ASSERT_IMAGE_NON_NULL(image, NULL);
     1588
     1589    int numCols = image->numCols, numRows = image->numRows; // Size of image
     1590
     1591    int nThreads = psThreadPoolSize();
     1592    int scanCols = nThreads ? (numCols / 4 / nThreads) : numCols;
     1593    int scanRows = nThreads ? (numRows / 4 / nThreads) : numRows;
     1594    int size = sigma * numSigma + 0.5;  // Half-size of kernel
     1595
     1596    // Generate normalized gaussian
     1597    psVector *gaussNorm = NULL;
     1598    IMAGE_SMOOTH_GAUSS(gaussNorm, size, sigma, F32);
     1599
     1600    switch (image->type.type) {
     1601        // Smooth an image with masked pixels
     1602        // The calculation and calcMask images are *deliberately* backwards (row,col instead of col,row or
     1603        // [col][row] instead of [row][col]) to optimise the iteration over rows; such instances are marked "BW"
     1604
     1605      case PS_TYPE_F32: {
     1606          psImage *calculation = psImageAlloc(numRows, numCols, PS_TYPE_F32); /* Calculation image; BW */
     1607
     1608          if (threaded) {
     1609              /** Smooth in X direction **/
     1610              for (int rowStart = 0; rowStart < numRows; rowStart+=scanRows) {
     1611                  int rowStop = PS_MIN (rowStart + scanRows, numRows);
     1612
     1613                  // allocate a job, construct the arguments for this job
     1614                  psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_SMOOTH_NOMASK_SCANROWS");
     1615                  psArrayAdd(job->args, 0, calculation);
     1616                  psArrayAdd(job->args, 0, (psImage *) image); // cast away const
     1617                  psArrayAdd(job->args, 0, gaussNorm);
     1618                  PS_ARRAY_ADD_SCALAR(job->args, minGauss, PS_TYPE_F32);
     1619                  PS_ARRAY_ADD_SCALAR(job->args, size,     PS_TYPE_S32);
     1620                  PS_ARRAY_ADD_SCALAR(job->args, rowStart, PS_TYPE_S32);
     1621                  PS_ARRAY_ADD_SCALAR(job->args, rowStop,  PS_TYPE_S32);
     1622                  // -> psImageSmoothNoMask_ScanRows_F32 (calculation, image, gauss, minGauss, size, rowStart, rowStop);
     1623
     1624                  // if threading is not active, we simply run the job and return
     1625                  if (!psThreadJobAddPending(job)) {
     1626                      psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
     1627                      psFree(calculation);
     1628                      psFree(gaussNorm);
     1629                      return false;
     1630                  }
     1631              }
     1632              // wait here for the threaded jobs to finish (NOP if threading is not active)
     1633              if (!psThreadPoolWait(true, true)) {
     1634                  psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
     1635                  psFree(calculation);
     1636                  psFree(gaussNorm);
     1637                  return false;
     1638              }
     1639          } else if (!psImageSmoothNoMask_ScanRows_F32(calculation, image, gaussNorm, minGauss, size, 0, numRows)) {
     1640              psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
     1641              psFree(calculation);
     1642              psFree(gaussNorm);
     1643              return false;
     1644          }
     1645
     1646          output = psImageRecycle(output, numCols, numRows, PS_TYPE_F32);
     1647
     1648          /** Smooth in Y direction  **/
     1649          if (threaded) {
     1650              for (int colStart = 0; colStart < numCols; colStart+=scanCols) {
     1651                  int colStop = PS_MIN (colStart + scanCols, numCols);
     1652
     1653                  // allocate a job, construct the arguments for this job
     1654                  psThreadJob *job = psThreadJobAlloc("PSLIB_IMAGE_SMOOTH_NOMASK_SCANCOLS");
     1655                  psArrayAdd(job->args, 0, output);
     1656                  psArrayAdd(job->args, 0, calculation);
     1657                  psArrayAdd(job->args, 0, gaussNorm);
     1658                  PS_ARRAY_ADD_SCALAR(job->args, minGauss, PS_TYPE_F32);
     1659                  PS_ARRAY_ADD_SCALAR(job->args, size,     PS_TYPE_S32);
     1660                  PS_ARRAY_ADD_SCALAR(job->args, colStart, PS_TYPE_S32);
     1661                  PS_ARRAY_ADD_SCALAR(job->args, colStop,  PS_TYPE_S32);
     1662                  // -> psImageSmoothMask_ScanCols_F32 (output, calculation, gauss, minGauss, size, colStart, colStop);
     1663
     1664                  // if threading is not active, we simply run the job and return
     1665                  if (!psThreadJobAddPending(job)) {
     1666                      psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
     1667                      psFree(calculation);
     1668                      psFree(gaussNorm);
     1669                      return false;
     1670                  }
     1671              }
     1672
     1673              // wait here for the threaded jobs to finish (NOP if threading is not active)
     1674              if (!psThreadPoolWait(true, true)) {
     1675                  psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
     1676                  psFree(calculation);
     1677                  psFree(gaussNorm);
     1678                  return false;
     1679              }
     1680          } else if (!psImageSmoothNoMask_ScanCols_F32(output, calculation, gaussNorm, minGauss, size, 0, numCols)) {
     1681              psError(PS_ERR_UNKNOWN, false, "Unable to smooth image");
     1682              psFree(calculation);
     1683              psFree(gaussNorm);
     1684              return false;
     1685          }
     1686
     1687          psFree(calculation);
     1688          psFree(gaussNorm);
     1689
     1690          return output;
     1691      }
     1692      default:
     1693        psFree(gaussNorm);
     1694        char *typeStr;
     1695        PS_TYPE_NAME(typeStr,image->type.type);
     1696        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
     1697                _("Specified psImage type, %s, is not supported."),
     1698                typeStr);
     1699        return false;
     1700    }
     1701
     1702    psAbort("Should never reach here.");
     1703    return false;
     1704}
     1705
     1706/****************************************************************************************/
     1707
    14861708bool psImageSmoothMaskF32(psImage *image, psImage *mask, psImageMaskType maskVal,
    14871709                          double  sigma, double  Nsigma)
     
    19002122        }
    19012123        {
     2124            psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_SMOOTH_NOMASK_SCANROWS", 7);
     2125            task->function = &psImageSmoothNoMask_ScanRows_F32_Threaded;
     2126            psThreadTaskAdd(task);
     2127            psFree(task);
     2128        }
     2129        {
     2130            psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_SMOOTH_NOMASK_SCANCOLS", 7);
     2131            task->function = &psImageSmoothNoMask_ScanCols_F32_Threaded;
     2132            psThreadTaskAdd(task);
     2133            psFree(task);
     2134        }
     2135        {
    19022136            psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS", 9);
    19032137            task->function = &psImageSmoothMaskPixelsThread;
     
    19092143        psThreadTaskRemove("PSLIB_IMAGE_SMOOTHMASK_SCANROWS");
    19102144        psThreadTaskRemove("PSLIB_IMAGE_SMOOTHMASK_SCANCOLS");
     2145        psThreadTaskRemove("PSLIB_IMAGE_SMOOTH_NOMASK_SCANROWS");
     2146        psThreadTaskRemove("PSLIB_IMAGE_SMOOTH_NOMASK_SCANCOLS");
    19112147        psThreadTaskRemove("PSLIB_IMAGE_SMOOTHMASK_PIXELS");
    19122148    }
Note: See TracChangeset for help on using the changeset viewer.