Ocean
Optimizer4NeighborhoodAreaConstrainedI1.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_CV_SYNTHESIS_OPTIMIZER_4_NEIGHBORHOOD_AREA_CONSTRAINED_I_1_H
9 #define META_OCEAN_CV_SYNTHESIS_OPTIMIZER_4_NEIGHBORHOOD_AREA_CONSTRAINED_I_1_H
10 
16 
17 namespace Ocean
18 {
19 
20 namespace CV
21 {
22 
23 namespace Synthesis
24 {
25 
26 /**
27  * This optimizer uses a frame that defines undesired source elements that are avoided during the optimization.
28  * @tparam tWeightFactor Spatial weight impact, with range [0, infinity)
29  * @tparam tBorderFactor Weight factor of border pixels, with range [1, infinity)
30  * @tparam tUpdateFrame True, to update the frame pixel whenever a new mapping has been found
31  * @ingroup cvsynthesis
32  */
33 template <unsigned int tWeightFactor, unsigned int tBorderFactor, bool tUpdateFrame>
35  virtual public OptimizerI,
36  virtual public OptimizerSubset,
37  virtual public Optimizer1
38 {
39  public:
40 
41  /**
42  * Creates a new optimizer object.
43  * @param layer Synthesis layer that will be optimized
44  * @param randomGenerator Random number generator
45  * @param filter The filter frame that is used during the optimization
46  */
47  inline Optimizer4NeighborhoodAreaConstrainedI1(LayerI1& layer, RandomGenerator& randomGenerator, const Frame& filter);
48 
49  private:
50 
51  /**
52  * Optimizes a subset of the synthesis frame.
53  * @see Optimizer1::optimizeSubset().
54  * @see optimizerSubsetChannels().
55  */
56  void optimizeSubset(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 override;
57 
58  /**
59  * Specialization of the default subset optimization function.
60  * The template parameters specified the number of channels the synthesis frame has.<br>
61  * @param radii Number of improvement radii during one optimization iteration for each mapping position
62  * @param maxSpatialCost Maximal spatial cost
63  * @param boundingBoxTop First row of the entire synthesis area
64  * @param boundingBoxHeight Number of rows of the entire synthesis area
65  * @param downIsMain True, if the downwards direction is the main optimization direction (for all subsets with even thread indices)
66  * @param firstColumn First column to be handled in the subset
67  * @param numberColumns Number of columns to be handled in the subset
68  * @param rowOffset Offset within the entire synthesis area (boundingBoxHeight), the subset may be moved by this offset
69  * @param firstRow First row to be handled in the subset
70  * @param numberRows Number of rows to be handled in the subset
71  * @param threadIndex Index of the thread that executes the subset optimization function
72  * @tparam tChannels Number of data channels of the frame
73  * @see optimizerSubset().
74  */
75  template <unsigned int tChannels>
76  void 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;
77 
78  protected:
79 
80  /// Specialized layer reference.
82 
83  /// Filter frame that is used during the optimization.
84  const Frame& filter_;
85 };
86 
87 template <unsigned int tWeightFactor, unsigned int tBorderFactor, bool tUpdateFrame>
89  Optimizer(layer),
90  OptimizerI(layer),
91  OptimizerSubset(layer, randomGenerator),
92  Optimizer1(layer),
93  layerI1_(layer),
94  filter_(filter)
95 {
96  // nothing to do here
97 }
98 
99 template <unsigned int tWeightFactor, unsigned int tBorderFactor, bool tUpdateFrame>
100 void Optimizer4NeighborhoodAreaConstrainedI1<tWeightFactor, tBorderFactor, tUpdateFrame>::optimizeSubset(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
101 {
102  ocean_assert(layerI1_.frame().numberPlanes() == 1u);
103 
104  switch (layerI1_.frame().channels())
105  {
106  case 1u:
107  optimizeSubsetChannels<1u>(radii, maxSpatialCost, boundingBoxTop, boundingBoxHeight, downIsMain, firstColumn, numberColumns, rowOffset, firstRow, numberRows, threadIndex);
108  break;
109 
110  case 2u:
111  optimizeSubsetChannels<2u>(radii, maxSpatialCost, boundingBoxTop, boundingBoxHeight, downIsMain, firstColumn, numberColumns, rowOffset, firstRow, numberRows, threadIndex);
112  break;
113 
114  case 3u:
115  optimizeSubsetChannels<3u>(radii, maxSpatialCost, boundingBoxTop, boundingBoxHeight, downIsMain, firstColumn, numberColumns, rowOffset, firstRow, numberRows, threadIndex);
116  break;
117 
118  case 4u:
119  optimizeSubsetChannels<4u>(radii, maxSpatialCost, boundingBoxTop, boundingBoxHeight, downIsMain, firstColumn, numberColumns, rowOffset, firstRow, numberRows, threadIndex);
120  break;
121 
122  default:
123  ocean_assert(false && "Invalid frame type.");
124  }
125 }
126 
127 template <unsigned int tWeightFactor, unsigned int tBorderFactor, bool tUpdateFrame>
128 template <unsigned int tChannels>
129 void 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
130 {
131  const unsigned int layerWidth = layerI1_.width();
132  const unsigned int layerHeight = layerI1_.height();
133  ocean_assert(layerWidth != 0 && layerHeight != 0);
134 
135  const std::vector<int> searchRadii(calculateSearchRadii(radii, layerWidth, layerHeight));
136 
137  Frame& layerFrame = layerI1_.frame();
138  const Frame& layerMask = layerI1_.mask();
139  MappingI1& layerMapping = layerI1_.mapping();
140 
141  ocean_assert(layerFrame.width() == layerWidth);
142  ocean_assert(layerFrame.height() == layerHeight);
143 
144  ocean_assert(FrameType::formatIsGeneric(layerFrame.pixelFormat(), FrameType::DT_UNSIGNED_INTEGER_8, tChannels));
145  ocean_assert(layerFrame.pixelOrigin() == layerMask.pixelOrigin());
146 
147  ocean_assert(firstColumn + numberColumns <= layerFrame.width());
148  ocean_assert(firstRow + numberRows <= layerFrame.height());
149 
150  RandomGenerator generator(randomGenerator_);
151 
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>();
155 
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();
160 
161 #ifdef OCEAN_DEBUG
162  const PixelBoundingBox& debugLayerBoundingBox = layerI1_.boundingBox();
163  ocean_assert(!debugLayerBoundingBox || firstRow >= debugLayerBoundingBox.top());
164  ocean_assert(!debugLayerBoundingBox || firstRow + numberRows <= debugLayerBoundingBox.bottomEnd());
165 #endif
166 
167  const bool down = (downIsMain && (threadIndex % 2u) == 0u) || (!downIsMain && (threadIndex % 2u) == 1u);
168 
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;
173 
174  ocean_assert(xEnd - xStart <= layerWidth);
175  ocean_assert(yEnd - yStart <= layerHeight);
176 
177  if (down)
178  {
179  // find better positions for each mask pixel (top left to bottom right)
180  for (unsigned int yy = yStart; yy < yEnd; ++yy)
181  {
182  const unsigned int y = modulo(int(yy + rowOffset - boundingBoxTop), int(boundingBoxHeight)) + boundingBoxTop;
183 
184  const uint8_t* maskRow = layerMask.constrow<uint8_t>(y) + xStart;
185  PixelPosition* positionRow = layerMapping.row(y) + xStart;
186 
187  for (unsigned int x = xStart; x < xEnd; ++x)
188  {
189  bool foundBetter = false;
190 
191  ocean_assert(maskRow == layerMask.constpixel<uint8_t>(x, y));
192  if (*maskRow != 0xFF)
193  {
194  unsigned int newPositionX = positionRow->x();
195  unsigned int newPositionY = positionRow->y();
196 
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;
200 
201  unsigned int testPositionX, testPositionY;
202 
203  // first propagation from left to right
204  ocean_assert(x == 0 || maskRow - 1 == layerMask.constpixel<uint8_t>(x - 1u, y));
205  if (x > 0 && *(maskRow - 1) != 0xFF)
206  {
207  ocean_assert(layerMapping.position(x - 1, y));
208  ocean_assert(*(positionRow - 1) == layerMapping.position(x - 1, y));
209 
210  // take the position to the left (of the current position)
211  testPositionX = (positionRow - 1)->x() + 1;
212  testPositionY = (positionRow - 1)->y();
213 
214  if (testPositionX < layerWidth && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
215  && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
216  {
217  // the structure cost is 0 due to the neighbor condition
218  ocean_assert(layerMapping.spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
219 
220  const unsigned int testCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
221 
222  if (testCost < newCost)
223  {
224  newPositionX = testPositionX;
225  newPositionY = testPositionY;
226  newCost = testCost;
227  foundBetter = true;
228  }
229  }
230 
231  // second propagation from top to bottom
232  ocean_assert(y == 0 || maskRow - layerMaskStrideElements == layerMask.constpixel<uint8_t>(x, y - 1u));
233  if (y > 0 && *(maskRow - layerMaskStrideElements) != 0xFFu
234  // test only if the mapping of the left position does not match (shifted) to the mapping of the top position
235  && (positionRow - 1)->northEast() != *(positionRow - layerWidth))
236  {
237  ocean_assert(layerMapping.position(x, y - 1));
238  ocean_assert(*(positionRow - layerWidth) == layerMapping.position(x, y - 1));
239 
240  // take the next position to the top (of the current position)
241  testPositionX = (positionRow - layerWidth)->x();
242  testPositionY = (positionRow - layerWidth)->y() + 1;
243 
244  if (testPositionY < layerHeight && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
245  && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
246  {
247  // the structure cost is 0 due to the neighbor condition
248  ocean_assert(layerMapping.spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
249 
250  const unsigned int testCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
251 
252  if (testCost < newCost)
253  {
254  newPositionX = testPositionX;
255  newPositionY = testPositionY;
256  newCost = testCost;
257  foundBetter = true;
258  }
259  }
260  }
261 
262  }
263  else
264  {
265  // second propagation from top to bottom
266  ocean_assert(y == 0 || maskRow - layerMaskStrideElements == layerMask.constpixel<uint8_t>(x, y - 1u));
267  if (y > 0 && *(maskRow - layerMaskStrideElements) != 0xFFu)
268  {
269  ocean_assert(layerMapping.position(x, y - 1));
270  ocean_assert(*(positionRow - layerWidth) == layerMapping.position(x, y - 1));
271 
272  // take the next position to the top (of the current position)
273  testPositionX = (positionRow - layerWidth)->x();
274  testPositionY = (positionRow - layerWidth)->y() + 1;
275 
276  if (testPositionY < layerHeight && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
277  && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
278  {
279  // the structure cost is 0 due to the neighbor condition
280  ocean_assert(layerMapping.spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
281 
282  const unsigned int testCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
283 
284  if (testCost < newCost)
285  {
286  newPositionX = testPositionX;
287  newPositionY = testPositionY;
288  newCost = testCost;
289  foundBetter = true;
290  }
291  }
292  }
293  }
294 
295  // find a better position of the current mask pixel
296  for (unsigned int n = 0; n < radii; ++n)
297  {
298  ocean_assert(newPositionX != (unsigned int)(-1) && newPositionY != (unsigned int)(-1));
299 
300  testPositionX = newPositionX + RandomI::random(generator, -searchRadii[n], searchRadii[n]);
301  testPositionY = newPositionY + RandomI::random(generator, -searchRadii[n], searchRadii[n]);
302 
303  // the test position must not lie inside the mask
304  if ((testPositionX == newPositionX && testPositionY == newPositionY)
305  || testPositionX >= layerWidth || testPositionY >= layerHeight
306  || layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] != 0xFFu
307  || layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] != 0xFFu)
308  continue;
309 
310  const unsigned int testSpatialCost = layerMapping.spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
311  const unsigned int testColorCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
312  const unsigned int testCost = tWeightFactor * testSpatialCost + testColorCost;
313 
314  if (testCost < newCost)
315  {
316  newPositionX = testPositionX;
317  newPositionY = testPositionY;
318  newCost = testCost;
319  foundBetter = true;
320  }
321  }
322 
323  if (tUpdateFrame && foundBetter)
324  {
325  ocean_assert(layerMask.constpixel<uint8_t>(x, y)[0] != 0xFFu);
326  ocean_assert(layerMask.constpixel<uint8_t>(newPositionX, newPositionY)[0] == 0xFFu);
327 
328  positionRow->setPosition(newPositionX, newPositionY);
329 
330  CV::CVUtilities::copyPixel<tChannels>(layerFrameData, layerFrameData, x, y, newPositionX, newPositionY, layerWidth, layerWidth, layerFramePaddingElements, layerFramePaddingElements);
331  }
332  }
333 
334  ++maskRow;
335  ++positionRow;
336  }
337  }
338  }
339  else // up
340  {
341  // find better positions for each mask pixel (bottom right to top left)
342  for (unsigned int yy = yEnd - 1u; yy != yStart - 1u; --yy)
343  {
344  const unsigned int y = modulo(int(yy + rowOffset - boundingBoxTop), int(boundingBoxHeight)) + boundingBoxTop;
345 
346  const uint8_t* maskRow = layerMask.constrow<uint8_t>(y) + xEnd - 1u;
347  PixelPosition* positionRow = layerMapping.row(y) + xEnd - 1u;
348 
349  for (unsigned int x = xEnd - 1u; x != xStart - 1u; --x)
350  {
351  bool foundBetter = false;
352 
353  ocean_assert(maskRow == layerMask.constpixel<uint8_t>(x, y));
354  if (*maskRow != 0xFF)
355  {
356  unsigned int newPositionX = positionRow->x();
357  unsigned int newPositionY = positionRow->y();
358 
359  const unsigned int oldSpatialCost = layerMapping.spatialCost4Neighborhood<tChannels>(x, y, newPositionX, newPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
360  const unsigned int oldColorCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, newPositionX, newPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
361  unsigned int newCost = tWeightFactor * oldSpatialCost + oldColorCost;
362 
363  unsigned int testPositionX, testPositionY;
364 
365  // first propagation from right to left
366  ocean_assert(x == layerWidth - 1u || (maskRow + 1) == layerMask.constpixel<uint8_t>(x + 1u, y));
367  if (x < layerWidth - 1u && *(maskRow + 1) != 0xFF)
368  {
369  ocean_assert(layerMapping.position(x + 1u, y));
370  ocean_assert(*(positionRow + 1) == layerMapping.position(x + 1u, y));
371 
372  // take the position to the right (of the current position)
373  testPositionX = (positionRow + 1)->x() - 1;
374  testPositionY = (positionRow + 1)->y();
375 
376  if (testPositionX != (unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
377  && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
378  {
379  // the structure cost is 0 due to the neighbor condition
380  ocean_assert(layerMapping.spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
381 
382  const unsigned int testCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
383 
384  if (testCost < newCost)
385  {
386  newPositionX = testPositionX;
387  newPositionY = testPositionY;
388  newCost = testCost;
389  foundBetter = true;
390  }
391  }
392 
393  // second propagation from bottom to top
394  ocean_assert(y == layerHeight - 1 || (maskRow + layerMaskStrideElements) == layerMask.constpixel<uint8_t>(x, y + 1u));
395  if (y < layerHeight - 1 && *(maskRow + layerMaskStrideElements) != 0xFF
396  // test only if the mapping of the right position does not match (shifted) to the mapping of the bottom position
397  && (positionRow + 1)->southWest() != *(positionRow + layerWidth))
398  {
399  ocean_assert(layerMapping.position(x, y + 1));
400  ocean_assert(*(positionRow + layerWidth) == layerMapping.position(x, y + 1));
401 
402  // take the next position towards the bottom (of the current position)
403  testPositionX = (positionRow + layerWidth)->x();
404  testPositionY = (positionRow + layerWidth)->y() - 1u;
405 
406  if (testPositionY != (unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
407  && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
408  {
409  // the structure cost is 0 due to the neighbor condition
410  ocean_assert(layerMapping.spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
411 
412  const unsigned int testCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
413 
414  if (testCost < newCost)
415  {
416  newPositionX = testPositionX;
417  newPositionY = testPositionY;
418  newCost = testCost;
419  foundBetter = true;
420  }
421  }
422  }
423  }
424  else
425  {
426  // second propagation from bottom to top
427  ocean_assert(y == layerHeight - 1u || (maskRow + layerMaskStrideElements) == layerMask.constpixel<uint8_t>(x, y + 1u));
428  if (y < layerHeight - 1u && *(maskRow + layerMaskStrideElements) != 0xFFu)
429  {
430  ocean_assert(layerMapping.position(x, y + 1u));
431  ocean_assert(*(positionRow + layerWidth) == layerMapping.position(x, y + 1u));
432 
433  // take the next position towards the bottom (of the current position)
434  testPositionX = (positionRow + layerWidth)->x();
435  testPositionY = (positionRow + layerWidth)->y() - 1u;
436 
437  if (testPositionY != (unsigned int)(-1) && layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] == 0xFFu
438  && layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] == 0xFFu)
439  {
440  // the structure cost is 0 due to the neighbor condition
441  ocean_assert(layerMapping.spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost) == 0u);
442 
443  const unsigned int testCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
444 
445  if (testCost < newCost)
446  {
447  newPositionX = testPositionX;
448  newPositionY = testPositionY;
449  newCost = testCost;
450  foundBetter = true;
451  }
452  }
453  }
454  }
455 
456  // find a better position of the current mask pixel
457  for (unsigned int n = 0; n < radii; ++n)
458  {
459  ocean_assert(newPositionX != (unsigned int)(-1) && newPositionY != (unsigned int)(-1));
460 
461  testPositionX = newPositionX + RandomI::random(generator, -searchRadii[n], searchRadii[n]);
462  testPositionY = newPositionY + RandomI::random(generator, -searchRadii[n], searchRadii[n]);
463 
464  if ((testPositionX == newPositionX && testPositionY == newPositionY)
465  || testPositionX >= layerWidth || testPositionY >= layerHeight
466  || layerMaskData[testPositionY * layerMaskStrideElements + testPositionX] != 0xFFu
467  || layerFilterData[testPositionY * layerFilterStrideElements + testPositionX] != 0xFFu)
468  continue;
469 
470  const unsigned int testSpatialCost = layerMapping.spatialCost4Neighborhood<tChannels>(x, y, testPositionX, testPositionY, layerMaskData, layerMaskPaddingElements, maxSpatialCost);
471  const unsigned int testColorCost = layerMapping.appearanceCost5x5<tChannels, tBorderFactor>(x, y, testPositionX, testPositionY, layerFrameData, layerMaskData, layerFramePaddingElements, layerMaskPaddingElements);
472  const unsigned int testCost = tWeightFactor * testSpatialCost + testColorCost;
473 
474  if (testCost < newCost)
475  {
476  newPositionX = testPositionX;
477  newPositionY = testPositionY;
478  newCost = testCost;
479  foundBetter = true;
480  }
481  }
482 
483  if (tUpdateFrame && foundBetter)
484  {
485  ocean_assert(layerMask.constpixel<uint8_t>(x, y)[0] != 0xFFu);
486  ocean_assert(layerMask.constpixel<uint8_t>(newPositionX, newPositionY)[0] == 0xFFu);
487 
488  positionRow->setPosition(newPositionX, newPositionY);
489 
490  CV::CVUtilities::copyPixel<tChannels>(layerFrameData, layerFrameData, x, y, newPositionX, newPositionY, layerWidth, layerWidth, layerFramePaddingElements, layerFramePaddingElements);
491  }
492  }
493 
494  --maskRow;
495  --positionRow;
496  }
497  }
498  }
499 }
500 
501 }
502 
503 }
504 
505 }
506 
507 #endif // META_OCEAN_CV_SYNTHESIS_OPTIMIZER_4_NEIGHBORHOOD_AREA_CONSTRAINED_I_1_H
T bottomEnd() const
Returns the bottom (excluding) pixel position of this bounding box.
Definition: PixelBoundingBox.h:451
T top() const
Returns the top (including) pixel position of this bounding box.
Definition: PixelBoundingBox.h:423
This class implements a single layer for pixel synthesis within one frame and pixel accuracy.
Definition: LayerI1.h:41
This class implements the pixel mapping between source and target frames.
Definition: MappingI1.h:49
unsigned int spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t *targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const
Calculates the smallest/cheapest spatial cost for a given point in a four-neighborhood and normalizes...
Definition: MappingI1.h:212
unsigned int appearanceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t *frame, const uint8_t *mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements) const
Calculates the appearance cost for a given point in a given frame.
Definition: MappingI1.h:634
const PixelPosition * row(const unsigned int y) const
Returns the pointer to a mapping row.
Definition: MappingI.h:243
const PixelPosition & position(const unsigned int x, const unsigned int y) const
Returns the mapping for a given position.
Definition: MappingI.h:215
This class implements the base class for all synthesis optimizers that use one single frame.
Definition: Optimizer1.h:28
This optimizer uses a frame that defines undesired source elements that are avoided during the optimi...
Definition: Optimizer4NeighborhoodAreaConstrainedI1.h:38
void 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
Specialization of the default subset optimization function.
Definition: Optimizer4NeighborhoodAreaConstrainedI1.h:129
Optimizer4NeighborhoodAreaConstrainedI1(LayerI1 &layer, RandomGenerator &randomGenerator, const Frame &filter)
Creates a new optimizer object.
Definition: Optimizer4NeighborhoodAreaConstrainedI1.h:88
void optimizeSubset(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 override
Optimizes a subset of the synthesis frame.
Definition: Optimizer4NeighborhoodAreaConstrainedI1.h:100
const Frame & filter_
Filter frame that is used during the optimization.
Definition: Optimizer4NeighborhoodAreaConstrainedI1.h:84
LayerI1 & layerI1_
Specialized layer reference.
Definition: Optimizer4NeighborhoodAreaConstrainedI1.h:81
This class is the base class for all synthesis optimizers.
Definition: Optimizer.h:30
This class is the base class for all optimizers that use a mapping with integer accuracy.
Definition: OptimizerI.h:29
This class is the base class for all optimizers that are able to optimize seperate subsets of the syn...
Definition: OptimizerSubset.h:30
This class implements Ocean's image class.
Definition: Frame.h:1760
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:4026
const T * constdata(const unsigned int planeIndex=0u) const
Returns a pointer to the read-only pixel data of a specific plane.
Definition: Frame.h:4136
T * data(const unsigned int planeIndex=0u)
Returns a pointer to the pixel data of a specific plane.
Definition: Frame.h:4127
const T * constpixel(const unsigned int x, const unsigned int y, const unsigned int planeIndex=0u) const
Returns the pointer to the constant data of a specific pixel.
Definition: Frame.h:4218
const T * constrow(const unsigned int y, const unsigned int planeIndex=0u) const
Returns the pointer to the constant data of a specific row.
Definition: Frame.h:4161
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:4010
unsigned int width() const
Returns the width of the frame format in pixel.
Definition: Frame.h:3111
PixelOrigin pixelOrigin() const
Returns the pixel origin of the frame.
Definition: Frame.h:3156
PixelFormat pixelFormat() const
Returns the pixel format of the frame.
Definition: Frame.h:3121
@ DT_UNSIGNED_INTEGER_8
Unsigned 8 bit integer data type (uint8_t).
Definition: Frame.h:41
unsigned int height() const
Returns the height of the frame in pixel.
Definition: Frame.h:3116
static bool formatIsGeneric(const PixelFormat pixelFormat, const DataType dataType, const uint32_t channels, const uint32_t planes=1u, const uint32_t widthMultiple=1u, const uint32_t heightMultiple=1u)
Checks whether a given pixel format is a specific layout regarding data channels and data type.
Definition: Frame.h:3374
This class implements a generator for random numbers.
Definition: RandomGenerator.h:42
static unsigned int random(const unsigned int maxValue)
Returns one random integer value with specified maximum value.
T modulo(const T &value, const T &ring)
Returns the modulo value of a given parameter within a ring allowing positive and negative parameters...
Definition: base/Utilities.h:924
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15