Changeset 41868
- Timestamp:
- Oct 28, 2021, 7:54:55 AM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/eam_branches/psModules.20211015/src/imcombine/pmStack.c
r36710 r41868 1510 1510 } 1511 1511 1512 # define MIN_GOOD_PERCENTILE 2 1513 bool pmStackCombineByPercentile( 1514 pmReadout *combined, 1515 psArray *stackData, 1516 psF64 minRange, 1517 psF64 maxRange, 1518 psImageMaskType badMaskBits, // treat these bits as 'bad' 1519 psImageMaskType suspectMaskBits, // treat these bits as 'suspect' 1520 psImageMaskType blankMaskBits // use this mask value for pixels missing input data (distinguish between Ninput = 0 and Ngood = 0?) 1521 ) { 1522 int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine 1523 int xSize, ySize; // Size of the output image 1524 1525 // we need to copy the readouts to their own array for validation 1526 psArray *stackReadouts = psArrayAlloc(stackData->n); 1527 for (int i = 0; i < stackData->n; i++) { 1528 pmStackData *data = stackData->data[i]; // Stack data for this input 1529 pmReadout *ro = data->readout; // Readout of interest 1530 stackReadouts->data[i] = psMemIncrRefCounter(ro); 1531 } 1532 1533 if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize, stackReadouts)) { 1534 psError(psErrorCodeLast(), false, "Input stack is not valid."); 1535 psFree(stackReadouts); 1536 return false; 1537 } 1538 psFree(stackReadouts); 1539 1540 psVector *pixelData = psVectorAlloc(stackData->n, PS_TYPE_F32); 1541 psVector *pixelMask = psVectorAlloc(stackData->n, PS_TYPE_VECTOR_MASK); 1542 1543 for (int y = minInputRows; y < maxInputRows; y++) { 1544 for (int x = minInputCols; x < maxInputCols; x++) { 1545 1546 int nGood = 0; 1547 for (int i = 0; i < stackData->n; i++) { 1548 1549 pmStackData *data = stackData->data[i]; // Stack data for this input 1550 pmReadout *ro = data->readout; // Readout of interest 1551 psImage *image = ro->image; 1552 psImage *mask = ro->mask; 1553 1554 int xIn = x - data->readout->col0; 1555 int yIn = y - data->readout->row0; // Coordinates on input readout 1556 1557 if (!isfinite(image->data.F32[yIn][xIn])) continue; 1558 if (fabs(image->data.F32[yIn][xIn]) > 1e5) continue; 1559 // XXX need to test the input mask as well here 1560 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & badMaskBits) continue; 1561 1562 // XXX save the count of suspect bits 1563 1564 # if (0) 1565 // count the number of times a given mask bit is set in the input pixels. 1566 // NOTE: since we have explicitly skipped the pixels with any bad bits, these are only 1567 // the suspect bits (nGoodBits is a bit of a misnomer: it is more like 'nSuspectBitsForGoodInputs' 1568 if (1) { 1569 psImageMaskType value = 0x0001; 1570 for (int nbit = 0; nbit < 16; nbit ++) { 1571 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) { 1572 // XXX nGoodBits[nbit] ++; 1573 } 1574 value <<= 1; 1575 } 1576 } 1577 # endif 1578 1579 pixelData->data.F32[nGood] = image->data.F32[yIn][xIn]; 1580 nGood ++; 1581 } 1582 pixelData->n = nGood; 1583 psVectorSortInPlace (pixelData); 1584 1585 if (nGood < MIN_GOOD_PERCENTILE) { 1586 combined->image->data.F32[y][x] = NAN; 1587 combined->variance->data.F32[y][x] = NAN; 1588 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 1; 1589 continue; 1590 } 1591 1592 # if (0) 1593 # define SUSPECT_FRACTION 0.65 1594 // set the mask bits if nGoodBits[i] > f*numGood 1595 if (0) { 1596 psImageMaskType value = 0x0001; 1597 for (int nbit = 0; nbit < 16; nbit ++) { 1598 if (nGoodBits[nbit] > SUSPECT_FRACTION*numGood) { 1599 *goodMask |= value; 1600 } 1601 value <<= 1; 1602 } 1603 } 1604 # endif 1605 1606 int Ns = MIN(MAX(0, minRange * nGood),nGood); // e.g., 0.1 * 50 = 5 1607 int Ne = MIN(MAX(0, maxRange * nGood),nGood); // e.g., 0.9 * 50 = 45 1608 int Npt = Ne - Ns; 1609 1610 float sum = 0.0; 1611 for (int n = Ns; n < Ne; n++) { 1612 sum += pixelData->data.F32[n]; 1613 } 1614 float mean = sum / (float) Npt; 1615 1616 float varSum = 0.0; 1617 for (int n = Ns; n < Ne; n++) { 1618 varSum += SQ(pixelData->data.F32[n] - mean); 1619 } 1620 // variance on the mean (stdev / sqrt(N))^2 1621 float varValue = varSum / (Npt - 1) / Npt; 1622 1623 // XXX this is probably not the correct variance to save 1624 // the predicted variance should be the 1 / sum (1/var) 1625 1626 combined->image->data.F32[y][x] = mean; 1627 combined->variance->data.F32[y][x] = varValue; 1628 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0; 1629 } 1630 } 1631 1632 psFree(pixelData); 1633 psFree(pixelMask); 1634 1635 return (true); 1636 } 1637 1638 # define MIN_GOOD_PERCENTILE 2 1639 bool pmStackCombineByPercentile( 1640 pmReadout *combined, 1641 psArray *stackData, 1642 psF64 minRange, 1643 psF64 maxRange, 1644 psImageMaskType badMaskBits, // treat these bits as 'bad' 1645 psImageMaskType suspectMaskBits, // treat these bits as 'suspect' 1646 psImageMaskType blankMaskBits // use this mask value for pixels missing input data (distinguish between Ninput = 0 and Ngood = 0?) 1647 ) { 1648 int minInputCols, maxInputCols, minInputRows, maxInputRows; // Smallest and largest values to combine 1649 int xSize, ySize; // Size of the output image 1650 1651 // we need to copy the readouts to their own array for validation 1652 psArray *stackReadouts = psArrayAlloc(stackData->n); 1653 for (int i = 0; i < stackData->n; i++) { 1654 pmStackData *data = stackData->data[i]; // Stack data for this input 1655 pmReadout *ro = data->readout; // Readout of interest 1656 stackReadouts->data[i] = psMemIncrRefCounter(ro); 1657 } 1658 1659 if (!pmReadoutStackValidate(&minInputCols, &maxInputCols, &minInputRows, &maxInputRows, &xSize, &ySize, stackReadouts)) { 1660 psError(psErrorCodeLast(), false, "Input stack is not valid."); 1661 psFree(stackReadouts); 1662 return false; 1663 } 1664 psFree(stackReadouts); 1665 1666 psVector *pixelData = psVectorAlloc(stackData->n, PS_TYPE_F32); 1667 psVector *pixelMask = psVectorAlloc(stackData->n, PS_TYPE_VECTOR_MASK); 1668 1669 for (int y = minInputRows; y < maxInputRows; y++) { 1670 for (int x = minInputCols; x < maxInputCols; x++) { 1671 1672 int nGood = 0; 1673 for (int i = 0; i < stackData->n; i++) { 1674 1675 pmStackData *data = stackData->data[i]; // Stack data for this input 1676 pmReadout *ro = data->readout; // Readout of interest 1677 psImage *image = ro->image; 1678 psImage *mask = ro->mask; 1679 1680 int xIn = x - data->readout->col0; 1681 int yIn = y - data->readout->row0; // Coordinates on input readout 1682 1683 if (!isfinite(image->data.F32[yIn][xIn])) continue; 1684 if (fabs(image->data.F32[yIn][xIn]) > 1e5) continue; 1685 // XXX need to test the input mask as well here 1686 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & badMaskBits); 1687 1688 // XXX save the count of suspect bits 1689 1690 # if (0) 1691 // count the number of times a given mask bit is set in the input pixels. 1692 // NOTE: since we have explicitly skipped the pixels with any bad bits, these are only 1693 // the suspect bits (nGoodBits is a bit of a misnomer: it is more like 'nSuspectBitsForGoodInputs' 1694 if (1) { 1695 psImageMaskType value = 0x0001; 1696 for (int nbit = 0; nbit < 16; nbit ++) { 1697 if (mask->data.PS_TYPE_IMAGE_MASK_DATA[yIn][xIn] & value) { 1698 // XXX nGoodBits[nbit] ++; 1699 } 1700 value <<= 1; 1701 } 1702 } 1703 # endif 1704 1705 pixelData->data.F32[nGood] = image->data.F32[yIn][xIn]; 1706 nGood ++; 1707 } 1708 pixelData->n = nGood; 1709 psVectorSortInPlace (pixelData); 1710 1711 if (nGood < MIN_GOOD_PERCENTILE) { 1712 combined->image->data.F32[y][x] = NAN; 1713 combined->variance->data.F32[y][x] = NAN; 1714 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 1; 1715 continue; 1716 } 1717 1718 # if (0) 1719 # define SUSPECT_FRACTION 0.65 1720 // set the mask bits if nGoodBits[i] > f*numGood 1721 if (0) { 1722 psImageMaskType value = 0x0001; 1723 for (int nbit = 0; nbit < 16; nbit ++) { 1724 if (nGoodBits[nbit] > SUSPECT_FRACTION*numGood) { 1725 *goodMask |= value; 1726 } 1727 value <<= 1; 1728 } 1729 } 1730 # endif 1731 1732 int Ns = MIN(MAX(0, minRange * nGood),nGood); // e.g., 0.1 * 50 = 5 1733 int Ne = MIN(MAX(0, maxRange * nGood),nGood); // e.g., 0.9 * 50 = 45 1734 int Npt = Ne - Ns; 1735 1736 float sum = 0.0; 1737 for (int n = Ns; n < Ne; n++) { 1738 sum += pixelData->data.F32[n]; 1739 } 1740 float mean = sum / (float) Npt; 1741 1742 float varSum = 0.0; 1743 for (int n = Ns; n < Ne; n++) { 1744 varSum += SQ(pixelData->data.F32[n] - mean); 1745 } 1746 // variance on the mean (stdev / sqrt(N))^2 1747 float varValue = varSum / (Npt - 1) / Npt; 1748 1749 // XXX this is probably not the correct variance to save 1750 // the predicted variance should be the 1 / sum (1/var) 1751 1752 combined->image->data.F32[y][x] = mean; 1753 combined->variance->data.F32[y][x] = varValue; 1754 combined->mask->data.PS_TYPE_IMAGE_MASK_DATA[y][x] = 0; 1755 } 1756 } 1757 1758 psFree(pixelData); 1759 psFree(pixelMask); 1760 1761 return (true); 1762 } 1763 1512 1764 /// Stack input images 1513 1765 bool pmStackCombine(
Note:
See TracChangeset
for help on using the changeset viewer.
