基本信息
源码名称:像素处理
源码大小:0.02M
文件格式:.rar
开发语言:C#
更新时间:2016-06-01
友情提示:(无需注册或充值,赞助后即可获取资源下载链接)
嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300
本次赞助数额为: 2 元×
微信扫码支付:2 元
×
请留下您的邮箱,我们将在2小时内将文件发到您的邮箱
源码介绍
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") : "");
}
}
}