OpenCV笔记(7) 轮廓

1. 查找轮廓 FindContours

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. 绘制轮廓 DrawContours

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. 查找连通区域 ConnectedComponentsWithStats

示例:连通区域

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. 获得矩形包围框 BoundingRect

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. 获得轮廓凸包 ConvexHull

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); } } }

7. Tips

学到一个新知识点,在二值化和查找轮廓之间,运用开运算,可以去除小的区域干扰。相比于在for循环遍历中再判断大小,要更节约时间。——2021.10.18

 

 

源自:蝴蝶书第十四章轮廓

posted @ 2021-09-17 20:48  湾仔码农  阅读(595)  评论(0编辑  收藏  举报