@@ -180,8 +180,10 @@ std::vector<StStep> planSparseTableConstr(std::vector<std::vector<bool>> sparseM
180
180
return plan;
181
181
}
182
182
183
+ #pragma region Dilation
184
+
183
185
template <typename T>
184
- void makeMinSparseTableMat (InputArray src, OutputArray dst, int rowStep, int colStep)
186
+ void makeMaxSparseTableMat (InputArray src, OutputArray dst, int rowStep, int colStep)
185
187
{
186
188
CV_Assert (rowStep * colStep == 0 ); // one of "rowStep" or "colStep" is required to be 0.
187
189
@@ -199,8 +201,8 @@ void makeMinSparseTableMat(InputArray src, OutputArray dst, int rowStep, int col
199
201
{
200
202
for (int colCh = 0 ; colCh < colChLim; colCh++)
201
203
{
202
- // Somehow std::min (a,b) or a< b?a:b are slower.
203
- if (*srcPtr1 < *srcPtr2)
204
+ // Somehow std::max (a,b) or a> b?a:b are slower.
205
+ if (*srcPtr1 > *srcPtr2)
204
206
{
205
207
*dstPtr++ = *srcPtr1++;
206
208
srcPtr2++;
@@ -218,10 +220,157 @@ void makeMinSparseTableMat(InputArray src, OutputArray dst, int rowStep, int col
218
220
}
219
221
220
222
template <typename T>
221
- void makeMaxSparseTableMat (InputArray src, OutputArray dst, int rowStep, int colStep)
223
+ void _dilate (InputArray _src, OutputArray _dst, InputArray _kernel,
224
+ Point anchor, int iterations,
225
+ int borderType, const Scalar& borderValue)
226
+ {
227
+ Mat kernel = _kernel.getMat ();
228
+
229
+ // Generate list of rectangles whose width and height are power of 2.
230
+ // (The width and height values of returned rects are the log2 of the actual values.)
231
+ std::vector<Rect> pow2Rects = genPow2RectsToCoverKernel (kernel);
232
+
233
+ // get the depth limits
234
+ int rowDepthLim = 0 , colDepthLim = 0 ;
235
+ for (int i = 0 ; i < pow2Rects.size (); i++)
236
+ {
237
+ if (rowDepthLim < pow2Rects[i].height ) rowDepthLim = pow2Rects[i].height ;
238
+ if (colDepthLim < pow2Rects[i].width ) colDepthLim = pow2Rects[i].width ;
239
+ }
240
+ rowDepthLim++;
241
+ colDepthLim++;
242
+
243
+ // list up required sparse table nodes.
244
+ std::vector<std::vector<bool >> sparseMatMap (rowDepthLim, std::vector<bool >(colDepthLim, false ));
245
+ for (int i = 0 ; i < pow2Rects.size (); i++)
246
+ sparseMatMap[pow2Rects[i].height ][pow2Rects[i].width ] = true ;
247
+
248
+ // plan how to calculate required nodes of 2D sparse table.
249
+ std::vector<StStep> stPlan = planSparseTableConstr (sparseMatMap);
250
+
251
+ Mat src = _src.getMat ();
252
+
253
+ do
254
+ {
255
+ // adding border to the source.
256
+ Scalar bV = borderValue;
257
+ if (borderType == BorderTypes::BORDER_CONSTANT
258
+ && borderValue == morphologyDefaultBorderValue ())
259
+ bV = Scalar::all (0 );
260
+ Mat expandedSrc (src.rows + kernel.rows , src.cols + kernel.cols , src.type ());
261
+ copyMakeBorder (src, expandedSrc,
262
+ anchor.y , kernel.cols - 1 - anchor.y ,
263
+ anchor.x , kernel.rows - 1 - anchor.x ,
264
+ borderType, bV);
265
+
266
+ _dst.create (_src.size (), _src.type ());
267
+ Mat dst = _dst.getMat ();
268
+
269
+ std::vector<std::vector<Mat>> st (rowDepthLim, std::vector<Mat>(colDepthLim));
270
+ st[0 ][0 ] = expandedSrc;
271
+ for (int i = 0 ; i < stPlan.size (); i++)
272
+ {
273
+ StStep step = stPlan[i];
274
+ switch (step.ax )
275
+ {
276
+ case Dim::Col:
277
+ makeMaxSparseTableMat<T>(st[step.dimRow ][step.dimCol ], st[step.dimRow ][step.dimCol + 1 ],
278
+ 0 , 1 << step.dimCol );
279
+ break ;
280
+ case Dim::Row:
281
+ makeMaxSparseTableMat<T>(st[step.dimRow ][step.dimCol ], st[step.dimRow + 1 ][step.dimCol ],
282
+ 1 << step.dimRow , 0 );
283
+ break ;
284
+ }
285
+ }
286
+
287
+ // result constructioin
288
+ dst.setTo (0 );
289
+ int colChLim = dst.cols * dst.channels ();
290
+ for (int i = 0 ; i < pow2Rects.size (); i++)
291
+ {
292
+ Rect rect = pow2Rects[i];
293
+ Mat sparseMat = st[rect.height ][rect.width ];
294
+ int sideBorderSkipStep = (kernel.cols - 1 ) * sparseMat.channels ();
295
+ T* srcPtr = sparseMat.ptr <T>(rect.y , rect.x );
296
+ T* dstPtr = dst.ptr <T>();
297
+ for (int row = 0 ; row < dst.rows ; row++)
298
+ {
299
+ for (int col = 0 ; col < colChLim; col++)
300
+ {
301
+ if (*srcPtr > *dstPtr) *dstPtr = *srcPtr;
302
+ srcPtr++;
303
+ dstPtr++;
304
+ }
305
+ srcPtr += sideBorderSkipStep;
306
+ }
307
+ }
308
+
309
+ src = dst;
310
+ } while (--iterations > 0 );
311
+ }
312
+
313
+ void dilate (InputArray _src, OutputArray _dst, InputArray _kernel,
314
+ Point anchor, int iterations,
315
+ int borderType, const Scalar& borderValue)
316
+ {
317
+ Mat kernel = _kernel.getMat ();
318
+ if (iterations == 0 || kernel.rows * kernel.cols == 1 )
319
+ {
320
+ _src.copyTo (_dst);
321
+ return ;
322
+ }
323
+ // Fix kernel in case of it is empty.
324
+ if (kernel.empty ())
325
+ {
326
+ kernel = getStructuringElement (MORPH_RECT, Size (1 + iterations * 2 , 1 + iterations * 2 ));
327
+ anchor = Point (iterations, iterations);
328
+ iterations = 1 ;
329
+ }
330
+ if (countNonZero (kernel) == 0 )
331
+ {
332
+ kernel.at <uchar>(0 , 0 ) = 1 ;
333
+ }
334
+ // Fix anchor to the center of the kernel.
335
+ anchor = stMorph::normalizeAnchor (anchor, kernel.size ());
336
+
337
+ // dilate operation
338
+ switch (_src.depth ())
339
+ {
340
+ case CV_8U:
341
+ _dilate<uchar>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
342
+ return ;
343
+ case CV_8S:
344
+ _dilate<char >(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
345
+ return ;
346
+ case CV_16U:
347
+ _dilate<ushort>(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
348
+ return ;
349
+ case CV_16S:
350
+ _dilate<short >(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
351
+ return ;
352
+ case CV_32S:
353
+ _dilate<int >(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
354
+ return ;
355
+ case CV_32F:
356
+ _dilate<float >(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
357
+ return ;
358
+ case CV_64F:
359
+ _dilate<double >(_src, _dst, kernel, anchor, iterations, borderType, borderValue);
360
+ return ;
361
+ }
362
+ }
363
+
364
+ #pragma endregion
365
+
366
+ #pragma region Erosion
367
+
368
+ template <typename T>
369
+ void makeMinSparseTableMat (InputArray src, OutputArray dst, int rowStep, int colStep)
222
370
{
223
371
CV_Assert (rowStep * colStep == 0 ); // one of "rowStep" or "colStep" is required to be 0.
224
372
373
+ dst.create (src.size (), src.type ());
225
374
Mat src_ = src.getMat ();
226
375
Mat dst_ = dst.getMat ();
227
376
int rowLim = src.rows () - rowStep;
@@ -235,7 +384,8 @@ void makeMaxSparseTableMat(InputArray src, OutputArray dst, int rowStep, int col
235
384
{
236
385
for (int colCh = 0 ; colCh < colChLim; colCh++)
237
386
{
238
- if (*srcPtr1 > *srcPtr2)
387
+ // Somehow std::min(a,b) or a<b?a:b are slower.
388
+ if (*srcPtr1 < *srcPtr2)
239
389
{
240
390
*dstPtr++ = *srcPtr1++;
241
391
srcPtr2++;
@@ -343,12 +493,6 @@ void _erode(InputArray _src, OutputArray _dst, InputArray _kernel,
343
493
} while (--iterations > 0 );
344
494
}
345
495
346
- void dilate (InputArray src, OutputArray dst, InputArray kernel,
347
- Point anchor, int iterations,
348
- int borderType, const Scalar& borderValue)
349
- {
350
- }
351
-
352
496
void erode (InputArray _src, OutputArray _dst, InputArray _kernel,
353
497
Point anchor, int iterations,
354
498
int borderType, const Scalar& borderValue)
@@ -400,6 +544,8 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
400
544
}
401
545
}
402
546
547
+ #pragma endregion
548
+
403
549
void morphologyEx (InputArray _src, OutputArray _dst, int op,
404
550
InputArray _kernel, Point anchor, int iterations,
405
551
int borderType, const Scalar& borderValue)
0 commit comments