1. 程式人生 > >EmgnCv進行輪廓尋找和計算物體凸包

EmgnCv進行輪廓尋找和計算物體凸包

一、輪廓尋找
用的是FindContours函式,在CvInvoke中
不過需要用到這個VectorOfVectorOfPoint,來代替c++中的Vector
還有就是FindContours函式中的第三個引數hierarchy,不知道作用是什麼,填入的只要是符合IOutputArray型別的都可以執行
程式碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using
System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using Emgu.CV.Util; using Emgu.Util; using Emgu.CV.UI; namespace EmguCVHist { public partial class Form1 : Form { public Form1() { InitializeComponent(); Image<Bgr, byte
> a = new Image<Bgr, byte>("153_140703112619_1.jpg"); Image<Gray, byte> b = new Image<Gray, byte>(a.Width, a.Height); Image<Gray, byte> c = new Image<Gray, byte>(a.Width, a.Height); Image<Bgr, byte> d = new Image<Bgr, byte>(a.Width, a.Height); CvInvoke.Canny(a, b, 100
, 60); VectorOfVectorOfPoint con = new VectorOfVectorOfPoint(); CvInvoke.FindContours(b, con, c, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple); for (int i = 0; i < con.Size; i++) CvInvoke.DrawContours(d, con, i, new MCvScalar(255, 0, 255, 255),2); imageBox1.Image = d; } } }

這裡寫圖片描述

二、凸包的計算
凸包的計算需要用到上面所求得的輪廓尋找的資料
ConvexHull函式的引數之前的不太一樣,換成了PointF型別的,但所求的資料為VectorOfVectorOfPoint型別,所以就需要個轉換,先把VectorOfVectorOfPoint轉為Point的二維陣列,在把二維陣列轉成PointF的二維陣列,然後再挨個呼叫,
程式碼如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using Emgu.Util;
using Emgu.CV.UI;

namespace EmguCVHist
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            Image<Bgr, byte> a = new Image<Bgr, byte>("9660416_102608612175_2.jpg");
            Image <Gray, byte> b = new Image<Gray, byte>(a.Width, a.Height);
            Image<Gray, byte> c = new Image<Gray, byte>(a.Width, a.Height);
            Image<Bgr, byte> d = new Image<Bgr, byte>(a.Width, a.Height);
            CvInvoke.Canny(a, b, 100, 60);
            VectorOfVectorOfPoint con = new VectorOfVectorOfPoint();
            CvInvoke.FindContours(b, con, c, RetrType.Ccomp, ChainApproxMethod.ChainApproxSimple);

            Point[][] con1 = con.ToArrayOfArray();
            PointF[][] con2 = Array.ConvertAll<Point[], PointF[]>(con1, new Converter<Point[], PointF[]>(PointToPointF));
            for (int i = 0; i < con.Size; i++)
            {
                PointF[] hull = CvInvoke.ConvexHull(con2[i], true);
                for (int j = 0; j < hull.Length; j++)
                {
                    Point p1 = new Point((int)(hull[j].X + 0.5), (int)(hull[j].Y + 0.5));
                    Point p2;
                    if (j == hull.Length - 1)
                        p2 = new Point((int)(hull[0].X + 0.5), (int)(hull[0].Y + 0.5));
                    else
                        p2 = new Point((int)(hull[j + 1].X + 0.5), (int)(hull[j + 1].Y + 0.5));
                    CvInvoke.Circle(d, p1, 3, new MCvScalar(0, 255, 255, 255), 6);
                    CvInvoke.Line(d, p1, p2, new MCvScalar(255, 255, 0, 255), 3);
                }
            }
            for (int i = 0; i < con.Size; i++)
                CvInvoke.DrawContours(d, con, i, new MCvScalar(255, 0, 255, 255), 2);

            imageBox1.Image = a.ConcateVertical(d);
        }
        public static PointF[] PointToPointF(Point[] pf)
        {
            PointF[] aaa = new PointF[pf.Length];
            int num = 0;
            foreach(var point in pf)
            {
                aaa[num].X = (int)point.X;
                aaa[num++].Y = (int)point.Y;
            }
            return aaa;
        }
    }
}

執行圖:(之前那個圖片由於會被分為好多塊,所以換了張圖片)
這裡寫圖片描述