一、前文
Canny边缘检测算法,Canny是一个人名
Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:
(1) 最优检测:算法能够尽可能多地标识出图像中的实际边缘,漏检真实边缘的概率和误检非边缘的概率都尽可能小;
(2) 最优定位准则:检测到的边缘点的位置距离实际边缘点的位置最近,或者是由于噪声影响引起检测出的边缘偏离物体的真实边缘的程度最小;
(3) 检测点与边缘点一一对应:算子检测的边缘点与实际边缘点应该是一一对应。
二、Canny边缘检测算法流程
- 应用高斯滤波来平滑图像,目的是去除噪声
- 找寻图像的强度梯度(intensity gradients)
- 应用非最大抑制(non-maximum suppression)技术来消除边误检(本来不是但检测出来是)
- 应用双阈值的方法来决定可能的(潜在的)边界
- 利用滞后技术来跟踪边界
三、界面布局
- 一个
Label
- N个
Button
- 三个
Picture
四、功能实现
4.1 打开图片
private void openFileBtn_Click(object sender, EventArgs e)
{
OpenFileDialog openfiledialog = new OpenFileDialog();
openfiledialog.Filter = "PNG Files (*.png)|*.png|JPG Files (*.jpg)|*.jpg|GIF Files (*.gif)|*.gif";
openfiledialog.RestoreDirectory = true;
if (openfiledialog.ShowDialog() == DialogResult.OK)
{
Console.WriteLine(openfiledialog.FileName);
fileName = openfiledialog.FileName;
//Mat src = new Mat("foo.png", LoadMode.Color);
Mat src = new Mat(fileName);
//Mat src = new Mat(fileName, ImreadModes.Color);
var frameBitmap = BitmapConverter.ToBitmap(src);
pictureBox1.Image?.Dispose();
pictureBox1.Image = frameBitmap;
}
}
4.2 Canny边缘检测—源码
private void threshold1ScrollBar_Scroll(object sender, ScrollEventArgs e)
{
threshold1Label.Text = threshold1ScrollBar.Value + "";
cannyBtn_Click(sender, e);
}
private void threshold2ScrollBar_Scroll(object sender, ScrollEventArgs e)
{
threshold2Label.Text = threshold2ScrollBar.Value + "";
cannyBtn_Click(sender, e);
}
private void cannyBtn_Click(object sender, EventArgs e)
{
GaussianBlurBtn_Click(sender, e);
edges = new Mat(mInput.Rows, mInput.Cols, MatType.CV_8UC4);
double threshold1 = threshold1ScrollBar.Value;
double threshold2 = threshold2ScrollBar.Value;
int apertureSize = 3;
Cv2.Canny(blur, edges, threshold1, threshold2, apertureSize); //边缘检测
srcPictureBox.Image = BitmapConverter.ToBitmap(mInput);
grayPictureBox.Image = BitmapConverter.ToBitmap(blur);
dstPictureBox.Image = BitmapConverter.ToBitmap(edges);
}
4.3 Canny边缘检测—参数讲解
//
// 摘要:
// Finds edges in an image using Canny algorithm.
//
// 参数:
// src:
// Single-channel 8-bit input image
//
// edges:
// The output edge map. It will have the same size and the same type as image
//
// threshold1:
// The first threshold for the hysteresis procedure
//
// threshold2:
// The second threshold for the hysteresis procedure
//
// apertureSize:
// Aperture size for the Sobel operator [By default this is ApertureSize.Size3]
//
// L2gradient:
// Indicates, whether the more accurate L2 norm should be used to compute the image
// gradient magnitude (true), or a faster default L1 norm is enough (false). [By
// default this is false]
public static void Canny(InputArray src, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false);
threshold1
,滞后过程的第一个阈值,下限,如果低于下限,则被舍弃掉threshold2
,滞后过程的第二个阈值,上限,如果高于上限,则认为是边缘像素。如果在两个阈值之间,且跟边缘像素相连才会被接受。apertureSize
,Sobel计算用的孔径大小,只能选3/5/7
L2gradient
,L2范数计算方式的指定
五、运行效果图
从左到右
- 第一张是原图
- 第二张是高斯模糊的结果图
- 第三张是Canny边缘检测的结果图
觉得好,就一键三连呗(点赞+收藏+关注)