@@ -257,20 +257,11 @@ void morphDfs(int minmax, Mat& st, Mat& dst,
257
257
}
258
258
259
259
template <typename T>
260
- void morphOp (Op minmax, InputArray _src, OutputArray _dst, InputArray kernel,
261
- Point anchor, int iterations,
262
- int borderType, const Scalar& borderVal)
260
+ void morphOp (Op minmax, InputArray _src, OutputArray _dst, kernelDecompInfo kdi,
261
+ BorderTypes borderType, const Scalar& borderVal)
263
262
{
264
263
T nil = (minmax == Op::Min) ? std::numeric_limits<T>::max () : std::numeric_limits<T>::min ();
265
264
266
- Mat _kernel = kernel.getMat ();
267
- int rowDepthLim = log2 (longestRowRunLength (_kernel)) + 1 ;
268
- int colDepthLim = log2 (longestColRunLength (_kernel)) + 1 ;
269
- std::vector<std::vector<std::vector<Point>>> pow2Rects
270
- = genPow2RectsToCoverKernel (_kernel, rowDepthLim, colDepthLim);
271
- Mat stPlan
272
- = sparseTableFillPlanning (pow2Rects, rowDepthLim, colDepthLim);
273
-
274
265
Mat src = _src.getMat ();
275
266
_dst.create (_src.size (), _src.type ());
276
267
Mat dst = _dst.getMat ();
@@ -283,163 +274,176 @@ void morphOp(Op minmax, InputArray _src, OutputArray _dst, InputArray kernel,
283
274
{
284
275
Mat expandedSrc;
285
276
copyMakeBorder (src, expandedSrc,
286
- anchor.y , _kernel .cols - 1 - anchor.y ,
287
- anchor.x , _kernel .rows - 1 - anchor.x ,
277
+ kdi. anchor .y , kdi .cols - 1 - kdi. anchor .y ,
278
+ kdi. anchor .x , kdi .rows - 1 - kdi. anchor .x ,
288
279
borderType, bV);
289
280
dst.setTo (nil);
290
- morphDfs (minmax, expandedSrc, dst, pow2Rects, stPlan , 0 , 0 );
281
+ morphDfs (minmax, expandedSrc, dst, kdi. stRects , kdi. plan , 0 , 0 );
291
282
src = dst;
292
- } while (--iterations > 0 );
283
+ } while (--kdi. iterations > 0 );
293
284
}
294
285
295
- void morphOp (Op minmax, InputArray _src, OutputArray _dst, InputArray _kernel,
296
- Point anchor, int iterations,
297
- int borderType, const Scalar& borderVal)
286
+ void morphOp (Op minmax, InputArray _src, OutputArray _dst, kernelDecompInfo kdi,
287
+ BorderTypes borderType, const Scalar& borderVal)
298
288
{
299
- Mat kernel = _kernel.getMat ();
300
- if (iterations == 0 || kernel.rows * kernel.cols == 1 )
289
+ if (kdi.iterations == 0 || kdi.rows * kdi.cols == 1 )
301
290
{
302
291
_src.copyTo (_dst);
303
292
return ;
304
293
}
305
- // Fix kernel in case of it is empty.
306
- if (kernel.empty ())
307
- {
308
- kernel = getStructuringElement (MORPH_RECT, Size (1 + iterations * 2 , 1 + iterations * 2 ));
309
- anchor = Point (iterations, iterations);
310
- iterations = 1 ;
311
- }
312
- if (countNonZero (kernel) == 0 )
313
- {
314
- kernel.at <uchar>(0 , 0 ) = 1 ;
315
- }
316
- // Fix anchor to the center of the kernel.
317
- anchor = stMorph::normalizeAnchor (anchor, kernel.size ());
318
294
319
295
switch (_src.depth ())
320
296
{
321
297
case CV_8U:
322
- morphOp<uchar>(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
298
+ morphOp<uchar>(minmax, _src, _dst, kdi , borderType, borderVal);
323
299
return ;
324
300
case CV_8S:
325
- morphOp<char >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
301
+ morphOp<char >(minmax, _src, _dst, kdi , borderType, borderVal);
326
302
return ;
327
303
case CV_16U:
328
- morphOp<ushort>(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
304
+ morphOp<ushort>(minmax, _src, _dst, kdi , borderType, borderVal);
329
305
return ;
330
306
case CV_16S:
331
- morphOp<short >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
307
+ morphOp<short >(minmax, _src, _dst, kdi , borderType, borderVal);
332
308
return ;
333
309
case CV_32S:
334
- morphOp<int >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
310
+ morphOp<int >(minmax, _src, _dst, kdi , borderType, borderVal);
335
311
return ;
336
312
case CV_32F:
337
- morphOp<float >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
313
+ morphOp<float >(minmax, _src, _dst, kdi , borderType, borderVal);
338
314
return ;
339
315
case CV_64F:
340
- morphOp<double >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
316
+ morphOp<double >(minmax, _src, _dst, kdi , borderType, borderVal);
341
317
return ;
342
318
}
343
319
}
344
320
345
- void dilate (InputArray src, OutputArray dst, InputArray kernel,
346
- Point anchor, int iterations,
347
- int borderType, const Scalar& borderVal)
321
+ kernelDecompInfo getKernelDecompInfo (InputArray kernel, Point anchor, int iterations)
348
322
{
349
- morphOp (Op::Max, src, dst, kernel, anchor, iterations, borderType, borderVal);
323
+ Mat _kernel = kernel.getMat ();
324
+ // Fix kernel in case of it is empty.
325
+ if (_kernel.empty ())
326
+ {
327
+ _kernel = getStructuringElement (MORPH_RECT, Size (1 + iterations * 2 , 1 + iterations * 2 ));
328
+ anchor = Point (iterations, iterations);
329
+ iterations = 1 ;
330
+ }
331
+ if (countNonZero (_kernel) == 0 )
332
+ {
333
+ _kernel.at <uchar>(0 , 0 ) = 1 ;
334
+ }
335
+ // Fix anchor to the center of the kernel.
336
+ anchor = stMorph::normalizeAnchor (anchor, _kernel.size ());
337
+
338
+
339
+ int rowDepthLim = log2 (longestRowRunLength (_kernel)) + 1 ;
340
+ int colDepthLim = log2 (longestColRunLength (_kernel)) + 1 ;
341
+ std::vector<std::vector<std::vector<Point>>> pow2Rects
342
+ = genPow2RectsToCoverKernel (_kernel, rowDepthLim, colDepthLim);
343
+
344
+ Mat stPlan
345
+ = sparseTableFillPlanning (pow2Rects, rowDepthLim, colDepthLim);
346
+
347
+ anchor = stMorph::normalizeAnchor (anchor, _kernel.size ());
348
+
349
+ return { _kernel.rows , _kernel.cols , pow2Rects, stPlan, anchor, iterations };
350
350
}
351
351
352
- void erode (InputArray src, OutputArray dst, InputArray kernel,
353
- Point anchor, int iterations,
354
- int borderType, const Scalar& borderVal)
352
+ void erode (InputArray src, OutputArray dst, kernelDecompInfo kdi,
353
+ BorderTypes borderType, const Scalar& borderVal)
355
354
{
356
- morphOp (Op::Min, src, dst, kernel, anchor, iterations , borderType, borderVal);
355
+ morphOp (Op::Min, src, dst, kdi , borderType, borderVal);
357
356
}
358
357
359
- void morphologyEx (InputArray src, OutputArray dst, int op,
360
- InputArray kernel, Point anchor, int iterations,
361
- int borderType, const Scalar& borderVal)
358
+ void dilate (InputArray src, OutputArray dst, kernelDecompInfo kdi,
359
+ BorderTypes borderType, const Scalar& borderVal)
360
+ {
361
+ morphOp (Op::Max, src, dst, kdi, borderType, borderVal);
362
+ }
363
+
364
+ void morphologyEx (InputArray src, OutputArray dst, int op, kernelDecompInfo kdi,
365
+ BorderTypes borderType, const Scalar& borderVal)
362
366
{
363
367
CV_INSTRUMENT_REGION ();
364
368
365
369
CV_Assert (!src.empty ());
366
370
367
- Mat _kernel = kernel.getMat ();
368
- if (_kernel.empty ())
369
- {
370
- _kernel = getStructuringElement (MORPH_RECT, Size (3 , 3 ), Point (1 , 1 ));
371
- }
372
-
373
371
Mat _src = src.getMat (), temp;
374
372
dst.create (_src.size (), _src.type ());
375
373
Mat _dst = dst.getMat ();
376
374
377
375
switch (op)
378
376
{
379
377
case MORPH_ERODE:
380
- stMorph:: erode (src, dst, kernel, anchor, iterations , borderType, borderVal);
378
+ erode (src, dst, kdi , borderType, borderVal);
381
379
break ;
382
380
case MORPH_DILATE:
383
- stMorph:: dilate (src, dst, kernel, anchor, iterations , borderType, borderVal);
381
+ dilate (src, dst, kdi , borderType, borderVal);
384
382
break ;
385
383
case MORPH_OPEN:
386
- stMorph::erode (src, dst, kernel, anchor, iterations , borderType, borderVal);
387
- stMorph::dilate (dst, dst, kernel, anchor, iterations , borderType, borderVal);
384
+ stMorph::erode (src, dst, kdi , borderType, borderVal);
385
+ stMorph::dilate (dst, dst, kdi , borderType, borderVal);
388
386
break ;
389
387
case MORPH_CLOSE:
390
- stMorph::dilate (src, dst, kernel, anchor, iterations , borderType, borderVal);
391
- stMorph::erode (dst, dst, kernel, anchor, iterations , borderType, borderVal);
388
+ stMorph::dilate (src, dst, kdi , borderType, borderVal);
389
+ stMorph::erode (dst, dst, kdi , borderType, borderVal);
392
390
break ;
393
391
case MORPH_GRADIENT:
394
- stMorph::erode (_src, temp, _kernel, anchor, iterations , borderType, borderVal);
395
- stMorph::dilate (_src, _dst, _kernel, anchor, iterations , borderType, borderVal);
392
+ stMorph::erode (_src, temp, kdi , borderType, borderVal);
393
+ stMorph::dilate (_src, _dst, kdi , borderType, borderVal);
396
394
_dst -= temp;
397
395
break ;
398
396
case MORPH_TOPHAT:
399
397
if (_src.data != _dst.data )
400
398
temp = _dst;
401
- stMorph::erode (_src, temp, _kernel, anchor, iterations , borderType, borderVal);
402
- stMorph::dilate (temp, temp, _kernel, anchor, iterations , borderType, borderVal);
399
+ stMorph::erode (_src, temp, kdi , borderType, borderVal);
400
+ stMorph::dilate (temp, temp, kdi , borderType, borderVal);
403
401
_dst = _src - temp;
404
402
break ;
405
403
case MORPH_BLACKHAT:
406
404
if (_src.data != _dst.data )
407
405
temp = _dst;
408
- stMorph::dilate (_src, temp, _kernel, anchor, iterations , borderType, borderVal);
409
- stMorph::erode (temp, temp, _kernel, anchor, iterations , borderType, borderVal);
406
+ stMorph::dilate (_src, temp, kdi , borderType, borderVal);
407
+ stMorph::erode (temp, temp, kdi , borderType, borderVal);
410
408
_dst = temp - _src;
411
409
break ;
412
410
case MORPH_HITMISS:
413
- CV_Assert (_src.type () == CV_8UC1);
414
- if (countNonZero (_kernel) <= 0 )
415
- {
416
- _src.copyTo (_dst);
417
- break ;
418
- }
419
- {
420
- Mat k1, k2, e1 , e2 ;
421
- k1 = (_kernel == 1 );
422
- k2 = (_kernel == -1 );
423
-
424
- if (countNonZero (k1) <= 0 )
425
- e1 = Mat (_src.size (), _src.type (), Scalar (255 ));
426
- else
427
- stMorph::erode (_src, e1 , k1, anchor, iterations, borderType, borderVal);
428
-
429
- if (countNonZero (k2) <= 0 )
430
- e2 = Mat (_src.size (), _src.type (), Scalar (255 ));
431
- else
432
- {
433
- Mat _src_complement;
434
- bitwise_not (_src, _src_complement);
435
- stMorph::erode (_src_complement, e2 , k2, anchor, iterations, borderType, borderVal);
436
- }
437
- _dst = e1 & e2 ;
438
- }
439
- break ;
411
+ CV_Error (cv::Error::StsBadArg, " stMorph doesn't support HITMISS operation" );
440
412
default :
441
413
CV_Error (cv::Error::StsBadArg, " unknown morphological operation" );
442
414
}
443
415
}
444
416
417
+ // ------------------------------------------
418
+ void erode (InputArray src, OutputArray dst, InputArray kernel,
419
+ Point anchor, int iterations,
420
+ BorderTypes borderType, const Scalar& borderVal)
421
+ {
422
+ kernelDecompInfo kdi = getKernelDecompInfo (kernel, anchor, iterations);
423
+ morphOp (Op::Min, src, dst, kdi, borderType, borderVal);
424
+ }
425
+
426
+ void dilate (InputArray src, OutputArray dst, InputArray kernel,
427
+ Point anchor, int iterations,
428
+ BorderTypes borderType, const Scalar& borderVal)
429
+ {
430
+ kernelDecompInfo kdi = getKernelDecompInfo (kernel, anchor, iterations);
431
+ morphOp (Op::Max, src, dst, kdi, borderType, borderVal);
432
+ }
433
+
434
+ void morphologyEx (InputArray src, OutputArray dst, int op,
435
+ InputArray kernel, Point anchor, int iterations,
436
+ BorderTypes borderType, const Scalar& borderVal)
437
+ {
438
+
439
+ Mat _kernel = kernel.getMat ();
440
+ if (_kernel.empty ())
441
+ {
442
+ _kernel = getStructuringElement (MORPH_RECT, Size (3 , 3 ), Point (1 , 1 ));
443
+ }
444
+
445
+ kernelDecompInfo kdi = getKernelDecompInfo (_kernel, anchor, iterations);
446
+ morphologyEx (src, dst, op, kdi, borderType, borderVal);
447
+ }
448
+
445
449
}} // cv::stMorph::
0 commit comments