8 #ifndef META_OCEAN_CV_SEGMENTATION_SEED_SEGMENTATION_H
9 #define META_OCEAN_CV_SEGMENTATION_SEED_SEGMENTATION_H
28 namespace Segmentation
44 class OCEAN_CV_SEGMENTATION_EXPORT
Comfort
83 static unsigned int iterativeSeedSegmentation(
const Frame& frame,
Frame& mask,
const PixelPosition& seed,
const unsigned char localThreshold,
const unsigned char minimalGlobalThreshold,
const unsigned char maximalGlobalThreshold,
const unsigned int maximalIncreaseFactor,
PixelBoundingBox* boundingBox =
nullptr,
const bool setMaskFrameType =
false,
Worker* worker =
nullptr);
102 inline PixelCandidate(
const unsigned int x,
const unsigned int y,
const unsigned int reference);
108 inline unsigned int reference()
const;
122 static constexpr uint8_t unvisitedMaskValue_ = 0xFFu;
125 static constexpr uint8_t visitedMaskValue_ = 0x00u;
148 template <
typename T,
unsigned int tChannels>
149 static unsigned int seedSegmentation(
const T* frame, uint8_t* mask,
const unsigned int width,
const unsigned int height,
const unsigned int framePaddingElements,
const unsigned int maskPaddingElements,
const PixelPosition& seed,
const T localThreshold,
const T globalThreshold = T(0),
PixelBoundingBox* boundingBox =
nullptr);
175 template <
typename T,
unsigned int tChannels>
176 static unsigned int iterativeSeedSegmentation(
const T* frame, uint8_t* mask,
const unsigned int width,
const unsigned int height,
const unsigned int framePaddingElements,
const unsigned int maskPaddingElements,
const PixelPosition& seed,
const T localThreshold,
const T minimalGlobalThreshold,
const T maximalGlobalThreshold,
const unsigned int maximalIncreaseFactor,
PixelBoundingBox* boundingBox =
nullptr,
Worker* worker =
nullptr);
197 template <
unsigned int tChannels>
198 static unsigned int seedSegmentationArea8BitPerChannel(
const uint32_t* borderedIntegral,
const unsigned int width,
const unsigned int height,
const unsigned int integralBorder,
const unsigned int areaSize,
const unsigned int maskPaddingElements,
const PixelPosition& seed,
const unsigned char localThreshold,
const unsigned char globalThreshold, uint8_t* mask,
PixelBoundingBox* boundingBox =
nullptr);
212 template <
typename T,
unsigned int tChannels>
213 static inline bool ssdBelowThreshold(
const T* image0,
const T* image1,
const typename SquareValueTyper<T>::Type sqrThreshold);
226 template <
unsigned int tChannels>
227 static inline bool ssdBelowThreshold8BitPerChannel(
const unsigned int* borderedIntegral0,
const unsigned int* borderedIntegral1,
const unsigned int integralWidth,
const unsigned int size,
const unsigned int sqrThreshold);
232 reference_(reference)
242 template <
typename T,
unsigned int tChannels>
245 static_assert(tChannels != 0u,
"Invalid channel number!");
247 ocean_assert(frame !=
nullptr && mask !=
nullptr);
249 if (seed.
x() >= width || seed.
y() >= height)
254 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
255 const unsigned int maskStrideElements = width + maskPaddingElements;
263 stack.reserve(width * height / 32u);
265 unsigned int counter = 1u;
272 const unsigned int frameSeedOffset = seed.
y() * frameStrideElements + seed.
x() * tChannels;
274 stack.emplace_back(seed.
x(), seed.
y(), frameSeedOffset);
278 const SqrType sqrLocalThreshold = localThreshold * localThreshold;
279 const SqrType sqrGlobalThreshold = globalThreshold * globalThreshold;
281 while (!stack.empty())
286 const unsigned int maskTestOffset = pixel.
y() * maskStrideElements + pixel.
x();
287 const unsigned int frameTestOffset = pixel.
y() * frameStrideElements + pixel.
x() * tChannels;
291 && ssdBelowThreshold<T, tChannels>(frame + frameTestOffset, frame + pixel.
reference(), sqrLocalThreshold)
292 && (sqrGlobalThreshold == SqrType(0) || ssdBelowThreshold<T, tChannels>(frame + frameTestOffset, frame + frameSeedOffset, sqrGlobalThreshold)))
296 *boundingBox += pixel;
304 stack.emplace_back(pixel.
x(), pixel.
y() - 1u, frameTestOffset);
308 if (pixel.
y() + 1u < height && mask[maskTestOffset + maskStrideElements] !=
visitedMaskValue_)
310 stack.emplace_back(pixel.
x(), pixel.
y() + 1u, frameTestOffset);
316 stack.emplace_back(pixel.
x() - 1u, pixel.
y(), frameTestOffset);
322 stack.emplace_back(pixel.
x() + 1u, pixel.
y(), frameTestOffset);
332 template <
typename T,
unsigned int tChannels>
333 unsigned int SeedSegmentation::iterativeSeedSegmentation(
const T* frame, uint8_t* mask,
const unsigned int width,
const unsigned int height,
const unsigned int framePaddingElements,
const unsigned int maskPaddingElements,
const PixelPosition& seed,
const T localThreshold,
const T minimalGlobalThreshold,
const T maximalGlobalThreshold,
const unsigned int maximalIncreaseFactor,
PixelBoundingBox* boundingBox,
Worker* worker)
335 static_assert(tChannels != 0u,
"Invalid channel number!");
337 ocean_assert(frame !=
nullptr && mask !=
nullptr);
338 ocean_assert(width >= 1u && height >= 1u);
339 ocean_assert(seed.
x() < width && seed.
y() < height);
341 ocean_assert(minimalGlobalThreshold != T(0));
342 ocean_assert(minimalGlobalThreshold < maximalGlobalThreshold);
344 if (seed.
x() >= width || seed.
y() >= height || minimalGlobalThreshold > maximalGlobalThreshold)
351 stack.reserve((width * height) / 16u);
354 if (boundingBox ==
nullptr)
356 boundingBox = &tmpBoundingBox;
363 unsigned int maskPixelCounter = seedSegmentation<T, tChannels>(frame, mask, width, height, framePaddingElements, maskPaddingElements, seed, localThreshold, maximalGlobalThreshold, boundingBox);
368 uint8_t*
const secondMask = secondMaskFrame.
data<uint8_t>();
370 const unsigned int secondMaskPaddingElements = secondMaskFrame.
paddingElements();
374 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
375 const unsigned int secondMaskStrideElements = secondMaskFrame.
strideElements();
377 const unsigned int frameSeedOffset = seed.
y() * frameStrideElements + seed.
x() * tChannels;
380 unsigned int maximalIterationMaskPixelCounter = (
unsigned int)(-1);
382 for (T t = minimalGlobalThreshold + 1u; t <= maximalGlobalThreshold; ++t)
386 secondMaskFrame.
copy(0, 0, maskFrame);
389 unsigned int iterationMaskPixelCounter = maskPixelCounter;
391 borderPixels8.clear();
394 for (PixelPositions::const_iterator i = borderPixels8.begin(); i != borderPixels8.end(); ++i)
396 const unsigned int frameBorderOffset = i->y() * frameStrideElements + i->x() * tChannels;
397 const unsigned int secondMaskBorderOffset = i->y() * secondMaskStrideElements + i->x();
402 if (i->y() > 0u && secondMask[secondMaskBorderOffset - secondMaskStrideElements] !=
visitedMaskValue_)
404 stack.emplace_back(i->x(), i->y() - 1u, frameBorderOffset);
408 if (i->y() + 1u < height && secondMask[secondMaskBorderOffset + secondMaskStrideElements] !=
visitedMaskValue_)
410 stack.emplace_back(i->x(), i->y() + 1u, frameBorderOffset);
416 stack.emplace_back(i->x() - 1u, i->y(), frameBorderOffset);
420 if (i->x() + 1u < width && secondMask[secondMaskBorderOffset + 1u] !=
visitedMaskValue_)
422 stack.emplace_back(i->x() + 1u, i->y(), frameBorderOffset);
426 while (!stack.empty())
431 const unsigned int frameTestOffset = pixel.
y() * frameStrideElements + pixel.
x() * tChannels;
432 const unsigned int secondMaskTestOffset = pixel.
y() * secondMaskStrideElements + pixel.
x();
436 && ssdBelowThreshold<T, tChannels>(frame + frameTestOffset, frame + pixel.
reference(), sqrLocalThreshold)
437 && ssdBelowThreshold<T, tChannels>(frame + frameTestOffset, frame + frameSeedOffset, sqrIterationGlobalThreshold))
439 iterationBoundingBox += pixel;
443 if (pixel.
y() > 0 && secondMask[secondMaskTestOffset - secondMaskStrideElements] !=
visitedMaskValue_)
445 stack.emplace_back(pixel.
x(), pixel.
y() - 1u, frameTestOffset);
449 if (pixel.
y() + 1u < height && secondMask[secondMaskTestOffset + secondMaskStrideElements] !=
visitedMaskValue_)
451 stack.emplace_back(pixel.
x(), pixel.
y() + 1u, frameTestOffset);
457 stack.emplace_back(pixel.
x() - 1u, pixel.
y(), frameTestOffset);
461 if (pixel.
x() + 1u < width && secondMask[secondMaskTestOffset + 1u] !=
visitedMaskValue_)
463 stack.emplace_back(pixel.
x() + 1u, pixel.
y(), frameTestOffset);
466 ++iterationMaskPixelCounter;
470 if (iterationMaskPixelCounter <= maximalIterationMaskPixelCounter)
472 ocean_assert(iterationMaskPixelCounter >= maskPixelCounter);
473 maximalIterationMaskPixelCounter = max(iterationMaskPixelCounter + maximalIncreaseFactor * (iterationMaskPixelCounter - maskPixelCounter), iterationMaskPixelCounter * 105u / 100u);
475 maskPixelCounter = iterationMaskPixelCounter;
476 *boundingBox = iterationBoundingBox;
478 maskFrame.
copy(0, 0, secondMaskFrame);
486 return maskPixelCounter;
489 template <
unsigned int tChannels>
490 unsigned int SeedSegmentation::seedSegmentationArea8BitPerChannel(
const uint32_t* borderedIntegral,
const unsigned int width,
const unsigned int height,
const unsigned int integralBorder,
const unsigned int areaSize,
const unsigned int maskPaddingElements,
const PixelPosition& seed,
const unsigned char localThreshold,
const unsigned char globalThreshold, uint8_t* mask,
PixelBoundingBox* boundingBox)
492 static_assert(tChannels != 0u,
"Invalid channel number!");
494 ocean_assert(borderedIntegral !=
nullptr && mask !=
nullptr);
495 ocean_assert(integralBorder >= areaSize / 2u);
496 ocean_assert(areaSize % 2u == 1u);
498 if (seed.
x() >= width || seed.
y() >= height)
503 const unsigned int maskStrideElements = width + maskPaddingElements;
505 const unsigned int areaHalf = areaSize;
506 const unsigned int integralWidth = width + integralBorder * 2u + 1u;
514 stack.reserve((width * height) / 16u);
516 unsigned int counter = 1u;
519 if (boundingBox ==
nullptr)
521 boundingBox = &tmpBoundingBox;
526 const unsigned int integralIndex = ((seed.
y() + integralBorder - areaHalf) * integralWidth + seed.
x() + integralBorder - areaHalf) * tChannels;
528 stack.emplace_back(seed.
x(), seed.
y(), integralIndex);
530 const unsigned int sqrLocalThreshold = localThreshold * localThreshold;
531 const unsigned int sqrGlobalThreshold = globalThreshold * globalThreshold;
533 while (!stack.empty())
538 const unsigned int maskTestOffset = pixel.
y() * maskStrideElements + pixel.
x();
539 const unsigned int testIntegralIndex = ((pixel.
y() + integralBorder - areaHalf) * integralWidth + pixel.
x() + integralBorder - areaHalf) * tChannels;
543 && ssdBelowThreshold8BitPerChannel<tChannels>(borderedIntegral + testIntegralIndex, borderedIntegral + pixel.
reference(), integralWidth, areaSize, sqrLocalThreshold)
544 && (sqrGlobalThreshold == 0u || ssdBelowThreshold8BitPerChannel<tChannels>(borderedIntegral + testIntegralIndex, borderedIntegral + integralIndex, integralWidth, areaSize, sqrGlobalThreshold)))
546 *boundingBox += pixel;
553 stack.emplace_back(pixel.
x(), pixel.
y() - 1u, testIntegralIndex);
559 stack.emplace_back(pixel.
x(), pixel.
y() + 1u, testIntegralIndex);
565 stack.emplace_back(pixel.
x() - 1u, pixel.
y(), testIntegralIndex);
571 stack.emplace_back(pixel.
x() + 1u, pixel.
y(), testIntegralIndex);
581 template <
typename T,
unsigned int tChannels>
584 static_assert(tChannels != 0u,
"Invalid channel number!");
586 ocean_assert(image0 && image1);
587 ocean_assert(sqrThreshold <= 255u * 255u);
591 for (
unsigned int n = 0u; n < tChannels; ++n)
593 value = image0[n] - image1[n];
604 template <
unsigned int tChannels>
607 static_assert(tChannels != 0u,
"Invalid channel number!");
609 ocean_assert(borderedIntegral0 && borderedIntegral1);
610 ocean_assert(integralWidth >= 1u);
611 ocean_assert(size < integralWidth);
612 ocean_assert(sqrThreshold <= 255u * 255u);
614 const unsigned int sqrThresholdArea = sqrThreshold * size * size;
616 for (
unsigned int n = 0u; n < tChannels; ++n)
618 const int value0 = *(borderedIntegral0 + n) - *(borderedIntegral0 + tChannels * size + n) - *(borderedIntegral0 + tChannels * size * integralWidth + n) + *(borderedIntegral0 + tChannels * (size * integralWidth + size) + n);
619 const int value1 = *(borderedIntegral1 + n) - *(borderedIntegral1 + tChannels * size + n) - *(borderedIntegral1 + tChannels * size * integralWidth + n) + *(borderedIntegral1 + tChannels * (size * integralWidth + size) + n);
621 const int value = value0 - value1;
623 if ((
unsigned int)(value * value) > sqrThresholdArea)
T y() const
Returns the vertical coordinate position of this object.
Definition: PixelPosition.h:470
T x() const
Returns the horizontal coordinate position of this object.
Definition: PixelPosition.h:458
static void findBorderPixels8(const uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, PixelPositions &borderPixels, const PixelBoundingBox &boundingBox=PixelBoundingBox(), Worker *worker=nullptr, const uint8_t nonMaskValue=255u)
Determines all border pixels in an 8 bit mask frame for a 8-neighborhood.
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition: SeedSegmentation.h:45
static unsigned int seedSegmentation(const Frame &frame, Frame &mask, const PixelPosition &seed, const uint8_t localThreshold, const uint8_t globalThreshold=0, PixelBoundingBox *boundingBox=nullptr, const bool setMaskFrameType=false)
Determines the seed segmentation in a frame.
static unsigned int iterativeSeedSegmentation(const Frame &frame, Frame &mask, const PixelPosition &seed, const unsigned char localThreshold, const unsigned char minimalGlobalThreshold, const unsigned char maximalGlobalThreshold, const unsigned int maximalIncreaseFactor, PixelBoundingBox *boundingBox=nullptr, const bool setMaskFrameType=false, Worker *worker=nullptr)
Determines the seed segmentation in a frame within several iterations.
This class extends the pixel position by another parameter holding the pixel index of the reference p...
Definition: SeedSegmentation.h:93
unsigned int reference() const
Returns the absolute pixel position of the reference pixel.
Definition: SeedSegmentation.h:237
unsigned int reference_
Holds the position of the reference pixel.
Definition: SeedSegmentation.h:113
PixelCandidate(const unsigned int x, const unsigned int y, const unsigned int reference)
Creates a new pixel candidate object.
Definition: SeedSegmentation.h:230
This class implements basic seed-based segmentation functions.
Definition: SeedSegmentation.h:36
static unsigned int iterativeSeedSegmentation(const T *frame, uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelPosition &seed, const T localThreshold, const T minimalGlobalThreshold, const T maximalGlobalThreshold, const unsigned int maximalIncreaseFactor, PixelBoundingBox *boundingBox=nullptr, Worker *worker=nullptr)
Determines the seed segmentation in a frame within several iterations.
Definition: SeedSegmentation.h:333
static unsigned int seedSegmentation(const T *frame, uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelPosition &seed, const T localThreshold, const T globalThreshold=T(0), PixelBoundingBox *boundingBox=nullptr)
Determines the seed segmentation in a frame.
Definition: SeedSegmentation.h:243
static constexpr uint8_t unvisitedMaskValue_
Mask value for unvisited mask pixels.
Definition: SeedSegmentation.h:122
static bool ssdBelowThreshold8BitPerChannel(const unsigned int *borderedIntegral0, const unsigned int *borderedIntegral1, const unsigned int integralWidth, const unsigned int size, const unsigned int sqrThreshold)
Tests whether the SSD between two areas is below a given threshold.
Definition: SeedSegmentation.h:605
static constexpr uint8_t visitedMaskValue_
Mask value for visited mask pixels.
Definition: SeedSegmentation.h:125
static unsigned int seedSegmentationArea8BitPerChannel(const uint32_t *borderedIntegral, const unsigned int width, const unsigned int height, const unsigned int integralBorder, const unsigned int areaSize, const unsigned int maskPaddingElements, const PixelPosition &seed, const unsigned char localThreshold, const unsigned char globalThreshold, uint8_t *mask, PixelBoundingBox *boundingBox=nullptr)
Determines the seed segmentation in a frame while using a mean-area around each pixel to increase the...
Definition: SeedSegmentation.h:490
std::vector< PixelCandidate > PixelCandidates
Definition of a vector holding pixel candidate objects (will be used as stack).
Definition: SeedSegmentation.h:119
static bool ssdBelowThreshold(const T *image0, const T *image1, const typename SquareValueTyper< T >::Type sqrThreshold)
Tests whether all channel-wise SSD values between two pixels are below a given threshold.
Definition: SeedSegmentation.h:582
T Type
Definition of the data type for the signed difference value.
Definition: DataType.h:176
This class implements Ocean's image class.
Definition: Frame.h:1792
unsigned int strideElements(const unsigned int planeIndex=0u) const
Returns the number of elements within one row, including optional padding at the end of a row for a s...
Definition: Frame.h:4058
const FrameType & frameType() const
Returns the frame type of this frame.
Definition: Frame.h:3775
T * data(const unsigned int planeIndex=0u)
Returns a pointer to the pixel data of a specific plane.
Definition: Frame.h:4159
bool copy(const Frame &source, const bool copyTimestamp=true)
Deprecated.
@ CM_USE_KEEP_LAYOUT
The source memory is used only, no copy is created, the padding layout is preserved.
Definition: Frame.h:1801
bool setValue(const uint8_t value, const unsigned int planeIndex=0u, const bool skipPaddingData=true)
Sets the memory of the frame to a specified byte value (the memory of one plane).
unsigned int paddingElements(const unsigned int planeIndex=0u) const
Returns the optional number of padding elements at the end of each row for a specific plane.
Definition: Frame.h:4042
Definition of a frame type composed by the frame dimension, pixel format and pixel origin.
Definition: Frame.h:30
@ FORMAT_Y8
Pixel format for grayscale images with byte order Y and 8 bits per pixel.
Definition: Frame.h:594
@ ORIGIN_UPPER_LEFT
The first pixel lies in the upper left corner, the last pixel in the lower right corner.
Definition: Frame.h:1050
T Type
Definition of the data type for the square value.
Definition: DataType.h:132
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
std::vector< PixelPosition > PixelPositions
Definition of a vector holding pixel positions (with positive coordinate values).
Definition: PixelPosition.h:48
PixelBoundingBoxT< unsigned int > PixelBoundingBox
Definition of the default PixelBoundingBox object with data type allowing only positive coordinate va...
Definition: PixelBoundingBox.h:21
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15