实例介绍
【实例截图】
【核心代码】
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Runtime.InteropServices; using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using Emgu.CV.UI; namespace ImageProcessLearn { public partial class FormFeatureDetection : Form { //成员变量 private string sourceImageFileName = "wky_tms_2272x1704.jpg"; //源图像文件名 private Image<Bgr, Byte> imageSource = null; //源图像 private Image<Gray, Byte> imageSourceGrayscale = null; //灰度源图像 public FormFeatureDetection() { InitializeComponent(); } //加载窗体时 private void FormFeatureDetection_Load(object sender, EventArgs e) { //加载源图像 imageSource = new Image<Bgr, byte>(sourceImageFileName); imageSourceGrayscale = imageSource.Convert<Gray, Byte>(); pbSource.Image = imageSource.Bitmap; pbResult.Image = imageSourceGrayscale.Bitmap; //初始化控件 //Sobel算子 cmbSobelXOrder.SelectedItem = "1"; cmbSobelYOrder.SelectedItem = "0"; cmbSobelApertureSize.SelectedItem = "3"; //拉普拉斯变换 cmbLaplaceApertureSize.SelectedItem = "3"; //Canny算子 cmbCannyApertureSize.SelectedItem = "3"; //Star关键点 cmbStarMaxSize.SelectedItem = "45"; } //加载图像 private void btnLoadImage_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.CheckFileExists = true; ofd.DefaultExt = "jpg"; ofd.Filter = "图片文件|*.jpg;*.png;*.bmp|所有文件|*.*"; if (ofd.ShowDialog(this) == DialogResult.OK) { if (ofd.FileName != "") { sourceImageFileName = ofd.FileName; if (imageSource != null) imageSource.Dispose(); imageSource = new Image<Bgr, byte>(sourceImageFileName); if (imageSourceGrayscale != null) imageSourceGrayscale.Dispose(); imageSourceGrayscale = imageSource.Convert<Gray, Byte>(); pbSource.Image = imageSource.Bitmap; pbResult.Image = imageSourceGrayscale.Bitmap; } } ofd.Dispose(); } //关闭窗体时 private void FormFeatureDetection_FormClosing(object sender, FormClosingEventArgs e) { //释放资源 if (imageSource != null) imageSource.Dispose(); if (imageSourceGrayscale != null) imageSourceGrayscale.Dispose(); } //计算特征 private void btnCalcFeature_Click(object sender, EventArgs e) { string result = ""; if (tcFeatureDetections.SelectedTab == tpSobel) result = SobelFeatureDetect(); //Sobel算子 else if (tcFeatureDetections.SelectedTab == tpLaplace) result = LaplaceFeatureDetect(); //拉普拉斯变换 else if (tcFeatureDetections.SelectedTab == tpCanny) result = CannyFeatureDetect(); //Canny算子 else if (tcFeatureDetections.SelectedTab == tpHoughLines) result = HoughLinesFeatureDetect(); //霍夫线变换 else if (tcFeatureDetections.SelectedTab == tpHoughCircles) result = HoughCirclesFeatureDetect(); //霍夫圆变换 else if (tcFeatureDetections.SelectedTab == tpHarris) result = CornerHarrisFeatureDetect(); //Harris角点 else if (tcFeatureDetections.SelectedTab == tpShiTomasi) result = CornerShiTomasiFeatureDetect();//ShiTomasi角点 else if (tcFeatureDetections.SelectedTab == tpCornerSubPix) result = CornerSubPixFeatureDetect(); //亚像素级角点 else if (tcFeatureDetections.SelectedTab == tpSurf) result = SurfFeatureDetect(); //SURF角点 else if (tcFeatureDetections.SelectedTab == tpStarKeypoints) result = StarKeyPointFeatureDetect(); //Star关键点 else if (tcFeatureDetections.SelectedTab == tpMser) result = MserFeatureDetect(); //MSER区域 else if (tcFeatureDetections.SelectedTab == tpFASTKeypoints) result = FASTKeyPointFeatureDetect(); //FAST关键点 else if (tcFeatureDetections.SelectedTab == tpSift) result = SiftFeatureDetect(); //SIFT关键点 txtResult.Text = result; } //Sobel算子 private string SobelFeatureDetect() { //获取参数 int xOrder = int.Parse((string)cmbSobelXOrder.SelectedItem); int yOrder = int.Parse((string)cmbSobelYOrder.SelectedItem); int apertureSize = int.Parse((string)cmbSobelApertureSize.SelectedItem); if ((xOrder == 0 && yOrder == 0) || (xOrder != 0 && yOrder != 0)) return "Sobel算子,参数错误:xOrder和yOrder中必须且只能有一个非零。\r\n"; //计算 Stopwatch sw = new Stopwatch(); sw.Start(); Image<Gray, Single> imageDest = imageSourceGrayscale.Sobel(xOrder, yOrder, apertureSize); sw.Stop(); //显示 pbResult.Image = imageDest.Bitmap; //释放资源 imageDest.Dispose(); //返回 return string.Format("·Sobel算子,用时{0:F05}毫秒,参数(x方向求导阶数:{1},y方向求导阶数:{2},方形滤波器宽度:{3})\r\n", sw.Elapsed.TotalMilliseconds, xOrder, yOrder, apertureSize); } //拉普拉斯变换 private string LaplaceFeatureDetect() { //获取参数 int apertureSize = int.Parse((string)cmbLaplaceApertureSize.SelectedItem); //计算 Stopwatch sw = new Stopwatch(); sw.Start(); Image<Gray, Single> imageDest = imageSourceGrayscale.Laplace(apertureSize); sw.Stop(); //显示 pbResult.Image = imageDest.Bitmap; //释放资源 imageDest.Dispose(); //返回 return string.Format("·拉普拉斯变换,用时{0:F05}毫秒,参数(方形滤波器宽度:{1})\r\n", sw.Elapsed.TotalMilliseconds, apertureSize); } //Canny算子 private string CannyFeatureDetect() { //获取参数 double lowThresh = double.Parse(txtCannyLowThresh.Text); double highThresh = double.Parse(txtCannyHighThresh.Text); int apertureSize = int.Parse((string)cmbCannyApertureSize.SelectedItem); //计算 Stopwatch sw = new Stopwatch(); sw.Start(); Image<Gray, Byte> imageDest = null; Image<Bgr, Byte> imageDest2 = null; if (rbCannyUseCvCanny.Checked) { imageDest = new Image<Gray, byte>(imageSourceGrayscale.Size); CvInvoke.cvCanny(imageSourceGrayscale.Ptr, imageDest.Ptr, lowThresh, highThresh, apertureSize); } else imageDest2 = imageSource.Canny(new Bgr(lowThresh, lowThresh, lowThresh), new Bgr(highThresh, highThresh, highThresh)); sw.Stop(); //显示 pbResult.Image = rbCannyUseCvCanny.Checked ? imageDest.Bitmap : imageDest2.Bitmap; //释放资源 if (imageDest != null) imageDest.Dispose(); if (imageDest2 != null) imageDest2.Dispose(); //返回 return string.Format("·Canny算子,用时{0:F05}毫秒,参数(方式:{1},阀值下限:{2},阀值上限:{3},方形滤波器宽度:{4})\r\n", sw.Elapsed.TotalMilliseconds, rbCannyUseCvCanny.Checked ? "cvCanny" : "Image<TColor, TDepth>.Canny", lowThresh, highThresh, apertureSize); } //计算自适应的Canny算子阀值 private void btnCannyCalcAdaptiveThresh_Click(object sender, EventArgs e) { int apertureSize = int.Parse((string)cmbCannyApertureSize.SelectedItem); double lowThresh, highThresh; AdaptiveFindCannyThreshold(imageSourceGrayscale, apertureSize, out lowThresh, out highThresh); txtCannyLowThresh.Text = lowThresh.ToString(); txtCannyHighThresh.Text = highThresh.ToString(); } /// <summary> /// 计算图像的自适应Canny算子阀值 /// </summary> /// <param name="imageSrc">源图像,只能是256级灰度图像</param> /// <param name="apertureSize">方形滤波器的宽度</param> /// <param name="lowThresh">阀值下限</param> /// <param name="highThresh">阀值上限</param> unsafe void AdaptiveFindCannyThreshold(Image<Gray, Byte> imageSrc, int apertureSize, out double lowThresh, out double highThresh) { //计算源图像x方向和y方向的1阶Sobel算子 Size size = imageSrc.Size; Image<Gray, Int16> imageDx = new Image<Gray, short>(size); Image<Gray, Int16> imageDy = new Image<Gray, short>(size); CvInvoke.cvSobel(imageSrc.Ptr, imageDx.Ptr, 1, 0, apertureSize); CvInvoke.cvSobel(imageSrc.Ptr, imageDy.Ptr, 0, 1, apertureSize); Image<Gray, Single> image = new Image<Gray, float>(size); int i, j; DenseHistogram hist = null; int hist_size = 255; float[] range_0 = new float[] { 0, 256 }; double PercentOfPixelsNotEdges = 0.7; //计算边缘的强度,并保存于图像中 float maxv = 0; float temp; byte* imageDataDx = (byte*)imageDx.MIplImage.imageData.ToPointer(); byte* imageDataDy = (byte*)imageDy.MIplImage.imageData.ToPointer(); byte* imageData = (byte*)image.MIplImage.imageData.ToPointer(); int widthStepDx = imageDx.MIplImage.widthStep; int widthStepDy = widthStepDx; int widthStep = image.MIplImage.widthStep; for (i = 0; i < size.Height; i ) { short* _dx = (short*)(imageDataDx widthStepDx * i); short* _dy = (short*)(imageDataDy widthStepDy * i); float* _image = (float*)(imageData widthStep * i); for (j = 0; j < size.Width; j ) { temp = (float)(Math.Abs(*(_dx j)) Math.Abs(*(_dy j))); *(_image j) = temp; if (maxv < temp) maxv = temp; } } //计算直方图 range_0[1] = maxv; hist_size = hist_size > maxv ? (int)maxv : hist_size; hist = new DenseHistogram(hist_size, new RangeF(range_0[0], range_0[1])); hist.Calculate<Single>(new Image<Gray, Single>[] { image }, false, null); int total = (int)(size.Height * size.Width * PercentOfPixelsNotEdges); double sum = 0; int icount = hist.BinDimension[0].Size; for (i = 0; i < icount; i ) { sum = hist[i]; if (sum > total) break; } //计算阀值 highThresh = (i 1) * maxv / hist_size; lowThresh = highThresh * 0.4; //释放资源 imageDx.Dispose(); imageDy.Dispose(); image.Dispose(); hist.Dispose(); } //霍夫线变换 private string HoughLinesFeatureDetect() { //获取参数 HOUGH_TYPE method = rbHoughLinesSHT.Checked ? HOUGH_TYPE.CV_HOUGH_STANDARD : (rbHoughLinesPPHT.Checked ? HOUGH_TYPE.CV_HOUGH_PROBABILISTIC : HOUGH_TYPE.CV_HOUGH_MULTI_SCALE); double rho = double.Parse(txtHoughLinesRho.Text); double theta = double.Parse(txtHoughLinesTheta.Text); int threshold = int.Parse(txtHoughLinesThreshold.Text); double param1 = double.Parse(txtHoughLinesParam1.Text); double param2 = double.Parse(txtHoughLinesParam2.Text); MemStorage storage = new MemStorage(); int linesCount = 0; StringBuilder sbResult = new StringBuilder(); //计算,先运行Canny边缘检测(参数来自Canny算子属性页),然后再用计算霍夫线变换 double lowThresh = double.Parse(txtCannyLowThresh.Text); double highThresh = double.Parse(txtCannyHighThresh.Text); int apertureSize = int.Parse((string)cmbCannyApertureSize.SelectedItem); Image<Gray, Byte> imageCanny = new Image<Gray, byte>(imageSourceGrayscale.Size); CvInvoke.cvCanny(imageSourceGrayscale.Ptr, imageCanny.Ptr, lowThresh, highThresh, apertureSize); Stopwatch sw = new Stopwatch(); sw.Start(); IntPtr ptrLines = CvInvoke.cvHoughLines2(imageCanny.Ptr, storage.Ptr, method, rho, theta, threshold, param1, param2); Seq<LineSegment2D> linesSeq = null; Seq<PointF> linesSeq2 = null; if (method == HOUGH_TYPE.CV_HOUGH_PROBABILISTIC) linesSeq = new Seq<LineSegment2D>(ptrLines, storage); else linesSeq2 = new Seq<PointF>(ptrLines, storage); sw.Stop(); //显示 Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); if (linesSeq != null) { linesCount = linesSeq.Total; foreach (LineSegment2D line in linesSeq) { imageResult.Draw(line, new Bgr(255d, 0d, 0d), 4); sbResult.AppendFormat("{0}-{1},", line.P1, line.P2); } } else { linesCount = linesSeq2.Total; foreach (PointF line in linesSeq2) { float r = line.X; float t = line.Y; double a = Math.Cos(t), b = Math.Sin(t); double x0 = a * r, y0 = b * r; int x1 = (int)(x0 1000 * (-b)); int y1 = (int)(y0 1000 * (a)); int x2 = (int)(x0 - 1000 * (-b)); int y2 = (int)(y0 - 1000 * (a)); Point pt1 = new Point(x1, y1); Point pt2 = new Point(x2, y2); imageResult.Draw(new LineSegment2D(pt1, pt2), new Bgr(255d, 0d, 0d), 4); sbResult.AppendFormat("{0}-{1},", pt1, pt2); } } pbResult.Image = imageResult.Bitmap; //释放资源 imageCanny.Dispose(); imageResult.Dispose(); storage.Dispose(); //返回 return string.Format("·霍夫线变换,用时{0:F05}毫秒,参数(变换方式:{1},距离精度:{2},弧度精度:{3},阀值:{4},参数1:{5},参数2:{6}),找到{7}条直线\r\n{8}", sw.Elapsed.TotalMilliseconds, method.ToString("G"), rho, theta, threshold, param1, param2, linesCount, linesCount != 0 ? (sbResult.ToString() "\r\n") : ""); } //霍夫圆变换 private string HoughCirclesFeatureDetect() { //获取参数 double dp = double.Parse(txtHoughCirclesDp.Text); double minDist = double.Parse(txtHoughCirclesMinDist.Text); double param1 = double.Parse(txtHoughCirclesParam1.Text); double param2 = double.Parse(txtHoughCirclesParam2.Text); int minRadius = int.Parse(txtHoughCirclesMinRadius.Text); int maxRadius = int.Parse(txtHoughCirclesMaxRadius.Text); StringBuilder sbResult = new StringBuilder(); //计算 Stopwatch sw = new Stopwatch(); sw.Start(); CircleF[][] circles = imageSourceGrayscale.HoughCircles(new Gray(param1), new Gray(param2), dp, minDist, minRadius, maxRadius); sw.Stop(); //显示 Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); int circlesCount = 0; foreach (CircleF[] cs in circles) { foreach (CircleF circle in cs) { imageResult.Draw(circle, new Bgr(255d, 0d, 0d), 4); sbResult.AppendFormat("圆心{0}半径{1},", circle.Center, circle.Radius); circlesCount ; } } pbResult.Image = imageResult.Bitmap; //释放资源 imageResult.Dispose(); //返回 return string.Format("·霍夫圆变换,用时{0:F05}毫秒,参数(累加器图像的最小分辨率:{1},不同圆之间的最小距离:{2},边缘阀值:{3},累加器阀值:{4},最小圆半径:{5},最大圆半径:{6}),找到{7}个圆\r\n{8}", sw.Elapsed.TotalMilliseconds, dp, minDist, param1, param2, minRadius, maxRadius, circlesCount, sbResult.Length > 0 ? (sbResult.ToString() "\r\n") : ""); } //Harris角点 private string CornerHarrisFeatureDetect() { //获取参数 int blockSize = int.Parse(txtCornerHarrisBlockSize.Text); int apertureSize = int.Parse(txtCornerHarrisApertureSize.Text); double k = double.Parse(txtCornerHarrisK.Text); //计算 Image<Gray, Single> imageDest = new Image<Gray, float>(imageSourceGrayscale.Size); Stopwatch sw = new Stopwatch(); sw.Start(); CvInvoke.cvCornerHarris(imageSourceGrayscale.Ptr, imageDest.Ptr, blockSize, apertureSize, k); sw.Stop(); //显示 pbResult.Image = imageDest.Bitmap; //释放资源 imageDest.Dispose(); //返回 return string.Format("·Harris角点,用时{0:F05}毫秒,参数(邻域大小:{1},方形滤波器宽度:{2},权重系数:{3})\r\n", sw.Elapsed.TotalMilliseconds, blockSize, apertureSize, k); } //ShiTomasi角点 private string CornerShiTomasiFeatureDetect() { //获取参数 int cornerCount = int.Parse(txtGoodFeaturesCornerCount.Text); double qualityLevel = double.Parse(txtGoodFeaturesQualityLevel.Text); double minDistance = double.Parse(txtGoodFeaturesMinDistance.Text); int blockSize = int.Parse(txtGoodFeaturesBlockSize.Text); bool useHarris = cbGoodFeaturesUseHarris.Checked; double k = double.Parse(txtGoodFeaturesK.Text); //计算 Stopwatch sw = new Stopwatch(); sw.Start(); PointF[][] corners = imageSourceGrayscale.GoodFeaturesToTrack(cornerCount, qualityLevel, minDistance, blockSize, useHarris, k); sw.Stop(); //显示 Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); int cornerCount2 = 0; StringBuilder sbResult = new StringBuilder(); int radius = (int)(minDistance / 2) 1; int thickness = (int)(minDistance / 4) 1; foreach (PointF[] cs in corners) { foreach (PointF p in cs) { imageResult.Draw(new CircleF(p, radius), new Bgr(255d, 0d, 0d), thickness); cornerCount2 ; sbResult.AppendFormat("{0},", p); } } pbResult.Image = imageResult.Bitmap; //释放资源 imageResult.Dispose(); //返回 return string.Format("·ShiTomasi角点,用时{0:F05}毫秒,参数(最大角点数目:{1},最小特征值:{2},角点间的最小距离:{3},邻域大小:{4},角点类型:{5},权重系数:{6}),检测到{7}个角点\r\n{8}", sw.Elapsed.TotalMilliseconds, cornerCount, qualityLevel, minDistance, blockSize, useHarris ? "Harris" : "ShiTomasi", k, cornerCount2, cornerCount2 > 0 ? (sbResult.ToString() "\r\n") : ""); } //亚像素级角点 private string CornerSubPixFeatureDetect() { //获取参数 int winWidth = int.Parse(txtCornerSubPixWinWidth.Text); int winHeight = int.Parse(txtCornerSubPixWinHeight.Text); Size win = new Size(winWidth, winHeight); int zeroZoneWidth = int.Parse(txtCornerSubPixZeroZoneWidth.Text); int zeroZoneHeight = int.Parse(txtCornerSubPixZeroZoneHeight.Text); Size zeroZone = new Size(zeroZoneWidth, zeroZoneHeight); int maxIter=int.Parse(txtCornerSubPixMaxIter.Text); double epsilon=double.Parse(txtCornerSubPixEpsilon.Text); MCvTermCriteria criteria = new MCvTermCriteria(maxIter, epsilon); //先计算得到易于跟踪的点(ShiTomasi角点) int cornerCount = int.Parse(txtGoodFeaturesCornerCount.Text); double qualityLevel = double.Parse(txtGoodFeaturesQualityLevel.Text); double minDistance = double.Parse(txtGoodFeaturesMinDistance.Text); int blockSize = int.Parse(txtGoodFeaturesBlockSize.Text); bool useHarris = cbGoodFeaturesUseHarris.Checked; double k = double.Parse(txtGoodFeaturesK.Text); PointF[][] corners = imageSourceGrayscale.GoodFeaturesToTrack(cornerCount, qualityLevel, minDistance, blockSize, useHarris, k); //计算 Stopwatch sw = new Stopwatch(); sw.Start(); imageSourceGrayscale.FindCornerSubPix(corners, win, zeroZone, criteria); sw.Stop(); //显示 Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); int cornerCount2 = 0; StringBuilder sbResult = new StringBuilder(); int radius = (int)(minDistance / 2) 1; int thickness = (int)(minDistance / 4) 1; foreach (PointF[] cs in corners) { foreach (PointF p in cs) { imageResult.Draw(new CircleF(p, radius), new Bgr(255d, 0d, 0d), thickness); cornerCount2 ; sbResult.AppendFormat("{0},", p); } } pbResult.Image = imageResult.Bitmap; //释放资源 imageResult.Dispose(); //返回 return string.Format("·亚像素级角点,用时{0:F05}毫秒,参数(搜索窗口:{1},死区:{2},最大迭代次数:{3},亚像素值的精度:{4}),检测到{5}个角点\r\n{6}", sw.Elapsed.TotalMilliseconds, win, zeroZone, maxIter, epsilon, cornerCount2, cornerCount2 > 0 ? (sbResult.ToString() "\r\n") : ""); } //SURF角点 private string SurfFeatureDetect() { //获取参数 bool getDescriptors = cbSurfGetDescriptors.Checked; MCvSURFParams surfParam = new MCvSURFParams(); surfParam.extended=rbSurfBasicDescriptor.Checked ? 0 : 1; surfParam.hessianThreshold=double.Parse(txtSurfHessianThreshold.Text); surfParam.nOctaves=int.Parse(txtSurfNumberOfOctaves.Text); surfParam.nOctaveLayers=int.Parse(txtSurfNumberOfOctaveLayers.Text); //计算 SURFFeature[] features = null; MKeyPoint[] keyPoints = null; Stopwatch sw = new Stopwatch(); sw.Start(); if (getDescriptors) features = imageSourceGrayscale.ExtractSURF(ref surfParam); else keyPoints = surfParam.DetectKeyPoints(imageSourceGrayscale, null); sw.Stop(); //显示 bool showDetail = cbSurfShowDetail.Checked; Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); StringBuilder sbResult = new StringBuilder(); int idx = 0; if (getDescriptors) { foreach (SURFFeature feature in features) { imageResult.Draw(new CircleF(feature.Point.pt, 5), new Bgr(255d, 0d, 0d), 2); if (showDetail) { sbResult.AppendFormat("第{0}点(坐标:{1},尺寸:{2},方向:{3}°,hessian值:{4},拉普拉斯标志:{5},描述:[", idx, feature.Point.pt, feature.Point.size, feature.Point.dir, feature.Point.hessian, feature.Point.laplacian); foreach (float d in feature.Descriptor) sbResult.AppendFormat("{0},", d); sbResult.Append("]),"); } idx ; } } else { foreach (MKeyPoint keypoint in keyPoints) { imageResult.Draw(new CircleF(keypoint.Point, 5), new Bgr(255d, 0d, 0d), 2); if (showDetail) sbResult.AppendFormat("第{0}点(坐标:{1},尺寸:{2},方向:{3}°,响应:{4},octave:{5}),", idx, keypoint.Point, keypoint.Size, keypoint.Angle, keypoint.Response, keypoint.Octave); idx ; } } pbResult.Image = imageResult.Bitmap; //释放资源 imageResult.Dispose(); //返回 return string.Format("·SURF角点,用时{0:F05}毫秒,参数(描述:{1},hessian阀值:{2},octave数目:{3},每个octave的层数:{4},检测到{5}个角点\r\n{6}", sw.Elapsed.TotalMilliseconds, getDescriptors ? (surfParam.extended == 0 ? "获取基本描述" : "获取扩展描述") : "不获取描述", surfParam.hessianThreshold, surfParam.nOctaves, surfParam.nOctaveLayers, getDescriptors ? features.Length : keyPoints.Length, showDetail ? sbResult.ToString() "\r\n" : ""); } //Star关键点 private string StarKeyPointFeatureDetect() { //获取参数 StarDetector starParam = new StarDetector(); starParam.MaxSize = int.Parse((string)cmbStarMaxSize.SelectedItem); starParam.ResponseThreshold = int.Parse(txtStarResponseThreshold.Text); starParam.LineThresholdProjected = int.Parse(txtStarLineThresholdProjected.Text); starParam.LineThresholdBinarized = int.Parse(txtStarLineThresholdBinarized.Text); starParam.SuppressNonmaxSize = int.Parse(txtStarSuppressNonmaxSize.Text); //计算 Stopwatch sw = new Stopwatch(); sw.Start(); MCvStarKeypoint[] keyPoints = imageSourceGrayscale.GetStarKeypoints(ref starParam); sw.Stop(); //显示 Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); StringBuilder sbResult = new StringBuilder(); int idx = 0; foreach (MCvStarKeypoint keypoint in keyPoints) { imageResult.Draw(new CircleF(new PointF(keypoint.pt.X, keypoint.pt.Y), keypoint.size / 2), new Bgr(255d, 0d, 0d), keypoint.size / 4); sbResult.AppendFormat("第{0}点(坐标:{1},尺寸:{2},强度:{3}),", idx, keypoint.pt, keypoint.size, keypoint.response); idx ; } pbResult.Image = imageResult.Bitmap; //释放资源 imageResult.Dispose(); //返回 return string.Format("·Star关键点,用时{0:F05}毫秒,参数(MaxSize:{1},ResponseThreshold:{2},LineThresholdProjected:{3},LineThresholdBinarized:{4},SuppressNonmaxSize:{5}),检测到{6}个关键点\r\n{7}", sw.Elapsed.TotalMilliseconds, starParam.MaxSize, starParam.ResponseThreshold, starParam.LineThresholdProjected, starParam.LineThresholdBinarized, starParam.SuppressNonmaxSize, keyPoints.Length, keyPoints.Length > 0 ? (sbResult.ToString() "\r\n") : ""); } //获取默认的Star关键点检测参数 private void btnStarGetDefaultParams_Click(object sender, EventArgs e) { StarDetector starParam = new StarDetector(); starParam.SetDefaultParameters(); cmbStarMaxSize.SelectedItem = starParam.MaxSize.ToString(); txtStarResponseThreshold.Text = starParam.ResponseThreshold.ToString(); txtStarLineThresholdProjected.Text = starParam.LineThresholdProjected.ToString(); txtStarLineThresholdBinarized.Text = starParam.LineThresholdBinarized.ToString(); txtStarSuppressNonmaxSize.Text = starParam.SuppressNonmaxSize.ToString(); } //获取默认的MSER参数 private void btnMserGetDefaultParams_Click(object sender, EventArgs e) { MCvMSERParams param = MCvMSERParams.GetDefaultParameter(); txtMserDelta.Text = param.delta.ToString(); txtMserMaxArea.Text = param.maxArea.ToString(); txtMserMinArea.Text = param.minArea.ToString(); txtMserMaxVariation.Text = param.maxVariation.ToString(); txtMserMinDiversity.Text = param.minDiversity.ToString(); txtMserMaxEvolution.Text = param.maxEvolution.ToString(); txtMserAreaThreshold.Text = param.areaThreshold.ToString(); txtMserMinMargin.Text = param.minMargin.ToString(); txtMserEdgeBlurSize.Text = param.edgeBlurSize.ToString(); } //MSER(区域)特征检测 private string MserFeatureDetect() { //获取参数 MCvMSERParams mserParam = new MCvMSERParams(); mserParam.delta = int.Parse(txtMserDelta.Text); mserParam.maxArea = int.Parse(txtMserMaxArea.Text); mserParam.minArea = int.Parse(txtMserMinArea.Text); mserParam.maxVariation = float.Parse(txtMserMaxVariation.Text); mserParam.minDiversity = float.Parse(txtMserMinDiversity.Text); mserParam.maxEvolution = int.Parse(txtMserMaxEvolution.Text); mserParam.areaThreshold = double.Parse(txtMserAreaThreshold.Text); mserParam.minMargin = double.Parse(txtMserMinMargin.Text); mserParam.edgeBlurSize = int.Parse(txtMserEdgeBlurSize.Text); bool showDetail = cbMserShowDetail.Checked; //计算 Stopwatch sw = new Stopwatch(); sw.Start(); MemStorage storage = new MemStorage(); Seq<Point>[] regions = imageSource.ExtractMSER(null, ref mserParam, storage); sw.Stop(); //显示 Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); StringBuilder sbResult = new StringBuilder(); int idx = 0; foreach (Seq<Point> region in regions) { imageResult.DrawPolyline(region.ToArray(), true, new Bgr(255d, 0d, 0d), 2); if (showDetail) { sbResult.AppendFormat("第{0}区域,包含{1}个顶点(", idx, region.Total); foreach (Point pt in region) sbResult.AppendFormat("{0},", pt); sbResult.Append(")\r\n"); } idx ; } pbResult.Image = imageResult.Bitmap; //释放资源 imageResult.Dispose(); storage.Dispose(); //返回 return string.Format("·MSER区域,用时{0:F05}毫秒,参数(delta:{1},maxArea:{2},minArea:{3},maxVariation:{4},minDiversity:{5},maxEvolution:{6},areaThreshold:{7},minMargin:{8},edgeBlurSize:{9}),检测到{10}个区域\r\n{11}", sw.Elapsed.TotalMilliseconds, mserParam.delta, mserParam.maxArea, mserParam.minArea, mserParam.maxVariation, mserParam.minDiversity, mserParam.maxEvolution, mserParam.areaThreshold, mserParam.minMargin, mserParam.edgeBlurSize, regions.Length, showDetail ? sbResult.ToString() : ""); } //FAST关键点 private string FASTKeyPointFeatureDetect() { //获取参数 int threshold = int.Parse(txtFASTThreshold.Text); bool nonmaxSuppression = cbFASTNonmaxSuppression.Checked; bool showDetail = cbFASTShowDetail.Checked; //计算 Stopwatch sw = new Stopwatch(); sw.Start(); MKeyPoint[] keyPoints = imageSourceGrayscale.GetFASTKeypoints(threshold, nonmaxSuppression); sw.Stop(); //显示 Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); StringBuilder sbResult = new StringBuilder(); int idx = 0; foreach (MKeyPoint keypoint in keyPoints) { imageResult.Draw(new CircleF(keypoint.Point, (int)(keypoint.Size / 2)), new Bgr(255d, 0d, 0d), (int)(keypoint.Size / 4)); if (showDetail) sbResult.AppendFormat("第{0}点(坐标:{1},尺寸:{2},方向:{3}°,响应:{4},octave:{5}),", idx, keypoint.Point, keypoint.Size, keypoint.Angle, keypoint.Response, keypoint.Octave); idx ; } pbResult.Image = imageResult.Bitmap; //释放资源 imageResult.Dispose(); //返回 return string.Format("·FAST关键点,用时{0:F05}毫秒,参数(阀值:{1},nonmaxSupression:{2}),检测到{3}个关键点\r\n{4}", sw.Elapsed.TotalMilliseconds, threshold, nonmaxSuppression, keyPoints.Length, showDetail ? (sbResult.ToString() "\r\n") : ""); } //SIFT关键点 private string SiftFeatureDetect() { //获取参数 int noctaves = int.Parse(txtSiftNumberOfOctaves.Text); int nlevels = int.Parse(txtSiftNumberOfLayersPerOctave.Text); int o_min = int.Parse(txtSiftOmin.Text); bool showDetail = cbSiftShowDetail.Checked; bool usePinvoke = rbSiftPinvoke.Checked; if (usePinvoke) return SiftFeatureDetectByPinvoke(noctaves, nlevels, o_min, showDetail); else return SiftFeatureDetectByDotNet(noctaves, nlevels, o_min, showDetail); } //通过P/Invoke调用vlfeat函数来进行SIFT检测 unsafe private string SiftFeatureDetectByPinvoke(int noctaves, int nlevels, int o_min, bool showDetail) { StringBuilder sbResult = new StringBuilder(); //初始化 IntPtr ptrSiftFilt = VlFeatInvoke.vl_sift_new(imageSource.Width, imageSource.Height, noctaves, nlevels, o_min); if (ptrSiftFilt == IntPtr.Zero) return "Sift特征检测:初始化失败。"; //处理 Image<Gray, Single> imageSourceSingle = imageSourceGrayscale.ConvertScale<Single>(1d, 0d); Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); int pointCount = 0; int idx = 0; //依次遍历每一组 if (VlFeatInvoke.vl_sift_process_first_octave(ptrSiftFilt, imageSourceSingle.MIplImage.imageData) != VlFeatInvoke.VL_ERR_EOF) { while (true) { //计算每组中的关键点 VlFeatInvoke.vl_sift_detect(ptrSiftFilt); //遍历并绘制每个点 VlSiftFilt siftFilt = (VlSiftFilt)Marshal.PtrToStructure(ptrSiftFilt, typeof(VlSiftFilt)); pointCount = siftFilt.nkeys; VlSiftKeypoint* pKeyPoints = (VlSiftKeypoint*)siftFilt.keys.ToPointer(); for (int i = 0; i < siftFilt.nkeys; i ) { VlSiftKeypoint keyPoint = *pKeyPoints; pKeyPoints ; imageResult.Draw(new CircleF(new PointF(keyPoint.x, keyPoint.y), keyPoint.sigma / 2), new Bgr(255d, 0d, 0d), 2); if (showDetail) sbResult.AppendFormat("第{0}点,坐标:({1},{2}),阶:{3},缩放:{4},s:{5},", idx, keyPoint.x, keyPoint.y, keyPoint.o, keyPoint.sigma, keyPoint.s); idx ; //计算并遍历每个点的方向 double[] angles = new double[4]; int angleCount = VlFeatInvoke.vl_sift_calc_keypoint_orientations(ptrSiftFilt, angles, ref keyPoint); if (showDetail) sbResult.AppendFormat("共{0}个方向,", angleCount); for (int j = 0; j < angleCount; j ) { double angle = angles[j]; if (showDetail) sbResult.AppendFormat("【方向:{0},描述:", angle); //计算每个方向的描述 IntPtr ptrDescriptors = Marshal.AllocHGlobal(128 * sizeof(float)); VlFeatInvoke.vl_sift_calc_keypoint_descriptor(ptrSiftFilt, ptrDescriptors, ref keyPoint, angle); float* pDescriptors = (float*)ptrDescriptors.ToPointer(); for (int k = 0; k < 128; k ) { float descriptor = *pDescriptors; pDescriptors ; if (showDetail) sbResult.AppendFormat("{0},", descriptor); } sbResult.Append("】,"); Marshal.FreeHGlobal(ptrDescriptors); } } //下一阶 if (VlFeatInvoke.vl_sift_process_next_octave(ptrSiftFilt) == VlFeatInvoke.VL_ERR_EOF) break; } } //显示 pbResult.Image = imageResult.Bitmap; //释放资源 VlFeatInvoke.vl_sift_delete(ptrSiftFilt); imageSourceSingle.Dispose(); imageResult.Dispose(); //返回 return string.Format("·SIFT特征检测(P/Invoke),用时:未统计,参数(阶数:{0},每阶层数:{1},最小阶索引:{2}),{3}个关键点\r\n{4}", noctaves, nlevels, o_min, pointCount, showDetail ? (sbResult.ToString() "\r\n") : ""); } //通过dotnet封装的SiftDetector类来进行SIFT检测 private string SiftFeatureDetectByDotNet(int noctaves, int nlevels, int o_min, bool showDetail) { //初始化对象 SiftDetector siftDetector = new SiftDetector(imageSource.Size, noctaves, nlevels, o_min); //计算 Image<Gray, Single> imageSourceSingle = imageSourceGrayscale.Convert<Gray, Single>(); Stopwatch sw = new Stopwatch(); sw.Start(); List<SiftFeature> features = siftDetector.Process(imageSourceSingle, showDetail ? SiftDetectorResultType.Extended : SiftDetectorResultType.Basic); sw.Stop(); //显示结果 Image<Bgr, Byte> imageResult = imageSourceGrayscale.Convert<Bgr, Byte>(); StringBuilder sbResult = new StringBuilder(); int idx=0; foreach (SiftFeature feature in features) { imageResult.Draw(new CircleF(new PointF(feature.keypoint.x, feature.keypoint.y), feature.keypoint.sigma / 2), new Bgr(255d, 0d, 0d), 2); if (showDetail) { sbResult.AppendFormat("第{0}点,坐标:({1},{2}),阶:{3},缩放:{4},s:{5},", idx, feature.keypoint.x, feature.keypoint.y, feature.keypoint.o, feature.keypoint.sigma, feature.keypoint.s); sbResult.AppendFormat("共{0}个方向,", feature.keypointOrientations != null ? feature.keypointOrientations.Length : 0); if (feature.keypointOrientations != null) { foreach (SiftKeyPointOrientation orientation in feature.keypointOrientations) { if (orientation.descriptors != null) { sbResult.AppendFormat("【方向:{0},描述:", orientation.angle); foreach (float descriptor in orientation.descriptors) sbResult.AppendFormat("{0},", descriptor); } else sbResult.AppendFormat("【方向:{0},", orientation.angle); sbResult.Append("】,"); } } } } pbResult.Image = imageResult.Bitmap; //释放资源 siftDetector.Dispose(); imageSourceSingle.Dispose(); imageResult.Dispose(); //返回 return string.Format("·SIFT特征检测(.net),用时:{0:F05}毫秒,参数(阶数:{1},每阶层数:{2},最小阶索引:{3}),{4}个关键点\r\n{5}", sw.Elapsed.TotalMilliseconds, noctaves, nlevels, o_min, features.Count, showDetail ? (sbResult.ToString() "\r\n") : ""); } } }
标签: 像素
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论