前言:本来是准备系统学习一遍OpenCvSharp的,但由于工作需要,所以决定问题导向,先走出第一步,深究边缘检测算法。

目录

1.定义

2.影响因素

3.检测方法

3.1 基于搜索

3.2 基于零交叉

4.常用边缘检测算法 

4.1 Sobel

4.2 Scharr(Sobel的优化)

22/4/19更新:理解一下canny边缘算法: 

1.定义

边缘检测是图像处理和计算机视觉中的基本问题,边缘检测的目的是标识数字图像中亮度变化明显的点。

1)深度上的不连续

2)表面方向不连续

3)物质属性变化和场景照明变化。

边缘检测是图像处理和计算机视觉中,尤其是特征提取中的一个研究领域。

2.影响因素

1)有限场景深度带来的聚焦模糊。(*处理相机聚焦问题)

2)非零半径光源产生的阴影带来的半影模糊。

3)光滑物体边缘的阴影。(需要考虑到,但是暂时可以忽略)

4)物体边缘附近的局部镜面反射或漫反射

3.检测方法

3.1 基于搜索

参考:边缘检测_百度百科

基于搜索的边缘检测方法首先计算边缘强度, 通常用一阶导数表示, 例如梯度模,然后,用计算估计边缘的局部方向, 通常采用梯度的方向,并利用此方向找到局部梯度模的最大值。

3.2 基于零交叉

基于零交叉的方法找到由图像得到的二阶导数的零交叉点来定位边缘。 通常用拉普拉斯算子或非线性微分方程的零交叉点。

4.常用边缘检测算法 

4.1 Sobel

private void SobelButton_Click(object sender, EventArgs e)
        {
            if(src.Empty())
            {
                PrintMsg("请加载图片", Color.Red);
                return;
            }
            hScrollBar1.Enabled = false;
            hScrollBar2.Enabled = false;
            Mat srcGray = new Mat();
            Cv2.CvtColor(src,srcGray,ColorConversionCodes.RGB2GRAY);
            label3.Text = "Gray Src";
            pictureBoxSrc.Image = Mat2Bitmap(srcGray);
            Mat SobelDstx1 = new Mat();
            Mat SobelDstx2 = new Mat();
            Mat SobelDsty1 = new Mat();
            Mat SobelDsty2 = new Mat();
            Cv2.Sobel(srcGray, SobelDstx1, MatType.CV_16S, 1, 0);
            Cv2.ConvertScaleAbs(SobelDstx1, SobelDstx2);
            Cv2.Sobel(srcGray, SobelDsty1, MatType.CV_16S, 0, 1);
            Cv2.ConvertScaleAbs(SobelDsty1, SobelDsty2);

            Mat SobelDst = new Mat();
            Cv2.AddWeighted(SobelDstx2, 0.5, SobelDsty2, 0.5, 0, SobelDst);
            pictureBoxDst.Image = Mat2Bitmap(SobelDst);
        }

opencv 对图像进行边缘柔化 opencv sobel边缘检测_Image

4.2 Scharr(Sobel的优化)

private void ScharrButton_Click(object sender, EventArgs e)
        {
            if (src.Empty())
            {
                PrintMsg("请加载图片", Color.Red);
                return;
            }
            hScrollBar1.Enabled = false;
            hScrollBar2.Enabled = false;
            Mat srcGray = new Mat();
            Cv2.CvtColor(src, srcGray, ColorConversionCodes.RGB2GRAY);
            label3.Text = "Gray Src";
            pictureBoxSrc.Image = Mat2Bitmap(srcGray);
            Mat grad_x = new Mat();
            Mat grad_x2 = new Mat();
            Cv2.Scharr(srcGray, grad_x, MatType.CV_16S, 1, 0);
            Cv2.ConvertScaleAbs(grad_x, grad_x2);

            Mat grad_y = new Mat();
            Mat grad_y2 = new Mat();
            Cv2.Scharr(srcGray, grad_y, MatType.CV_16S, 0, 1);
            Cv2.ConvertScaleAbs(grad_y, grad_y2);

            Mat ScharrDst = new Mat();
            Cv2.AddWeighted(grad_x2, 0.5, grad_y2, 0.5, 0, ScharrDst);
            pictureBoxDst.Image = Mat2Bitmap(ScharrDst);
        }

opencv 对图像进行边缘柔化 opencv sobel边缘检测_学习_02

 4.3 Canny

private void CannyButton_Click(object sender, EventArgs e)
        {
            if(src.Empty())
            {
                PrintMsg("请加载图片",Color.Red);
                return;
            }
            hScrollBar1.Enabled = true;
            hScrollBar2.Enabled = true;
            double threshold1 = hScrollBar1.Value;
            double threshold2 = hScrollBar2.Value;
            int apertureSize = 3;
            Cv2.Canny(src,dst,threshold1,threshold2,apertureSize);
            pictureBoxDst.Image = Mat2Bitmap(dst);
        }

opencv 对图像进行边缘柔化 opencv sobel边缘检测_Red_03

22/4/19更新:理解一下canny边缘算法: 

Canny算法分为四步:

  • 高斯滤波器 -- 滤除高斯噪声,使图像更平滑
  • 梯度计算 -- 计算灰度图像每个像素点在横向和纵向上的导数Gx和Gy,由此计算出梯度G
  • 非极大值抑制 -- 抑制一些非边缘信息,具体实现为比对当前像素的G和邻域像素的G,若为极大值则保留,否则置为0
  • 双阈值边缘检测和边缘连接  -- 利用高低双阈值去除伪边缘。梯度值G大于高阈值的的像素点一定是边缘,输出像素置为255;G小于低阈值的则置为0;G介于高低阈值之间的像素点通过判定八邻域的G,若都小于高阈值则置为0,否则置为255