73 static inline void checkWarpingKernelParameter(
const SeparableKernel *p,
unsigned int ind,
double value) {
76 "bad ind argument in WarpingKernel::setKernelParameter()");
78 int ctr = p->getCtr()[ind];
79 int size = p->getDimensions()[ind];
81 if (ctr == (size - 1) / 2) {
82 if (value < -1e-6 || value > 1 + 1e-6) {
84 "bad coordinate in WarpingKernel::setKernelParameter()");
86 }
else if (ctr == (size + 1) / 2) {
87 if (value < -1 - 1e-6 || value > 1e-6) {
89 "bad coordinate in WarpingKernel::setKernelParameter()");
93 "bad ctr value in WarpingKernel::setKernelParameter()");
104 checkWarpingKernelParameter(
this, ind, value);
125 return 0.5 + (1.0 - (2.0 * fabs(this->
_params[0]))) * (0.5 - fabs(
x));
129 checkWarpingKernelParameter(
this, ind, value);
135 os <<
"_BilinearFunction1: ";
136 os << Function1<Kernel::Pixel>::toString(
prefix);
141 return std::make_shared<NearestWarpingKernel>();
146 return static_cast<double>((fabs(this->_params[0]) < 0.5) == (fabs(
x) < 0.5));
150 checkWarpingKernelParameter(
this, ind, value);
156 os <<
"_NearestFunction1: ";
157 os << Function1<Kernel::Pixel>::toString(
prefix);
163 struct LanczosKernelPersistenceHelper {
167 static LanczosKernelPersistenceHelper
const &get() {
168 static LanczosKernelPersistenceHelper
const instance;
172 LanczosKernelPersistenceHelper(LanczosKernelPersistenceHelper
const &) =
delete;
173 LanczosKernelPersistenceHelper(LanczosKernelPersistenceHelper &&) =
delete;
174 LanczosKernelPersistenceHelper &
operator=(LanczosKernelPersistenceHelper
const &) =
delete;
175 LanczosKernelPersistenceHelper &
operator=(LanczosKernelPersistenceHelper &&) =
delete;
178 LanczosKernelPersistenceHelper()
182 class :
public table::io::PersistableFactory {
184 table::io::CatalogVector
const &catalogs)
const override {
185 auto const &
keys = LanczosKernelPersistenceHelper::get();
188 afw::table::BaseRecord
const &record = catalogs.front().front();
190 return std::make_shared<LanczosWarpingKernel>(record.get(
keys.order));
194 } lanczosFactory(
"LanczosWarpingKernel");
197 class DefaultPersistableFactory :
public table::io::PersistableFactory {
199 table::io::CatalogVector
const &catalogs)
const override {
201 return std::make_shared<T>();
207 DefaultPersistableFactory<BilinearWarpingKernel> bilinearFactory(
"BilinearWarpingKernel");
208 DefaultPersistableFactory<NearestWarpingKernel> nearestFactory(
"NearestWarpingKernel");
213 auto const &
keys = LanczosKernelPersistenceHelper::get();
216 record->set(
keys.order, getOrder());
227 static const std::regex LanczosRE(
"lanczos(\\d+)");
228 if (
name ==
"bilinear") {
234 }
else if (
name ==
"nearest") {
242 if (_warpingKernelPtr->getCacheSize() != _cacheSize) {
243 _warpingKernelPtr->computeCache(_cacheSize);
245 return _warpingKernelPtr;
250 setWarpingKernel(*warpingKernelPtr);
254 if (_maskWarpingKernelPtr) {
255 _testWarpingKernels(warpingKernel, *_maskWarpingKernelPtr);
258 std::static_pointer_cast<SeparableKernel>(warpingKernel.
clone()));
259 _warpingKernelPtr = warpingKernelPtr;
263 if (_maskWarpingKernelPtr) {
264 if (_maskWarpingKernelPtr->getCacheSize() != _cacheSize) {
265 _maskWarpingKernelPtr->computeCache(_cacheSize);
268 return _maskWarpingKernelPtr;
272 if (!maskWarpingKernelName.
empty()) {
274 setMaskWarpingKernel(*maskWarpingKernelPtr);
276 _maskWarpingKernelPtr.reset();
281 _testWarpingKernels(*_warpingKernelPtr, maskWarpingKernel);
282 _maskWarpingKernelPtr = std::static_pointer_cast<SeparableKernel>(maskWarpingKernel.
clone());
285 void WarpingControl::_testWarpingKernels(
SeparableKernel const &warpingKernel,
293 if (!kernelBBox.
contains(maskKernelBBox)) {
295 "warping kernel is smaller than mask warping kernel");
301 struct WarpingControlPersistenceHelper {
310 static WarpingControlPersistenceHelper
const &get() {
311 static WarpingControlPersistenceHelper
const instance;
315 WarpingControlPersistenceHelper(WarpingControlPersistenceHelper
const &) =
delete;
316 WarpingControlPersistenceHelper(WarpingControlPersistenceHelper &&) =
delete;
317 WarpingControlPersistenceHelper &
operator=(WarpingControlPersistenceHelper
const &) =
delete;
318 WarpingControlPersistenceHelper &
operator=(WarpingControlPersistenceHelper &&) =
delete;
321 WarpingControlPersistenceHelper()
324 schema.addField<int>(
"warpingKernelIndex",
"archive ID of nested warping kernel")),
325 hasMaskKernel(
schema.addField<table::Flag>(
"hasMaskKernel",
"whether a mask kernel is stored")),
327 "archive ID of nested mask kernel. "
328 "Valid only if hasMaskKernel")),
329 cacheSize(
schema.addField<int>(
"cacheSize",
"Cache size for warping kernel(s)")),
331 "Distance over which WCS can be linearly interpolated")),
333 "growFullMask",
"bits to grow to full width of image/variance kernel")) {}
336 std::string _getWarpingControlPersistenceName() {
return "WarpingControl"; }
338 class :
public table::io::PersistableFactory {
340 table::io::CatalogVector
const &catalogs)
const override {
341 auto const &
keys = WarpingControlPersistenceHelper::get();
344 afw::table::BaseRecord
const &record = catalogs.front().front();
348 auto control = std::make_shared<WarpingControl>(
"bilinear",
"", record.get(
keys.cacheSize),
349 record.get(
keys.interpLength),
350 record.get(
keys.growFullMask));
354 control->setWarpingKernel(*archive.get<
SeparableKernel>(record.get(
keys.warpingKernelIndex)));
355 if (record.get(
keys.hasMaskKernel)) {
356 control->setMaskWarpingKernel(*archive.get<
SeparableKernel>(record.get(
keys.maskKernelIndex)));
362 } controlFactory(_getWarpingControlPersistenceName());
371 return _warpingKernelPtr->isPersistable() &&
372 (!hasMaskWarpingKernel() || _maskWarpingKernelPtr->isPersistable());
376 auto const &
keys = WarpingControlPersistenceHelper::get();
380 record->set(
keys.warpingKernelIndex, handle.
put(_warpingKernelPtr));
381 record->set(
keys.hasMaskKernel, hasMaskWarpingKernel());
382 if (hasMaskWarpingKernel()) {
383 record->set(
keys.maskKernelIndex, handle.
put(_maskWarpingKernelPtr));
385 record->set(
keys.cacheSize, _cacheSize);
386 record->set(
keys.interpLength, _interpLength);
387 record->set(
keys.growFullMask, _growFullMask);
392 template <
typename DestExposureT,
typename SrcExposureT>
394 typename DestExposureT::MaskedImageT::SinglePixel padValue) {
395 if (!destExposure.hasWcs()) {
398 if (!srcExposure.hasWcs()) {
401 typename DestExposureT::MaskedImageT mi = destExposure.getMaskedImage();
402 destExposure.setPhotoCalib(srcExposure.getPhotoCalib());
403 destExposure.setFilterLabel(srcExposure.getFilterLabel());
404 destExposure.getInfo()->setVisitInfo(srcExposure.getInfo()->getVisitInfo());
405 return warpImage(mi, *destExposure.getWcs(), srcExposure.getMaskedImage(), *srcExposure.getWcs(), control,
415 geom::SkyWcs
const &destWcs,
416 geom::SkyWcs
const &srcWcs)
420 return srcWcs.skyToPixel(destWcs.pixelToSky(destPix));
423 inline double computeRelativeArea(
432 return std::abs(dSrcA.getX() * dSrcB.getY() - dSrcA.getY() * dSrcB.getX());
437 template <
typename DestImageT,
typename SrcImageT>
438 int warpImage(DestImageT &destImage, geom::SkyWcs
const &destWcs, SrcImageT
const &srcImage,
440 typename DestImageT::SinglePixel padValue) {
442 return warpImage(destImage, srcImage, *srcToDest, control, padValue);
445 template <
typename DestImageT,
typename SrcImageT>
446 int warpImage(DestImageT &destImage, SrcImageT
const &srcImage,
448 typename DestImageT::SinglePixel padValue) {
458 warpingKernelPtr->shrinkBBox(srcImage.getBBox(
image::LOCAL));
460 for (
int y = 0, height = destImage.getHeight();
y < height; ++
y) {
461 for (
typename DestImageT::x_iterator destPtr = destImage.row_begin(
y),
end = destImage.row_end(
y);
462 destPtr !=
end; ++destPtr) {
471 std::dynamic_pointer_cast<LanczosWarpingKernel>(warpingKernelPtr);
473 int numGoodPixels = 0;
476 auto const parentDestToParentSrc = srcToDest.inverted();
477 std::vector<double> const localDestToParentDestVec = {
static_cast<double>(destImage.getX0()),
478 static_cast<double>(destImage.getY0())};
480 auto const localDestToParentSrc = localDestToParentDest.then(*parentDestToParentSrc);
483 int const srcWidth = srcImage.getWidth();
484 int const srcHeight = srcImage.getHeight();
485 LOGL_DEBUG(
"TRACE2.afw.math.warp",
"source image width=%d; height=%d", srcWidth, srcHeight);
487 int const destWidth = destImage.getWidth();
488 int const destHeight = destImage.getHeight();
489 LOGL_DEBUG(
"TRACE2.afw.math.warp",
"remap image width=%d; height=%d", destWidth, destHeight);
492 LOGL_DEBUG(
"TRACE3.afw.math.warp",
"Remapping masked image");
494 int const maxCol = destWidth - 1;
495 int const maxRow = destHeight - 1;
504 int const numColEdges = 2 + ((destWidth - 1) /
interpLength);
509 edgeColList.
reserve(numColEdges);
514 invWidthList.
reserve(numColEdges);
519 for (
int prevEndCol = -1; prevEndCol < maxCol; prevEndCol +=
interpLength) {
521 if (endCol > maxCol) {
525 assert(endCol - prevEndCol > 0);
526 invWidthList.
push_back(1.0 /
static_cast<double>(endCol - prevEndCol));
528 assert(edgeColList.
back() == maxCol);
543 endColPosList.
reserve(numColEdges);
546 for (
int endCol : edgeColList) {
549 auto rightSrcPosList = localDestToParentSrc->applyForward(endColPosList);
550 srcPosView[-1] = rightSrcPosList[0];
551 for (
int colBand = 1, endBand = edgeColList.
size(); colBand < endBand; ++colBand) {
552 int const prevEndCol = edgeColList[colBand - 1];
553 int const endCol = edgeColList[colBand];
557 (rightSrcPosList[colBand] - leftSrcPos) * invWidthList[colBand];
559 for (
int col = prevEndCol + 1;
col <= endCol; ++
col) {
560 srcPosView[
col] = srcPosView[
col - 1] + xDeltaSrcPos;
565 while (endRow < maxRow) {
568 int prevEndRow = endRow;
570 if (endRow > maxRow) {
573 assert(endRow - prevEndRow > 0);
574 double interpInvHeight = 1.0 /
static_cast<double>(endRow - prevEndRow);
579 for (
int endCol : edgeColList) {
582 auto bottomSrcPosList = localDestToParentSrc->applyForward(destRowPosList);
583 for (
int colBand = 0, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
584 int endCol = edgeColList[colBand];
585 yDeltaSrcPosList[colBand] =
586 (bottomSrcPosList[colBand] - srcPosView[endCol]) * interpInvHeight;
589 for (
int row = prevEndRow + 1;
row <= endRow; ++
row) {
590 typename DestImageT::x_iterator destXIter = destImage.row_begin(
row);
591 srcPosView[-1] += yDeltaSrcPosList[0];
592 for (
int colBand = 1, endBand = edgeColList.size(); colBand < endBand; ++colBand) {
595 int const prevEndCol = edgeColList[colBand - 1];
596 int const endCol = edgeColList[colBand];
605 for (
int col = prevEndCol + 1;
col <= endCol; ++
col, ++destXIter) {
608 double relativeArea = computeRelativeArea(srcPos, leftSrcPos, srcPosView[
col]);
610 srcPosView[
col] = srcPos;
613 destXIter, srcPos, relativeArea,
628 destPosList.
reserve(1 + destWidth);
629 for (
int col = -1;
col < destWidth; ++
col) {
632 auto prevSrcPosList = localDestToParentSrc->applyForward(destPosList);
634 for (
int row = 0;
row < destHeight; ++
row) {
636 for (
int col = -1;
col < destWidth; ++
col) {
639 auto srcPosList = localDestToParentSrc->applyForward(destPosList);
641 typename DestImageT::x_iterator destXIter = destImage.row_begin(
row);
642 for (
int col = 0;
col < destWidth; ++
col, ++destXIter) {
644 auto srcPos = srcPosList[
col + 1];
645 double relativeArea =
646 computeRelativeArea(srcPos, prevSrcPosList[
col], prevSrcPosList[
col + 1]);
648 if (warpAtOnePoint(destXIter, srcPos, relativeArea,
655 swap(srcPosList, prevSrcPosList);
659 return numGoodPixels;
662 template <
typename DestImageT,
typename SrcImageT>
666 typename DestImageT::SinglePixel padValue) {
668 if ((destImage.getWidth() != srcImage.getWidth()) || (destImage.getHeight() != srcImage.getHeight()) ||
669 (destImage.getXY0() != srcImage.getXY0())) {
671 errStream <<
"src and dest images must have same size and xy0.";
676 SrcImageT srcImageCopy(srcImage,
true);
677 srcImageCopy.setXY0(0, 0);
678 destImage.setXY0(0, 0);
690 static float t = 0.0;
691 float t_before = 1.0*clock()/CLOCKS_PER_SEC;
692 int n =
warpImage(destImage, srcImageCopy, affTran, control, padValue);
693 float t_after = 1.0*clock()/CLOCKS_PER_SEC;
694 float dt = t_after - t_before;
696 std::cout <<srcImage.getWidth()<<
"x"<<srcImage.getHeight()<<
": "<< dt <<
" "<< t <<
std::endl;
698 int n =
warpImage(destImage, srcImageCopy, *affineTransform22, control, padValue);
702 destImage.setXY0(srcImage.getXY0());
712 #define EXPOSURE(PIXTYPE) image::Exposure<PIXTYPE, image::MaskPixel, image::VariancePixel>
713 #define MASKEDIMAGE(PIXTYPE) image::MaskedImage<PIXTYPE, image::MaskPixel, image::VariancePixel>
714 #define IMAGE(PIXTYPE) image::Image<PIXTYPE>
717 #define INSTANTIATE(DESTIMAGEPIXELT, SRCIMAGEPIXELT) \
718 template int warpCenteredImage( \
719 IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage, \
720 lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const ¢erPosition, \
721 WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
722 NL template int warpCenteredImage( \
723 MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
724 lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const ¢erPosition, \
725 WarpingControl const &control, MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
726 NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, IMAGE(SRCIMAGEPIXELT) const &srcImage, \
727 geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \
728 IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
729 NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, \
730 MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, \
731 geom::TransformPoint2ToPoint2 const &srcToDest, WarpingControl const &control, \
732 MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
733 NL template int warpImage(IMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs, \
734 IMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs, \
735 WarpingControl const &control, IMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
736 NL template int warpImage(MASKEDIMAGE(DESTIMAGEPIXELT) & destImage, geom::SkyWcs const &destWcs, \
737 MASKEDIMAGE(SRCIMAGEPIXELT) const &srcImage, geom::SkyWcs const &srcWcs, \
738 WarpingControl const &control, \
739 MASKEDIMAGE(DESTIMAGEPIXELT)::SinglePixel padValue); \
740 NL template int warpExposure(EXPOSURE(DESTIMAGEPIXELT) & destExposure, \
741 EXPOSURE(SRCIMAGEPIXELT) const &srcExposure, WarpingControl const &control, \
742 EXPOSURE(DESTIMAGEPIXELT)::MaskedImageT::SinglePixel padValue);
table::Key< std::string > name
#define INSTANTIATE(FROMSYS, TOSYS)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
LSST DM logging module built on log4cxx.
#define LOGL_DEBUG(logger, message...)
Log a debug-level message using a varargs/printf style interface.
Implementation of the Photometric Calibration class.
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
ShiftMap is a linear Mapping which shifts each axis by a specified constant value.
std::string toString(std::string const &="") const override
Return string representation.
Kernel::Pixel operator()(double x) const override
Solve bilinear equation.
BilinearWarpingKernel & operator=(const BilinearWarpingKernel &)=delete
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
std::vector< double > _params
lsst::geom::Extent2I const getDimensions() const
Return the Kernel's dimensions (width, height)
lsst::geom::Point2I getCtr() const
Return index of kernel's center.
int getWidth() const
Return the Kernel's width.
Lanczos warping: accurate but slow and can introduce ringing artifacts.
int getOrder() const
get the order of the kernel
LanczosWarpingKernel(int order)
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Kernel::Pixel operator()(double x) const override
Solve nearest neighbor equation.
std::string toString(std::string const &="") const override
Return string representation.
Nearest neighbor warping: fast; good for undersampled data.
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
A kernel described by a pair of functions: func(x, y) = colFunc(x) * rowFunc(y)
std::shared_ptr< Kernel > clone() const override
Return a pointer to a deep copy of this kernel.
void setKernelParameter(unsigned int ind, double value) const override
Set one kernel parameter.
SeparableKernel()
Construct an empty spatially invariant SeparableKernel of size 0x0.
Parameters to control convolution.
void setWarpingKernel(SeparableKernel const &warpingKernel)
set the warping kernel
int getInterpLength() const
get the interpolation length (pixels)
std::string getPythonModule() const override
Return the fully-qualified Python module that should be imported to guarantee that its factory is reg...
void setWarpingKernelName(std::string const &warpingKernelName)
set the warping kernel by name
void setMaskWarpingKernelName(std::string const &maskWarpingKernelName)
set or clear the mask warping kernel by name
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
void setMaskWarpingKernel(SeparableKernel const &maskWarpingKernel)
set the mask warping kernel
std::shared_ptr< SeparableKernel > getWarpingKernel() const
get the warping kernel
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
std::shared_ptr< SeparableKernel > getMaskWarpingKernel() const
get the mask warping kernel
bool isPersistable() const noexcept override
Return true if this particular object can be persisted using afw::table::io.
A functor that computes one warped pixel.
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
Defines the fields and offsets for a table.
An object passed to Persistable::write to allow it to persist itself.
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
void saveEmpty()
Indicate that the object being persisted has no state, and hence will never call makeCatalog() or sav...
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
int put(Persistable const *obj, bool permissive=false)
Save an object to the archive and return a unique ID that can be used to retrieve it from an InputArc...
PersistableFactory(std::string const &name)
Constructor for the factory.
An integer coordinate rectangle.
bool contains(Point2I const &point) const noexcept
Return true if the box contains the point.
Reports invalid arguments.
T emplace_back(T... args)
void swap(CameraSys &a, CameraSys &b)
std::shared_ptr< TransformPoint2ToPoint2 > makeTransform(lsst::geom::AffineTransform const &affine)
Wrap an lsst::geom::AffineTransform as a Transform.
std::shared_ptr< TransformPoint2ToPoint2 > makeWcsPairTransform(SkyWcs const &src, SkyWcs const &dst)
A Transform obtained by putting two SkyWcs objects "back to back".
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects.
std::int32_t MaskPixel
default type for Masks and MaskedImage Masks
double indexToPosition(double ind)
Convert image index to image position.
bool imagesOverlap(ImageBase< T1 > const &image1, ImageBase< T2 > const &image2)
Return true if the pixels for two images or masks overlap in memory.
std::shared_ptr< SeparableKernel > makeWarpingKernel(std::string name)
Return a warping kernel given its name.
int warpCenteredImage(DestImageT &destImage, SrcImageT const &srcImage, lsst::geom::LinearTransform const &linearTransform, lsst::geom::Point2D const ¢erPosition, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an image with a LinearTranform about a specified point.
int warpImage(DestImageT &destImage, geom::SkyWcs const &destWcs, SrcImageT const &srcImage, geom::SkyWcs const &srcWcs, WarpingControl const &control, typename DestImageT::SinglePixel padValue=lsst::afw::math::edgePixel< DestImageT >(typename lsst::afw::image::detail::image_traits< DestImageT >::image_category()))
Warp an Image or MaskedImage to a new Wcs.
int warpExposure(DestExposureT &destExposure, SrcExposureT const &srcExposure, WarpingControl const &control, typename DestExposureT::MaskedImageT::SinglePixel padValue=lsst::afw::math::edgePixel< typename DestExposureT::MaskedImageT >(typename lsst::afw::image::detail::image_traits< typename DestExposureT::MaskedImageT >::image_category()))
Warp (remap) one exposure to another.
Extent< double, 2 > Extent2D
Angle abs(Angle const &a)
A base class for image defects.
afw::table::Key< std::string > warpingKernelName
typename ImageT::image_category image_category
table::Key< int > warpingKernelIndex
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override
table::Key< int > interpLength
table::Key< image::MaskPixel > growFullMask
table::Key< int > cacheSize
table::Key< int > maskKernelIndex
table::Key< table::Flag > hasMaskKernel