2015年4月23日
C#中cvFindContours与cvDrawContours使用方法
cvFindContours可以从二值图像中检索轮廓,并返回检测到的轮廓的个数,cvDrawContours则可用于绘制cvFindContours函数所找到的轮廓。这两个函数均为OPENCV图像处理库中的函数,我们在C#中要借助于EMGU,通过CvInvoke来调用这两个函数。斗胆借用人气王—-挖掘机的肖像来演示这两个函数的效果,见下图。
这两个函数的在C#中的用法大家可以参考后面的代码,各参数的意义大家百度一下就能找到,要想理解更深刻,还是要自己去尝试更改每个参数的值,去观察最终的效果。我这里记录一下我在使用这两个函数时的遇到的难点,目前我暂时只知道怎样做是正确的,还不知道为什么这样做是正确的,还希望后面能理解,若有高手愿意指点一二,那更是感激不尽:
1. cvFindContours的输入必须是二值化图像,应此源图像必须经过cvThreshold或者cvCanny或者其他的二值化方法处理;
2. cvFindContours的第4个参数即(int headerSize),EMGU官网中的说明是这样的:
Size of the sequence header, >=sizeof(CvChain) if method=CV_CHAIN_CODE, and >=sizeof(CvContour) otherwise
但实际上,EMGU中没有CvContour这样的东东,只有MCvContour,但直接使用sizeof(MCvContour) 是不行的,用如下方式才可以:
1 2 |
MCvContour con = new MCvContour(); Marshal.SizeOf(con)//以此形式作为cvFindContours的第4个参数 |
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
/* -------------------------------------------------------- * 作者:livezingy * * 博客:http://www.livezingy.com * * 开发环境: * Visual Studio V2012 * .NET Framework 4.5 * emgucv-windows-universal-cuda 2.4.10.1940 * * 版本历史: * V1.0 2015年04月23日 * 尝试使用cvFindContours与cvDrawContours来寻找与绘制图像轮廓 --------------------------------------------------------- */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; using Emgu.CV; using Emgu.CV.UI; using Emgu.Util; using Emgu.CV.Structure; /// <summary> /// 获取图像的轮廓 /// </summary> /// <param name="imageSrcPath">the path of src image</param> /// <param name="imageDestPath">存储图像轮廓</param> public static void getContours(string imageSrcPath, string imageDestPath) { Image<Gray, Byte> m_SourceImage = new Image<Gray, byte>(imageSrcPath); Image<Gray, Byte> m_ThresholdImage = new Image<Gray, Byte>(m_SourceImage.Size); Image<Gray, Byte> m_CannyImage = new Image<Gray, Byte>(m_SourceImage.Size); Image<Gray, Byte> m_ContoursImage = new Image<Gray, Byte>(m_SourceImage.Size); IntPtr Dynstorage = CvInvoke.cvCreateMemStorage(0); CvInvoke.cvThreshold(m_SourceImage, m_ThresholdImage, 0.0001, 255.0, Emgu.CV.CvEnum.THRESH.CV_THRESH_OTSU); CvInvoke.cvCanny(m_SourceImage, m_CannyImage, 0, 255, 3); IntPtr Dyncontour = new IntPtr();//存放检测到的图像块的首地址 MCvContour con = new MCvContour();////////////////////////////////////// CvInvoke.cvFindContours(m_ThresholdImage, Dynstorage, ref Dyncontour, Marshal.SizeOf(con), Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_LINK_RUNS, new Point(0, 0)); CvInvoke.cvDrawContours(m_ContoursImage, Dyncontour, new MCvScalar(255, 255, 255), new MCvScalar(255, 255, 255), 2, 1, Emgu.CV.CvEnum.LINE_TYPE.CV_AA, new Point(0, 0)); Bitmap bmp = m_ContoursImage.ToBitmap(); bmp.Save(imageDestPath, System.Drawing.Imaging.ImageFormat.Jpeg); } |
我来坐下沙发