@@ -257,20 +257,11 @@ void morphDfs(int minmax, Mat& st, Mat& dst,
257257}
258258
259259template <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)
263262{
264263 T nil = (minmax == Op::Min) ? std::numeric_limits<T>::max () : std::numeric_limits<T>::min ();
265264
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-
274265 Mat src = _src.getMat ();
275266 _dst.create (_src.size (), _src.type ());
276267 Mat dst = _dst.getMat ();
@@ -283,163 +274,176 @@ void morphOp(Op minmax, InputArray _src, OutputArray _dst, InputArray kernel,
283274 {
284275 Mat expandedSrc;
285276 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 ,
288279 borderType, bV);
289280 dst.setTo (nil);
290- morphDfs (minmax, expandedSrc, dst, pow2Rects, stPlan , 0 , 0 );
281+ morphDfs (minmax, expandedSrc, dst, kdi. stRects , kdi. plan , 0 , 0 );
291282 src = dst;
292- } while (--iterations > 0 );
283+ } while (--kdi. iterations > 0 );
293284}
294285
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)
298288{
299- Mat kernel = _kernel.getMat ();
300- if (iterations == 0 || kernel.rows * kernel.cols == 1 )
289+ if (kdi.iterations == 0 || kdi.rows * kdi.cols == 1 )
301290 {
302291 _src.copyTo (_dst);
303292 return ;
304293 }
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 ());
318294
319295 switch (_src.depth ())
320296 {
321297 case CV_8U:
322- morphOp<uchar>(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
298+ morphOp<uchar>(minmax, _src, _dst, kdi , borderType, borderVal);
323299 return ;
324300 case CV_8S:
325- morphOp<char >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
301+ morphOp<char >(minmax, _src, _dst, kdi , borderType, borderVal);
326302 return ;
327303 case CV_16U:
328- morphOp<ushort>(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
304+ morphOp<ushort>(minmax, _src, _dst, kdi , borderType, borderVal);
329305 return ;
330306 case CV_16S:
331- morphOp<short >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
307+ morphOp<short >(minmax, _src, _dst, kdi , borderType, borderVal);
332308 return ;
333309 case CV_32S:
334- morphOp<int >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
310+ morphOp<int >(minmax, _src, _dst, kdi , borderType, borderVal);
335311 return ;
336312 case CV_32F:
337- morphOp<float >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
313+ morphOp<float >(minmax, _src, _dst, kdi , borderType, borderVal);
338314 return ;
339315 case CV_64F:
340- morphOp<double >(minmax, _src, _dst, kernel, anchor, iterations , borderType, borderVal);
316+ morphOp<double >(minmax, _src, _dst, kdi , borderType, borderVal);
341317 return ;
342318 }
343319}
344320
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)
348322{
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 };
350350}
351351
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)
355354{
356- morphOp (Op::Min, src, dst, kernel, anchor, iterations , borderType, borderVal);
355+ morphOp (Op::Min, src, dst, kdi , borderType, borderVal);
357356}
358357
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)
362366{
363367 CV_INSTRUMENT_REGION ();
364368
365369 CV_Assert (!src.empty ());
366370
367- Mat _kernel = kernel.getMat ();
368- if (_kernel.empty ())
369- {
370- _kernel = getStructuringElement (MORPH_RECT, Size (3 , 3 ), Point (1 , 1 ));
371- }
372-
373371 Mat _src = src.getMat (), temp;
374372 dst.create (_src.size (), _src.type ());
375373 Mat _dst = dst.getMat ();
376374
377375 switch (op)
378376 {
379377 case MORPH_ERODE:
380- stMorph:: erode (src, dst, kernel, anchor, iterations , borderType, borderVal);
378+ erode (src, dst, kdi , borderType, borderVal);
381379 break ;
382380 case MORPH_DILATE:
383- stMorph:: dilate (src, dst, kernel, anchor, iterations , borderType, borderVal);
381+ dilate (src, dst, kdi , borderType, borderVal);
384382 break ;
385383 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);
388386 break ;
389387 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);
392390 break ;
393391 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);
396394 _dst -= temp;
397395 break ;
398396 case MORPH_TOPHAT:
399397 if (_src.data != _dst.data )
400398 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);
403401 _dst = _src - temp;
404402 break ;
405403 case MORPH_BLACKHAT:
406404 if (_src.data != _dst.data )
407405 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);
410408 _dst = temp - _src;
411409 break ;
412410 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" );
440412 default :
441413 CV_Error (cv::Error::StsBadArg, " unknown morphological operation" );
442414 }
443415}
444416
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+
445449}} // cv::stMorph::
0 commit comments