25-轮廓最小外接矩形(minAreaRect())(EmguCV学习)

文章目录

说明

1、MinAreaRect()函数可以寻找最小外接矩形;返回一个旋转矩形,旋转矩形的旋转角度一定是负(angle < 0),表示逆时针旋转,顺时针为正;
在这里插入图片描述
在这里插入图片描述
2、最小外接矩形可以用来进行矩形的旋转校正(应用);

Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Util;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using System.Drawing;

namespace lesson25
{
    class Program
    {
        static void Main(string[] args)
        {
            //旋转矩形
            //Mat src = CvInvoke.Imread("mask2.jpg");
            //Mat dst = src.Clone();
            //Mat grayimg = new Mat();
            //CvInvoke.Imshow("input", src);
            //CvInvoke.CvtColor(src, grayimg, ColorConversion.Bgr2Gray);
            //CvInvoke.Threshold(grayimg, grayimg, 100, 255, ThresholdType.Binary);
            //VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            //VectorOfRect hierarchy = new VectorOfRect();
            //CvInvoke.FindContours(grayimg, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxNone);
            //CvInvoke.DrawContours(dst, contours, -1, new MCvScalar(255, 255, 0), 2);
            //for (int i = 0; i < contours.Size; i++)
            //{
            //    RotatedRect rotatedRect = CvInvoke.MinAreaRect(contours[i]);  //计算最小外接矩形
            //    PointF[] pointFs = new PointF[4];                             //存储旋转矩形的4个顶点
            //    pointFs = rotatedRect.GetVertices();
            //    CvInvoke.PutText(dst, "rotated rectangle", new Point((int)pointFs[1].X, (int)pointFs[1].Y), FontFace.HersheyDuplex,
            //        1.2, new MCvScalar(0, 0, 255), 2);
            //    for (int j = 0; j < 4; j++)
            //    {
            //        CvInvoke.Line(dst, new Point((int)pointFs[j].X, (int)pointFs[j].Y), new Point((int)pointFs[(j + 1) % 4].X, (int)pointFs[(j + 1) % 4].Y),
            //            new MCvScalar(0, 0, 255), 2);
            //    }
            //}
            //CvInvoke.Imshow("result", dst);
            //CvInvoke.WaitKey(0);

            ///测量物体宽高
            //Mat src = CvInvoke.Imread("cup.jpg");
            //Mat dst = src.Clone();
            //Mat grayImg = new Mat();
            //CvInvoke.Imshow("input", src);
            //CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
            //CvInvoke.Threshold(grayImg, grayImg, 100, 255, ThresholdType.BinaryInv);
            //CvInvoke.Imshow("binary image", grayImg);
            //VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            //VectorOfRect hierarchy = new VectorOfRect();
            //CvInvoke.FindContours(grayImg, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxNone);
            //CvInvoke.DrawContours(dst, contours, -1, new MCvScalar(0, 255, 0), 3);
            //for(int i = 0; i < contours.Size;i++)
            //{
            //    RotatedRect rotatedRect = CvInvoke.MinAreaRect(contours[i]);
            //    Rectangle rectangle = CvInvoke.BoundingRectangle(contours[i]);
            //    CvInvoke.Rectangle(dst, rectangle, new MCvScalar(255, 255, 0), 2);
            //    PointF[] pFs = new PointF[4];
            //    pFs = rotatedRect.GetVertices();
            //    for(int j = 0; j < 4; j++)
            //    {
            //        CvInvoke.Line(dst, new Point((int)pFs[j].X, (int)pFs[j].Y), new Point((int)pFs[(j + 1) % 4].X, (int)pFs[(j + 1) % 4].Y),
            //            new MCvScalar(0, 0, 255), 2);
            //    }
            //    string strwidth = String.Format("Width = {0:N2}.", rotatedRect.Size.Width);
            //    string strheight = String.Format("Height = {0:N2}.", rotatedRect.Size.Height);
            //    CvInvoke.PutText(dst, strwidth, new Point(rectangle.X, rectangle.Y - 25), FontFace.HersheyComplexSmall,
            //        1.2, new MCvScalar(0, 255, 0), 2);
            //    CvInvoke.PutText(dst, strheight, new Point(rectangle.X, rectangle.Y - 2), FontFace.HersheyComplexSmall,
            //        1.2, new MCvScalar(0, 255, 0), 2);
            //}
            //CvInvoke.Imshow("result", dst);
            //CvInvoke.WaitKey(0);

            ///二维码选装校正
            Mat src = CvInvoke.Imread("qrcode.jpg");
            Mat dst = src.Clone();
            Mat result = new Mat();
            CvInvoke.Imshow("input", src);
            Mat grayImg = new Mat();
            CvInvoke.CvtColor(src, grayImg, ColorConversion.Bgr2Gray);
            CvInvoke.AdaptiveThreshold(grayImg, grayImg, 255, AdaptiveThresholdType.GaussianC, ThresholdType.BinaryInv, 11, 5);
            CvInvoke.MedianBlur(grayImg, grayImg, 5);
            CvInvoke.Imshow("binary", grayImg);

            Mat kernel = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(11, 11), new Point(-1, -1));
            Mat kerne2 = CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(3, 3), new Point(-1, -1));
            CvInvoke.Dilate(grayImg, grayImg, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());  //膨胀连通区域
            CvInvoke.Imshow("dilate", grayImg);
            CvInvoke.Erode(grayImg, grayImg, kernel, new Point(-1, -1), 1, BorderType.Default, new MCvScalar());
            CvInvoke.Imshow("erode", grayImg);

            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            VectorOfRect hierarchy = new VectorOfRect();
            CvInvoke.FindContours(grayImg, contours, hierarchy, RetrType.External, ChainApproxMethod.ChainApproxNone);
            
            for(int i = 0; i < contours.Size; i++)
            {
                RotatedRect rotatedRect = CvInvoke.MinAreaRect(contours[i]);
                PointF[] pFs = new PointF[4];
                Mat rotateMat = new Mat();
                double angle = 0.0;         //度数
                double rWidth = rotatedRect.Size.Width;
                double rHeight = rotatedRect.Size.Height;
                if(rWidth > 50 && rHeight > 50)                 //对轮廓进行筛选
                {
                    pFs = rotatedRect.GetVertices();
                    Point[] pTs = new Point[4];
                    angle = rotatedRect.Angle;
                    for(int j = 0; j < 4;j++)
                    {
                        pTs[j].X = (int)pFs[j].X;
                        pTs[j].Y = (int)pFs[j].Y;
                    }
                    CvInvoke.Polylines(dst, pTs, true, new MCvScalar(0, 0, 255), 2);        //绘制闭合多边形

                    if(0 < Math.Abs(angle) && Math.Abs(angle) <= 45)        //逆时针
                    {
                        angle = angle;
                    }
                    else if(45 < Math.Abs(angle) && Math.Abs(angle) < 90)  //顺时针
                    {
                        angle = 90 - Math.Abs(angle);
                    }

                    CvInvoke.GetRotationMatrix2D(rotatedRect.Center, angle, 1.0, rotateMat);  //获取旋转矩阵
                    CvInvoke.WarpAffine(src, result, rotateMat, src.Size);          //进行仿射变换

                    CvInvoke.Imshow("result111", result);

                }
            }

            CvInvoke.Imshow("result", dst);
            
            CvInvoke.WaitKey(0);
        }
    }
}

效果

1、旋转矩形
在这里插入图片描述在这里插入图片描述
2、测量物体的像素宽高:
在这里插入图片描述
3、二维码旋转校正:

在这里插入图片描述

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章