Changeset 35767 for trunk/psLib/src/imageops/psImageConvolve.c
- Timestamp:
- Jul 3, 2013, 2:30:22 PM (13 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/imageops/psImageConvolve.c (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/imageops/psImageConvolve.c
r34724 r35767 1231 1231 } 1232 1232 1233 /*********************** smooth with mask, threaded version ***********************/ 1234 1233 1235 bool psImageSmoothMask_ScanRows_F32(psImage *calculation, psImage *calcMask, const psImage *image, 1234 1236 const psImage *mask, psImageMaskType maskVal, psVector *gaussNorm, … … 1484 1486 1485 1487 1488 /*********************** smooth no-mask ***********************/ 1489 1490 bool 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 1520 bool 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 1547 bool 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 1566 bool 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 1585 psImage *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 1486 1708 bool psImageSmoothMaskF32(psImage *image, psImage *mask, psImageMaskType maskVal, 1487 1709 double sigma, double Nsigma) … … 1900 2122 } 1901 2123 { 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 { 1902 2136 psThreadTask *task = psThreadTaskAlloc("PSLIB_IMAGE_SMOOTHMASK_PIXELS", 9); 1903 2137 task->function = &psImageSmoothMaskPixelsThread; … … 1909 2143 psThreadTaskRemove("PSLIB_IMAGE_SMOOTHMASK_SCANROWS"); 1910 2144 psThreadTaskRemove("PSLIB_IMAGE_SMOOTHMASK_SCANCOLS"); 2145 psThreadTaskRemove("PSLIB_IMAGE_SMOOTH_NOMASK_SCANROWS"); 2146 psThreadTaskRemove("PSLIB_IMAGE_SMOOTH_NOMASK_SCANCOLS"); 1911 2147 psThreadTaskRemove("PSLIB_IMAGE_SMOOTHMASK_PIXELS"); 1912 2148 }
Note:
See TracChangeset
for help on using the changeset viewer.
