OpenCvSharp函数:ApproxPolyDP轮廓逼近

ApproxPolyDP轮廓逼近

函数说明:使用道格拉斯-普克算法(Douglas–Peucker algorithm)获取一个小于或等于指定精度(epsilon)的更少坐标集的轮廓(或曲线)。图片来自(道格拉斯普克算法)

OpenCvSharp函数:ApproxPolyDP轮廓逼近_第1张图片
//函数原型1
void ApproxPolyDP(InputArray curve,
    OutputArray approxCurve,
    double epsilon,
    bool closed)

//函数原型2
Point[] ApproxPolyDP(IEnumerable curve,
    double epsilon,
    bool closed)

//函数原型3
Point2f[] ApproxPolyDP(IEnumerable curve,
    double epsilon,
    bool closed)

参数

说明

InputArray curve

IEnumerable curve

IEnumerable curve

待计算的轮廓(曲线)

double epsilon

近似精度,为逼近结果与原轮廓(曲线)的最大差值

bool closed

轮廓(曲线)是否闭合

返回值OutputArray approxCurve

返回逼近后的轮廓(曲线)坐标集

图像示例

原图

OpenCvSharp函数:ApproxPolyDP轮廓逼近_第2张图片

逼近并矫正后结果

通过轮廓发现的轮廓个数是2864(蓝色边框),轮廓逼近后个数只剩4个(红点)

OpenCvSharp函数:ApproxPolyDP轮廓逼近_第3张图片

源代码示例

public void Run()
{
    using (var src = Cv2.ImRead(ImagePath.Book, ImreadModes.Color))
    {
        if (src.Empty()) throw new Exception("图像读取有误");
        var srcWinName = "src";

        ResizeWin(srcWinName, src);
        Cv2.ImShow("src", src);                

        using (var srcGray = new Mat())
        {
            Cv2.CvtColor(src, srcGray, ColorConversionCodes.BGR2GRAY);
            //中值模糊
            Cv2.MedianBlur(srcGray, srcGray, 15);
            //Otsu二值化
            Cv2.Threshold(srcGray, srcGray, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.BinaryInv);

            var srcGrayWinName = "srcGray";
            ResizeWin(srcGrayWinName, srcGray);
            Cv2.ImShow(srcGrayWinName, srcGray);

            //轮廓发现
            Cv2.FindContours(srcGray, out Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

            //找到最大轮廓
            var maxIndex = -1;
            double maxContourArea = 0;
            for (int index = 0; index < contours.Length; index++)
            {
                var area = Cv2.ContourArea(contours[index]);
                if (maxContourArea > area) continue;
                maxIndex = index;
                maxContourArea = area;
            }

            if (maxIndex > -1)
            {
                //绘制未逼近前的轮廓
                Cv2.DrawContours(src, new Point[][] { contours[maxIndex] }, -1, Scalar.Blue, 5);

                //轮廓逼近参数
                var epsilon = Cv2.ArcLength(contours[maxIndex], true) * 0.1;
                //轮廓逼近
                var approxContour = Cv2.ApproxPolyDP(contours[maxIndex], epsilon, true);

                //标记逼近后轮廓点
                foreach (var point in approxContour)
                {
                    Cv2.Circle(src, point, 10, Scalar.Red, -1);
                }

                //获取轮廓最小外接矩形(图像中书不是平行四边形,应该用霍夫变换的,但还没研究,先用这个简单处理吧)
                var RotatedRect = Cv2.MinAreaRect(approxContour);

                //获取旋转矩形,Angle为正数时是逆时针
                var rotMat = Cv2.GetRotationMatrix2D(RotatedRect.Center, RotatedRect.Angle, 1);

                //每个通道分开仿射变换
                var splits = Cv2.Split(src);
                for (int i = 0; i < splits.Length; i++)
                {
                    var dst = new Mat();
                    //仿射变换
                    Cv2.WarpAffine(splits[i], dst, rotMat, srcGray.Size());
                    splits[i] = dst;
                }
                Cv2.Merge(splits, src);

                //转化率逼近前后的个数
                Cv2.PutText(src, $"Before ApproxPolyDP Contour count={contours[maxIndex].Length},after ={approxContour.Length}", new Point(50, 50), HersheyFonts.HersheySimplex, 1.5, Scalar.Red,5);

                var srcResult = "ApproxPolyDP";
                ResizeWin(srcResult, src);
                Cv2.ImShow(srcResult, src);
            }                    
        }
    }
    Cv2.WaitKey();
    Cv2.DestroyAllWindows();
}

/// 
/// 缩放窗口
/// 
/// 
/// 
/// 
private void ResizeWin(string winName, Mat mat, int newWidth = 600)
{
    Cv2.NamedWindow(winName, WindowFlags.KeepRatio);
    Cv2.ResizeWindow(winName, newWidth, (int)(mat.Height * newWidth / mat.Width));
}

今天是女神节,祝天下女神们节日快乐!

OpenCvSharp函数示例(目录)

参考

https://edu.csdn.net/learn/38286/608280

https://docs.opencv.org/

你可能感兴趣的:(OpenCvSharp函数,opencv,c#,图像处理)