129void Optimizer4NeighborhoodAreaConstrainedI1<tWeightFactor, tBorderFactor, tUpdateFrame>::optimizeSubsetChannels(
const unsigned int radii,
const unsigned int maxSpatialCost,
const unsigned int boundingBoxTop,
const unsigned int boundingBoxHeight,
const bool downIsMain,
const unsigned int firstColumn,
const unsigned int numberColumns,
const unsigned int rowOffset,
const unsigned int firstRow,
const unsigned int numberRows,
const unsigned int threadIndex)
const
131 const unsigned int layerWidth = layerI1_.width();
132 const unsigned int layerHeight = layerI1_.height();
133 ocean_assert(layerWidth != 0 && layerHeight != 0);
135 const std::vector<int> searchRadii(calculateSearchRadii(radii, layerWidth, layerHeight));
137 Frame& layerFrame = layerI1_.frame();
138 const Frame& layerMask = layerI1_.mask();
139 MappingI1& layerMapping = layerI1_.mapping();
141 ocean_assert(layerFrame.
width() == layerWidth);
142 ocean_assert(layerFrame.
height() == layerHeight);
147 ocean_assert(firstColumn + numberColumns <= layerFrame.
width());
148 ocean_assert(firstRow + numberRows <= layerFrame.
height());
152 uint8_t*
const layerFrameData = layerFrame.
data<uint8_t>();
153 const uint8_t*
const layerMaskData = layerMask.
constdata<uint8_t>();
154 const uint8_t*
const layerFilterData = filter_.constdata<uint8_t>();
156 const unsigned int layerFramePaddingElements = layerFrame.
paddingElements();
157 const unsigned int layerMaskPaddingElements = layerMask.
paddingElements();
158 const unsigned int layerMaskStrideElements = layerMask.
strideElements();
159 const unsigned int layerFilterStrideElements = filter_.strideElements();
163 ocean_assert(!debugLayerBoundingBox || firstRow >= debugLayerBoundingBox.
top());
164 ocean_assert(!debugLayerBoundingBox || firstRow + numberRows <= debugLayerBoundingBox.
bottomEnd());
167 const bool down = (downIsMain && (threadIndex % 2u) == 0u) || (!downIsMain && (threadIndex % 2u) == 1u);
169 const unsigned int xStart = firstColumn;
170 const unsigned int yStart = firstRow;
171 const unsigned int xEnd = firstColumn + numberColumns;
172 const unsigned int yEnd = firstRow + numberRows;
174 ocean_assert(xEnd - xStart <= layerWidth);
175 ocean_assert(yEnd - yStart <= layerHeight);
180 for (
unsigned int yy = yStart; yy < yEnd; ++yy)
182 const unsigned int y =
modulo(
int(yy + rowOffset - boundingBoxTop),
int(boundingBoxHeight)) + boundingBoxTop;
184 const uint8_t* maskRow = layerMask.
constrow<uint8_t>(y) + xStart;
187 for (
unsigned int x = xStart; x < xEnd; ++x)
189 bool foundBetter =
false;
191 ocean_assert(maskRow == layerMask.
constpixel<uint8_t>(x, y));
192 if (*maskRow != 0xFF)
194 unsigned int newPositionX = positionRow->x();
195 unsigned int newPositionY = positionRow->y();
197 const unsigned int oldSpatialCost = layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, newPositionX, newPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
198 const unsigned int oldColorCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, newPositionX, newPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
199 unsigned int newCost = tWeightFactor * oldSpatialCost + oldColorCost;
201 unsigned int testPositionX, testPositionY;
204 ocean_assert(x == 0 || maskRow - 1 == layerMask.
constpixel<uint8_t>(x - 1u, y));
205 if (x > 0 && *(maskRow - 1) != 0xFF)
207 ocean_assert(layerMapping.
position(x - 1, y));
208 ocean_assert(*(positionRow - 1) == layerMapping.
position(x - 1, y));
211 testPositionX = (positionRow - 1)->x() + 1;
212 testPositionY = (positionRow - 1)->y();
214 if (testPositionX < layerWidth && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
215 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
218 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
220 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
222 if (testCost < newCost)
224 newPositionX = testPositionX;
225 newPositionY = testPositionY;
232 ocean_assert(y == 0 || maskRow - layerMaskStrideElements == layerMask.
constpixel<uint8_t>(x, y - 1u));
233 if (y > 0 && *(maskRow - layerMaskStrideElements) != 0xFFu
235 && (positionRow - 1)->northEast() != *(positionRow - layerWidth))
237 ocean_assert(layerMapping.
position(x, y - 1));
238 ocean_assert(*(positionRow - layerWidth) == layerMapping.
position(x, y - 1));
241 testPositionX = (positionRow - layerWidth)->x();
242 testPositionY = (positionRow - layerWidth)->y() + 1;
244 if (testPositionY < layerHeight && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
245 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
248 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
250 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
252 if (testCost < newCost)
254 newPositionX = testPositionX;
255 newPositionY = testPositionY;
266 ocean_assert(y == 0 || maskRow - layerMaskStrideElements == layerMask.
constpixel<uint8_t>(x, y - 1u));
267 if (y > 0 && *(maskRow - layerMaskStrideElements) != 0xFFu)
269 ocean_assert(layerMapping.
position(x, y - 1));
270 ocean_assert(*(positionRow - layerWidth) == layerMapping.
position(x, y - 1));
273 testPositionX = (positionRow - layerWidth)->x();
274 testPositionY = (positionRow - layerWidth)->y() + 1;
276 if (testPositionY < layerHeight && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
277 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
280 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
282 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
284 if (testCost < newCost)
286 newPositionX = testPositionX;
287 newPositionY = testPositionY;
296 for (
unsigned int n = 0; n < radii; ++n)
298 ocean_assert(newPositionX != (
unsigned int)(-1) && newPositionY != (
unsigned int)(-1));
300 testPositionX = newPositionX +
RandomI::random(generator, -searchRadii[n], searchRadii[n]);
301 testPositionY = newPositionY +
RandomI::random(generator, -searchRadii[n], searchRadii[n]);
304 if ((testPositionX == newPositionX && testPositionY == newPositionY)
305 || testPositionX >= layerWidth || testPositionY >= layerHeight
306 || layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] != 0xFFu
307 || layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] != 0xFFu)
312 const unsigned int testSpatialCost = layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
313 const unsigned int testColorCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
314 const unsigned int testCost = tWeightFactor * testSpatialCost + testColorCost;
316 if (testCost < newCost)
318 newPositionX = testPositionX;
319 newPositionY = testPositionY;
325 if (tUpdateFrame && foundBetter)
327 ocean_assert(layerMask.
constpixel<uint8_t>(x, y)[0] != 0xFFu);
328 ocean_assert(layerMask.
constpixel<uint8_t>(newPositionX, newPositionY)[0] == 0xFFu);
330 positionRow->setPosition(newPositionX, newPositionY);
332 CV::CVUtilities::copyPixel<tChannels>(layerFrameData, layerFrameData, x, y, newPositionX, newPositionY, layerWidth, layerWidth, layerFramePaddingElements, layerFramePaddingElements);
344 for (
unsigned int yy = yEnd - 1u; yy != yStart - 1u; --yy)
346 const unsigned int y =
modulo(
int(yy + rowOffset - boundingBoxTop),
int(boundingBoxHeight)) + boundingBoxTop;
348 const uint8_t* maskRow = layerMask.
constrow<uint8_t>(y) + xEnd - 1u;
351 for (
unsigned int x = xEnd - 1u; x != xStart - 1u; --x)
353 bool foundBetter =
false;
355 ocean_assert(maskRow == layerMask.
constpixel<uint8_t>(x, y));
356 if (*maskRow != 0xFF)
358 unsigned int newPositionX = positionRow->x();
359 unsigned int newPositionY = positionRow->y();
361 const unsigned int oldSpatialCost = layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, newPositionX, newPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
362 const unsigned int oldColorCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, newPositionX, newPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
363 unsigned int newCost = tWeightFactor * oldSpatialCost + oldColorCost;
365 unsigned int testPositionX, testPositionY;
368 ocean_assert(x == layerWidth - 1u || (maskRow + 1) == layerMask.
constpixel<uint8_t>(x + 1u, y));
369 if (x < layerWidth - 1u && *(maskRow + 1) != 0xFF)
371 ocean_assert(layerMapping.
position(x + 1u, y));
372 ocean_assert(*(positionRow + 1) == layerMapping.
position(x + 1u, y));
375 testPositionX = (positionRow + 1)->x() - 1;
376 testPositionY = (positionRow + 1)->y();
378 if (testPositionX != (
unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
379 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
382 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
384 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
386 if (testCost < newCost)
388 newPositionX = testPositionX;
389 newPositionY = testPositionY;
396 ocean_assert(y == layerHeight - 1 || (maskRow + layerMaskStrideElements) == layerMask.
constpixel<uint8_t>(x, y + 1u));
397 if (y < layerHeight - 1 && *(maskRow + layerMaskStrideElements) != 0xFF
399 && (positionRow + 1)->southWest() != *(positionRow + layerWidth))
401 ocean_assert(layerMapping.
position(x, y + 1));
402 ocean_assert(*(positionRow + layerWidth) == layerMapping.
position(x, y + 1));
405 testPositionX = (positionRow + layerWidth)->x();
406 testPositionY = (positionRow + layerWidth)->y() - 1u;
408 if (testPositionY != (
unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
409 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
412 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
414 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
416 if (testCost < newCost)
418 newPositionX = testPositionX;
419 newPositionY = testPositionY;
429 ocean_assert(y == layerHeight - 1u || (maskRow + layerMaskStrideElements) == layerMask.
constpixel<uint8_t>(x, y + 1u));
430 if (y < layerHeight - 1u && *(maskRow + layerMaskStrideElements) != 0xFFu)
432 ocean_assert(layerMapping.
position(x, y + 1u));
433 ocean_assert(*(positionRow + layerWidth) == layerMapping.
position(x, y + 1u));
436 testPositionX = (positionRow + layerWidth)->x();
437 testPositionY = (positionRow + layerWidth)->y() - 1u;
439 if (testPositionY != (
unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
440 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
443 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
445 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
447 if (testCost < newCost)
449 newPositionX = testPositionX;
450 newPositionY = testPositionY;
459 for (
unsigned int n = 0; n < radii; ++n)
461 ocean_assert(newPositionX != (
unsigned int)(-1) && newPositionY != (
unsigned int)(-1));
463 testPositionX = newPositionX +
RandomI::random(generator, -searchRadii[n], searchRadii[n]);
464 testPositionY = newPositionY +
RandomI::random(generator, -searchRadii[n], searchRadii[n]);
466 if ((testPositionX == newPositionX && testPositionY == newPositionY)
467 || testPositionX >= layerWidth || testPositionY >= layerHeight
468 || layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] != 0xFFu
469 || layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] != 0xFFu)
474 const unsigned int testSpatialCost = layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
475 const unsigned int testColorCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
476 const unsigned int testCost = tWeightFactor * testSpatialCost + testColorCost;
478 if (testCost < newCost)
480 newPositionX = testPositionX;
481 newPositionY = testPositionY;
487 if (tUpdateFrame && foundBetter)
489 ocean_assert(layerMask.
constpixel<uint8_t>(x, y)[0] != 0xFFu);
490 ocean_assert(layerMask.
constpixel<uint8_t>(newPositionX, newPositionY)[0] == 0xFFu);
492 positionRow->setPosition(newPositionX, newPositionY);
494 CV::CVUtilities::copyPixel<tChannels>(layerFrameData, layerFrameData, x, y, newPositionX, newPositionY, layerWidth, layerWidth, layerFramePaddingElements, layerFramePaddingElements);