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、二維碼旋轉校正:

在這裏插入圖片描述

在這裏插入圖片描述

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