3
3
// of this distribution and at http://opencv.org/license.html.
4
4
5
5
#include " precomp.hpp"
6
- #include < vector>
7
6
#include < limits>
7
+ #include < utility>
8
+ #include < vector>
8
9
9
10
namespace cv {
10
11
namespace stMorph {
@@ -256,10 +257,7 @@ void _erode(InputArray _src, OutputArray _dst, InputArray _kernel,
256
257
Point anchor, int iterations,
257
258
int borderType, const Scalar& borderValue)
258
259
{
259
- Mat src = _src.getMat ();
260
-
261
260
Mat kernel = _kernel.getMat ();
262
- anchor = stMorph::normalizeAnchor (anchor, kernel.size ());
263
261
264
262
// Generate list of rectangles whose width and height are power of 2.
265
263
// (The width and height values of returned rects are the log2 of the actual values.)
@@ -283,59 +281,66 @@ void _erode(InputArray _src, OutputArray _dst, InputArray _kernel,
283
281
// plan how to calculate required nodes of 2D sparse table.
284
282
std::vector<StStep> stPlan = planSparseTableConstr (sparseMatMap);
285
283
286
- // adding border to the source.
287
- Scalar bV = borderValue;
288
- if (borderType == BorderTypes::BORDER_CONSTANT
289
- && borderValue == morphologyDefaultBorderValue ())
290
- bV = Scalar::all (std::numeric_limits<T>::max ());
291
- Mat expandedSrc (src.rows + kernel.rows , src.cols + kernel.cols , src.type ());
292
- copyMakeBorder (src, expandedSrc,
293
- anchor.y , kernel.cols - 1 - anchor.y ,
294
- anchor.x , kernel.rows - 1 - anchor.x ,
295
- borderType, bV);
296
-
297
- _dst.create (_src.size (), _src.type ());
298
- Mat dst = _dst.getMat ();
299
-
300
- std::vector<std::vector<Mat>> st (rowDepthLim, std::vector<Mat>(colDepthLim));
301
- st[0 ][0 ] = expandedSrc;
302
- for (int i = 0 ; i < stPlan.size (); i++)
284
+ Mat src = _src.getMat ();
285
+
286
+ do
303
287
{
304
- StStep step = stPlan[i];
305
- switch (step.ax )
288
+ // adding border to the source.
289
+ Scalar bV = borderValue;
290
+ if (borderType == BorderTypes::BORDER_CONSTANT
291
+ && borderValue == morphologyDefaultBorderValue ())
292
+ bV = Scalar::all (std::numeric_limits<T>::max ());
293
+ Mat expandedSrc (src.rows + kernel.rows , src.cols + kernel.cols , src.type ());
294
+ copyMakeBorder (src, expandedSrc,
295
+ anchor.y , kernel.cols - 1 - anchor.y ,
296
+ anchor.x , kernel.rows - 1 - anchor.x ,
297
+ borderType, bV);
298
+
299
+ _dst.create (_src.size (), _src.type ());
300
+ Mat dst = _dst.getMat ();
301
+
302
+ std::vector<std::vector<Mat>> st (rowDepthLim, std::vector<Mat>(colDepthLim));
303
+ st[0 ][0 ] = expandedSrc;
304
+ for (int i = 0 ; i < stPlan.size (); i++)
306
305
{
307
- case Dim::Col:
308
- makeMinSparseTableMat<T>(st[step.dimRow ][step.dimCol ], st[step.dimRow ][step.dimCol + 1 ],
309
- 0 , 1 << step.dimCol );
310
- break ;
311
- case Dim::Row:
312
- makeMinSparseTableMat<T>(st[step.dimRow ][step.dimCol ], st[step.dimRow + 1 ][step.dimCol ],
313
- 1 << step.dimRow , 0 );
314
- break ;
306
+ StStep step = stPlan[i];
307
+ switch (step.ax )
308
+ {
309
+ case Dim::Col:
310
+ makeMinSparseTableMat<T>(st[step.dimRow ][step.dimCol ], st[step.dimRow ][step.dimCol + 1 ],
311
+ 0 , 1 << step.dimCol );
312
+ break ;
313
+ case Dim::Row:
314
+ makeMinSparseTableMat<T>(st[step.dimRow ][step.dimCol ], st[step.dimRow + 1 ][step.dimCol ],
315
+ 1 << step.dimRow , 0 );
316
+ break ;
317
+ }
315
318
}
316
- }
317
319
318
- // result constructioin
319
- dst.setTo (std::numeric_limits<T>::max ());
320
- int colChLim = dst.cols * dst.channels ();
321
- for (int i = 0 ; i < pow2Rects.size (); i++)
322
- {
323
- Rect rect = pow2Rects[i];
324
- Mat sparseMat = st[rect.height ][rect.width ];
325
- int sideBorderSkipStep = (kernel.cols - 1 ) * sparseMat.channels ();
326
- T* srcPtr = sparseMat.ptr <T>(rect.y , rect.x );
327
- T* dstPtr = dst.ptr <T>();
328
- for (int row = 0 ; row < dst.rows ; row++)
320
+ // result constructioin
321
+ dst.setTo (std::numeric_limits<T>::max ());
322
+ int colChLim = dst.cols * dst.channels ();
323
+ for (int i = 0 ; i < pow2Rects.size (); i++)
329
324
{
330
- for (int col = 0 ; col < colChLim; col++)
325
+ Rect rect = pow2Rects[i];
326
+ Mat sparseMat = st[rect.height ][rect.width ];
327
+ int sideBorderSkipStep = (kernel.cols - 1 ) * sparseMat.channels ();
328
+ T* srcPtr = sparseMat.ptr <T>(rect.y , rect.x );
329
+ T* dstPtr = dst.ptr <T>();
330
+ for (int row = 0 ; row < dst.rows ; row++)
331
331
{
332
- if (*srcPtr < *dstPtr) *dstPtr = *srcPtr;
333
- srcPtr++;
334
- dstPtr++;
332
+ for (int col = 0 ; col < colChLim; col++)
333
+ {
334
+ if (*srcPtr < *dstPtr) *dstPtr = *srcPtr;
335
+ srcPtr++;
336
+ dstPtr++;
337
+ }
338
+ srcPtr += sideBorderSkipStep;
335
339
}
336
- srcPtr += sideBorderSkipStep;
337
340
}
338
- }
341
+
342
+ src = dst;
343
+ } while (--iterations > 0 );
339
344
}
340
345
341
346
void dilate (InputArray src, OutputArray dst, InputArray kernel,
@@ -348,30 +353,50 @@ void erode(InputArray _src, OutputArray _dst, InputArray _kernel,
348
353
Point anchor, int iterations,
349
354
int borderType, const Scalar& borderValue)
350
355
{
356
+ Mat kernel = _kernel.getMat ();
357
+ if (iterations == 0 || kernel.rows * kernel.cols == 1 )
358
+ {
359
+ _src.copyTo (_dst);
360
+ return ;
361
+ }
362
+ // Fix kernel in case of it is empty.
363
+ if (kernel.empty ())
364
+ {
365
+ kernel = getStructuringElement (MORPH_RECT, Size (1 + iterations * 2 , 1 + iterations * 2 ));
366
+ anchor = Point (iterations, iterations);
367
+ iterations = 1 ;
368
+ }
369
+ if (countNonZero (kernel) == 0 )
370
+ {
371
+ kernel.at <uchar>(0 , 0 ) = 1 ;
372
+ }
373
+ // Fix anchor to the center of the kernel.
374
+ anchor = stMorph::normalizeAnchor (anchor, kernel.size ());
375
+
376
+ // erode operation
351
377
switch (_src.depth ())
352
378
{
353
379
case CV_8U:
354
- _erode<uchar>(_src, _dst, _kernel , anchor, iterations, borderType, borderValue);
380
+ _erode<uchar>(_src, _dst, kernel , anchor, iterations, borderType, borderValue);
355
381
return ;
356
382
case CV_8S:
357
- _erode<char >(_src, _dst, _kernel , anchor, iterations, borderType, borderValue);
383
+ _erode<char >(_src, _dst, kernel , anchor, iterations, borderType, borderValue);
358
384
return ;
359
385
case CV_16U:
360
- _erode<ushort>(_src, _dst, _kernel , anchor, iterations, borderType, borderValue);
386
+ _erode<ushort>(_src, _dst, kernel , anchor, iterations, borderType, borderValue);
361
387
return ;
362
388
case CV_16S:
363
- _erode<short >(_src, _dst, _kernel , anchor, iterations, borderType, borderValue);
389
+ _erode<short >(_src, _dst, kernel , anchor, iterations, borderType, borderValue);
364
390
return ;
365
391
case CV_32S:
366
- _erode<int >(_src, _dst, _kernel , anchor, iterations, borderType, borderValue);
392
+ _erode<int >(_src, _dst, kernel , anchor, iterations, borderType, borderValue);
367
393
return ;
368
394
case CV_32F:
369
- _erode<float >(_src, _dst, _kernel , anchor, iterations, borderType, borderValue);
395
+ _erode<float >(_src, _dst, kernel , anchor, iterations, borderType, borderValue);
370
396
return ;
371
397
case CV_64F:
372
- _erode<double >(_src, _dst, _kernel , anchor, iterations, borderType, borderValue);
398
+ _erode<double >(_src, _dst, kernel , anchor, iterations, borderType, borderValue);
373
399
return ;
374
-
375
400
}
376
401
}
377
402
0 commit comments