1. 程式人生 > 其它 >OpenCV筆記(7) 輪廓

OpenCV筆記(7) 輪廓

    目錄

  • 查詢輪廓
  • 繪製輪廓
  • 連通區域分析
  • 多邊形輪廓
  • 獲得矩形包圍框
  • 獲得輪廓凸包

1.查詢輪廓

public static void FindContours(InputOutputArray image, //輸入8-bit單通道的圖片
                    out Mat[] contours, //一組陣列,contours[i]是一條輪廓,而contours[i][j]是點
                    OutputArray hierarchy, //輸出一個數組,表示輪廓的樹結構,每個值都是四元陣列
                    RetrievalModes mode, //輪廓提取方式

                    ContourApproximationModes method, //輪廓如何被表達
                    Point? offset = null); public static void FindContours(InputOutputArray image,
                    out Point[][] contours,
                    out HierarchyIndex[] hierarchy,
                    RetrievalModes mode,
                    ContourApproximationModes method,
                    Point? offset = null
);

2. 繪製輪廓

public static void DrawContours(InputOutputArray image, 
                    IEnumerable<Mat> contours,
                    int contourIdx, //需要繪製的輪廓索引,若為負,繪製所有輪廓
                    Scalar color, //顏色
                    int thickness = 1, //線粗
                    LineTypes lineType = LineTypes.Link8, //四聯通、八聯通、AA線

                    Mat hierarchy = null,
                    int maxLevel = int.MaxValue,
                    Point? offset = null); public static void DrawContours(InputOutputArray image,
                    IEnumerable<IEnumerable<Point>> contours,
                    int contourIdx,
                    Scalar color,
                    int thickness = 1,
                    LineTypes lineType = LineTypes.Link8,
                    IEnumerable<HierarchyIndex> hierarchy = null,
                    int maxLevel = int.MaxValue, Point? offset = null);

示例:滑動條和找輪廓

程式碼:

using System;
using OpenCvSharp;

namespace ConsoleApp2
{
    class Program
    {

        static void Main(string[] args)
        {
            Mat g_gray = new Mat();
            Mat g_binary = new Mat();
            int g_thresh = 100;
            void on_trackbar(int pos, object userdata)
            {
                Cv2.Threshold((Mat)userdata, g_binary, pos, 255, ThresholdTypes.BinaryInv);
                Point[][] contours; HierarchyIndex[] hierarchy;
                Cv2.FindContours(g_binary, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
                Mat mask = new Mat(g_binary.Rows, g_binary.Cols, MatType.CV_8UC1, new Scalar(0));
                Cv2.DrawContours(mask, contours, -1, new Scalar(255));
                Cv2.ImShow("Contours", mask);
            }
            g_gray = Cv2.ImRead("C:\\Users\\ATWER\\Desktop\\b.png",ImreadModes.Grayscale);
            Cv2.ImShow("gray", g_gray);
            CvTrackbar cvTrackbar = new CvTrackbar("Threshold", "gray", g_thresh, 255, on_trackbar,g_gray);
            Cv2.ImShow("gray", g_gray);
            Cv2.WaitKey(0);
        }
    }
}

3. 查詢連通區域

示例:

using System;
using OpenCvSharp;

namespace ConsoleApp2
{
    class Program
    {

        static void Main(string[] args)
        {
            
            Mat img = Cv2.ImRead("C:\\Users\\ATWER\\Desktop\\c.png"); 
            Mat labelMat = new Mat(); Mat stats = new Mat();
            Mat centroids = new Mat();
            Cv2.CvtColor(img, img, ColorConversionCodes.BGR2GRAY);           
       Cv2.NamedWindow(
"img",WindowMode.Normal);        Cv2.ImShow("img", img); int num = Cv2.ConnectedComponentsWithStats(img, labelMat, stats, centroids, PixelConnectivity.Connectivity4); Console.WriteLine(num.ToString()); for (int i = 0; i < num; i++) { double a = centroids.At<double>(i, 0); double b = centroids.At<double>(i, 1); Point point = new OpenCvSharp.Point(a, b); Cv2.Circle(img, point, 2, new Scalar(0, 0, 255)); int x = stats.At<int>(i, 0); int y = stats.At<int>(i, 1); int width = stats.At<int>(i, 2); int height = stats.At<int>(i, 3); Rect rect = new Rect(x, y, width, height); Cv2.Rectangle(img, rect, new Scalar(255)); } Cv2.NamedWindow("繪製質心", WindowMode.Normal); Cv2.ImShow("繪製質心", img); Cv2.WaitKey(0); } } }

4. 多邊形逼近輪廓ApproxPolyDP()

public static void ApproxPolyDP(InputArray curve, 
                    OutputArray approxCurve,
                    double epsilon,
                    bool closed);

示例:多邊形逼近一個圓的外輪廓

程式碼:

using System;
using System.Numerics;
using OpenCvSharp;
namespace ConsoleApp10
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat img = new Mat();
            Mat src = Cv2.ImRead("D:\\Backup\\桌面\\c.png");
        //預處理 Cv2.CvtColor(src, img, ColorConversionCodes.BGR2GRAY); Cv2.BitwiseNot(img, img); Cv2.Threshold(img, img,
128, 255, ThresholdTypes.Binary); Cv2.ImShow("img", img);
        //查詢輪廓 Mat[] contours; Mat hierarchy
= new Mat(); Cv2.FindContours(img,out contours, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple); Mat[] contours_poly = (Mat[])contours.Clone(); //Cv2.DrawContours(img, contours, -1, new Scalar(255),5); for (int i = 0; i < contours.Length; i++) { Cv2.ApproxPolyDP(contours[i], contours_poly[i], 10, true);//多邊形逼近 }
        //繪製輪廓 Cv2.DrawContours(src, contours_poly,
-1, new Scalar(0,255, 0),2); Cv2.ImShow("a", src); Cv2.WaitKey(0); } } }

5.獲得矩形包圍框

public static Rect BoundingRect(InputArray curve);
public static RotatedRect MinAreaRect(InputArray points);

示例:

程式碼:

using System;
using System.Numerics;
using OpenCvSharp;
namespace ConsoleApp10
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat img = new Mat();
            Mat src = Cv2.ImRead("D:\\Backup\\桌面\\c.png");
            Cv2.ImShow("src", src);
            Cv2.CvtColor(src, img, ColorConversionCodes.BGR2GRAY);
            Cv2.BitwiseNot(img, img);
            Cv2.Threshold(img, img, 128, 255, ThresholdTypes.Binary);
            Cv2.ImShow("img", img);
            //查詢輪廓
       Mat[] contours; Mat hierarchy
= new Mat(); Cv2.FindContours(img,out contours, hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple); Mat[] contours_poly = (Mat[])contours.Clone(); for (int i = 0; i < contours.Length; i++) { Cv2.ApproxPolyDP(contours[i], contours_poly[i], 10, true); //獲得輪廓長度 double len = Cv2.ArcLength(contours_poly[i], true); Console.WriteLine(len.ToString()); //獲得矩形包圍框 Rect rect = Cv2.BoundingRect(contours_poly[i]); Cv2.Rectangle(src, rect, new Scalar(0),5); //獲得最小矩形框 RotatedRect rect_rotate = Cv2.MinAreaRect(contours_poly[i]); Console.WriteLine(rect_rotate.Angle.ToString()); }
        //繪製輪廓 Cv2.DrawContours(src, contours_poly,
-1, new Scalar(0,255, 0),2); Cv2.ImShow("a", src); Cv2.WaitKey(0); } } }

6. 獲得輪廓凸包

public static void ConvexHull(InputArray points, 
                  OutputArray hull,
                  bool clockwise = false,
                  bool returnPoints = true);

示例:

程式碼:

using System;
using System.Numerics;
using OpenCvSharp;
namespace ConsoleApp10
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat img = new Mat();
            Mat src = Cv2.ImRead("D:\\Backup\\桌面\\d.png");
            Cv2.ImShow("src", src);
            Cv2.CvtColor(src, img, ColorConversionCodes.BGR2GRAY);
            Cv2.BitwiseNot(img, img);
            Cv2.Threshold(img, img, 128, 255, ThresholdTypes.Binary);
            Cv2.ImShow("img", img);
        //查詢輪廓 Mat[] contours; Mat hierarchy
= new Mat(); Cv2.FindContours(img,out contours, hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple);
        //凸包 居然想不到第二個方法把hulls畫出來 Mat hulls
= new Mat(); Cv2.ConvexHull(contours[0],hulls,false); Mat[] r = new Mat[] { hulls };         //繪製輪廓 Cv2.DrawContours(src, r, -1, new Scalar(0, 255, 0), 2); Cv2.ImShow("a", src); Cv2.WaitKey(0); } } }

源自:蝴蝶書第十四章輪廓