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) {
311 const unsigned int testSpatialCost = layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
312 const unsigned int testColorCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
313 const unsigned int testCost = tWeightFactor * testSpatialCost + testColorCost;
315 if (testCost < newCost)
317 newPositionX = testPositionX;
318 newPositionY = testPositionY;
324 if (tUpdateFrame && foundBetter)
326 ocean_assert(layerMask.
constpixel<uint8_t>(x, y)[0] != 0xFFu);
327 ocean_assert(layerMask.
constpixel<uint8_t>(newPositionX, newPositionY)[0] == 0xFFu);
329 positionRow->setPosition(newPositionX, newPositionY);
331 CV::CVUtilities::copyPixel<tChannels>(layerFrameData, layerFrameData, x, y, newPositionX, newPositionY, layerWidth, layerWidth, layerFramePaddingElements, layerFramePaddingElements);
343 for (
unsigned int yy = yEnd - 1u; yy != yStart - 1u; --yy)
345 const unsigned int y =
modulo(
int(yy + rowOffset - boundingBoxTop),
int(boundingBoxHeight)) + boundingBoxTop;
347 const uint8_t* maskRow = layerMask.
constrow<uint8_t>(y) + xEnd - 1u;
350 for (
unsigned int x = xEnd - 1u; x != xStart - 1u; --x)
352 bool foundBetter =
false;
354 ocean_assert(maskRow == layerMask.
constpixel<uint8_t>(x, y));
355 if (*maskRow != 0xFF)
357 unsigned int newPositionX = positionRow->x();
358 unsigned int newPositionY = positionRow->y();
360 const unsigned int oldSpatialCost = layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, newPositionX, newPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
361 const unsigned int oldColorCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, newPositionX, newPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
362 unsigned int newCost = tWeightFactor * oldSpatialCost + oldColorCost;
364 unsigned int testPositionX, testPositionY;
367 ocean_assert(x == layerWidth - 1u || (maskRow + 1) == layerMask.
constpixel<uint8_t>(x + 1u, y));
368 if (x < layerWidth - 1u && *(maskRow + 1) != 0xFF)
370 ocean_assert(layerMapping.
position(x + 1u, y));
371 ocean_assert(*(positionRow + 1) == layerMapping.
position(x + 1u, y));
374 testPositionX = (positionRow + 1)->x() - 1;
375 testPositionY = (positionRow + 1)->y();
377 if (testPositionX != (
unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
378 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
381 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
383 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
385 if (testCost < newCost)
387 newPositionX = testPositionX;
388 newPositionY = testPositionY;
395 ocean_assert(y == layerHeight - 1 || (maskRow + layerMaskStrideElements) == layerMask.
constpixel<uint8_t>(x, y + 1u));
396 if (y < layerHeight - 1 && *(maskRow + layerMaskStrideElements) != 0xFF
398 && (positionRow + 1)->southWest() != *(positionRow + layerWidth))
400 ocean_assert(layerMapping.
position(x, y + 1));
401 ocean_assert(*(positionRow + layerWidth) == layerMapping.
position(x, y + 1));
404 testPositionX = (positionRow + layerWidth)->x();
405 testPositionY = (positionRow + layerWidth)->y() - 1u;
407 if (testPositionY != (
unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
408 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
411 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
413 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
415 if (testCost < newCost)
417 newPositionX = testPositionX;
418 newPositionY = testPositionY;
428 ocean_assert(y == layerHeight - 1u || (maskRow + layerMaskStrideElements) == layerMask.
constpixel<uint8_t>(x, y + 1u));
429 if (y < layerHeight - 1u && *(maskRow + layerMaskStrideElements) != 0xFFu)
431 ocean_assert(layerMapping.
position(x, y + 1u));
432 ocean_assert(*(positionRow + layerWidth) == layerMapping.
position(x, y + 1u));
435 testPositionX = (positionRow + layerWidth)->x();
436 testPositionY = (positionRow + layerWidth)->y() - 1u;
438 if (testPositionY != (
unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
439 && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
442 ocean_assert(layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
444 const unsigned int testCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
446 if (testCost < newCost)
448 newPositionX = testPositionX;
449 newPositionY = testPositionY;
458 for (
unsigned int n = 0; n < radii; ++n)
460 ocean_assert(newPositionX != (
unsigned int)(-1) && newPositionY != (
unsigned int)(-1));
462 testPositionX = newPositionX +
RandomI::random(generator, -searchRadii[n], searchRadii[n]);
463 testPositionY = newPositionY +
RandomI::random(generator, -searchRadii[n], searchRadii[n]);
465 if ((testPositionX == newPositionX && testPositionY == newPositionY)
466 || testPositionX >= layerWidth || testPositionY >= layerHeight
467 || layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] != 0xFFu
468 || layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] != 0xFFu) {
472 const unsigned int testSpatialCost = layerMapping.
spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
473 const unsigned int testColorCost = layerMapping.
appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
474 const unsigned int testCost = tWeightFactor * testSpatialCost + testColorCost;
476 if (testCost < newCost)
478 newPositionX = testPositionX;
479 newPositionY = testPositionY;
485 if (tUpdateFrame && foundBetter)
487 ocean_assert(layerMask.
constpixel<uint8_t>(x, y)[0] != 0xFFu);
488 ocean_assert(layerMask.
constpixel<uint8_t>(newPositionX, newPositionY)[0] == 0xFFu);
490 positionRow->setPosition(newPositionX, newPositionY);
492 CV::CVUtilities::copyPixel<tChannels>(layerFrameData, layerFrameData, x, y, newPositionX, newPositionY, layerWidth, layerWidth, layerFramePaddingElements, layerFramePaddingElements);