Emgu CV 角点检测
点是是图像中的特殊位置,是常用且非常实用的一类特征,而点的局部特征也可以叫做“关键特征点”(keypoint feature),或“角点”(conrner)。本文在C#中使用emgu cv中的cvGoodFeaturesToTrack与cvCornerHarris验证了Shi-Tomasi角点与Harris角点,十分有趣哦,上图先。
在Emgu中Shi-Tomasi对应的函数是cvGoodFeaturesToTrack,其函数形式及参数意义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public static void cvGoodFeaturesToTrack( IntPtr image, IntPtr eigImage, IntPtr tempImage, IntPtr corners, ref int cornerCount, double qualityLevel, double minDistance, IntPtr mask, int blockSize, int useHarris, double k ) |

image (IntPtr)The source 8-bit or floating-point 32-bit, single-channel image
eigImage(IntPtr)Temporary floating-point 32-bit image of the same size as image
tempImage(IntPtr)Another temporary image of the same size and same format as eig_image
corners (IntPtr)Output parameter. Detected corners
cornerCount ( Int32 )Output parameter. Number of detected corners
qualityLevel (Double)Multiplier for the maxmin eigenvalue; specifies minimal accepted quality of image corners
minDistance (Double)Limit, specifying minimum possible distance between returned corners; Euclidian distance is used
mask (IntPtr)Region of interest. The function selects points either in the specified region or in the whole image if the mask is NULL
blockSize (Int32)Size of the averaging block, passed to underlying cvCornerMinEigenVal or cvCornerHarris used by the function
useHarris(Int32)If nonzero, Harris operator (cvCornerHarris) is used instead of default cvCornerMinEigenVal.
k (Double)Free parameter of Harris detector; used only if useHarris != 0
Harris角点检测对应的函数是cvCornerHarris,该函数检测的结果实际上是一幅包含Harris角点的浮点型单通道图像。 如果要计算Harris角点列表,可以使用cvGoodFeatureToTrack函数,并传递适当的参数。
1 2 3 4 5 6 7 |
public static void cvCornerHarris( IntPtr image, IntPtr harrisResponce, int blockSize, int apertureSize, double k ) |

image (IntPtr)Input image
harrisResponce (IntPtr)Image to store the Harris detector responces. Should have the same size as image
blockSize (Int32)Neighborhood size
apertureSize (Int32)Aperture parameter for Sobel operator (see cvSobel). format. In the case of floating-point input format this parameter is the number of the fixed float filter used for differencing.
k (Double)Harris detector free parameter.
在Emgu中,大部分函数均需要传递多个参数,我在使用这些函数时通常对参数设置的数量级感到非常疑惑,在CSharp中为这些参数传递指针对于我而言也是一个难题,下面的代码我查阅的很多资料才拼凑出来的,可能效果不是最好的,但是它们可以正常执行,并且基本能满足我的需求,在此记录下来,供需要的同学参考。以下代码使用时,请在工程中包含EMGU的相关引用。
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 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
/* -------------------------------------------------------- * 作者:livezingy * * 博客:http://www.livezingy.com * * 开发环境: * Visual Studio V2012 * .NET Framework 4.5 * emgucv-windows-universal-cuda 2.4.10.1940 * * 版本历史: * V1.0 2015年04月6日 * 用Emgu的相关函数验证图像角点特征的处理 --------------------------------------------------------- */ 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; using ImageProcess; namespace ImageFeatureDetection { public static class ImageFeature { /// <summary> /// 获取图像的Harris角点 /// </summary> /// <param name="imageSrcPath">the path of src image</param> /// <param name="imageDestPath">存储harris角点</param> public static void getCornerHarris(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); CvInvoke.cvThreshold(m_SourceImage, m_ThresholdImage, 0.0001, 255.0, Emgu.CV.CvEnum.THRESH.CV_THRESH_OTSU); Image<Gray, float> m_CornerImage = new Image<Gray, float>(m_SourceImage.Size); CvInvoke.cvCornerHarris(m_SourceImage, m_CornerImage, 3, 3, 0.04); Bitmap bmpCorner = m_CornerImage.ToBitmap(); Bitmap bmpThreshold = m_ThresholdImage.ToBitmap(); bmpCorner.Save(imageDestPath, System.Drawing.Imaging.ImageFormat.Jpeg); } /// <summary> /// 获取图像的ShiTomasi角点 /// </summary> /// <param name="imageSrcPath">the path of src image</param> /// <param name="imageDestPath">存储变换后的图像存储路径角点</param> public static void getCornerShiTomasi(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); CvInvoke.cvThreshold(m_SourceImage, m_ThresholdImage, 0.0001, 255.0, Emgu.CV.CvEnum.THRESH.CV_THRESH_OTSU); Image<Gray, float> m_GoodFeaturesImage = new Image<Gray, float>(m_SourceImage.Size); Image<Gray, float> m_tmpImage = new Image<Gray, float>(m_SourceImage.Size); Image<Gray, float> m_tmpImage1 = new Image<Gray, float>(m_SourceImage.Size); //该变量在函数cvGoodFeaturesToTrack属于输出值,故在此赋值为0 int cornerCount = 0; System.Drawing.PointF[] corners = new PointF[200];//先随意定义一个大小 //C#语言中没有指针的概念,对于没有Ptr属性的对象可用此方法获取对象的指针 GCHandle hObject = GCHandle.Alloc(corners, GCHandleType.Pinned); IntPtr pObject = hObject.AddrOfPinnedObject(); CvInvoke.cvGoodFeaturesToTrack(m_ThresholdImage, m_tmpImage, m_tmpImage1, pObject, ref cornerCount, 0.1, 1, IntPtr.Zero, 3, 0, 0.4); Image<Bgr, Byte> imageResult = m_ThresholdImage.Convert<Bgr, Byte>(); foreach (PointF p in corners) { //将找到的角点用红色圈圈标示出来 imageResult.Draw(new CircleF(p,1), new Bgr(0, 0, 255), 2); } Bitmap bmpCornerShiTomasi = imageResult.ToBitmap(); bmpCornerShiTomasi.Save(imageDestPath, System.Drawing.Imaging.ImageFormat.Jpeg); } } } |