C#:Canny边缘检测

  边缘检测目的是在保留原有图像属性的情况下,显著减少图像的数据规模。
  有多种算法可以进行边缘检测,虽然Canny算法年代久远,但可以说它是边缘检测的一种标准算法。

一、Canny边缘检测

  • Canny边缘检测的历史比较久远,最早是在1986年的时候提出的,通常称为Canny边缘检测算法。
  • Canny边缘检测算法是一种对噪声比较敏感的边缘检测方法,
    所以通常在使用Canny边缘检测之前,首先对图像进行降噪。
  • 图像噪声抑制方法主要有均值滤波、高斯滤波、中值滤波,
    一般情况下,会优先考虑使用高斯滤波来完成噪声抑制,
    因为多数噪声都是自然界中的随机噪声,高斯模糊对它们有不同程度的抑制作用。
  • Canny边缘检测一个最大的创新在于其使用两个阈值尝试把所有的边缘像素连接起来,形成边缘曲线或者线段。
程序运行结果

二、检测步骤

  完整的Canny边缘检测由如下步骤组成。

  • 1)高斯模糊:完成噪声抑制。
  • 2)灰度转换:在灰度图像上计算梯度值。
  • 3)计算梯度:使用Sobel/Scharr。
  • 4)非最大信号抑制:在梯度图像上寻找局部最大值。
  • 5)高低阈值连接:把边缘像素连接为线段,形成完整边缘轮廓。
    上面的第5步是使用高低阈值连接,Canny推荐的高低阈值比在2:1到3:1之间,
    首先使用低阈值,把低于低阈值边缘的像素点都去掉,
    然后保留所有高于高阈值的像素点,
    对于处于高阈值与低阈值之间的像素点,如果从高阈值像素点出发,经过的所有像素点都高于低阈值,则保留这些像素,否则丢弃。
    OpenCV中Canny边缘检测函数已经包含了上述5个步骤。

三、函数Cv2.Canny

Cv2.Canny(src_img, dst, tkBarCannyMin.Value, kBarCannyMax.Value, hole, rbBtnTrue.Checked);
参数:

  • 1,8 bit 输入图像;
  • 2,输出边缘图像,一般是二值图像,背景是黑色;
  • 3,低阈值。值越大,找到的边缘越少;
  • 4,高阈值;
  • 5,表示应用Sobel算子的孔径大小,其有默认值3;
  • 6,计算图像梯度幅值的标识,有默认值false。
    低于阈值1的像素点会被认为不是边缘;
    高于阈值2的像素点会被认为是边缘;
    在阈值1和阈值2之间的像素点,若与一阶偏导算子计算梯度得到的边缘像素点相邻,则被认为是边缘,否则被认为不是边缘。

四、程序

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using Sunny.UI;

namespace Ky_Cv2Canny
{
    public partial class Form1 : UIForm
    {
        private Image image = null;
        private Mat dst = new Mat();
        private Mat src_img;
        string filePath = "";
        //private static int Num = 20;
        private List<Mat> reList = new List<Mat>();
        private int step = 1;

        public Form1()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.AllPaintingInWmPaint, true);
        }

        private void openImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Title = "选择操作的图片";
            openFileDialog.Filter = "图片 *.jpg|*.jpg|图像*.png|*.png";
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                filePath = openFileDialog.FileName;
                image = Image.FromFile(filePath);
                src_img = Cv2.ImRead(filePath);
                Mat tem1 = new Mat();
                src_img.CopyTo(tem1);
                if (reList.Count > 0)
                {
                    reList[0] = tem1;

                }
                else
                {
                    reList.Add(tem1);
                }

            }
            if (filePath != "")
            {
                picBoxShowDel.Image = image;
                picShowOri.Image = image;
            }


        }

        /// <summary>
        /// 边缘检测Canny
        /// </summary>
        private void Canny()
        {
            int hole = 0;
            if (!int.TryParse(txtBoxCannyHole.Text, out hole))
            {
                return;
            }
            try
            {
                Cv2.Canny(src_img, dst, tkBarCannyMin.Value, tkBarCannyMax.Value, hole, rbBtnTrue.Checked);
                picBoxShowDel.Image = dst.ToBitmap();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

        private void tkBarCannyMin_Scroll(object sender, EventArgs e)
        {
            if (tkBarCannyMin.Value < 0)
            {
                tkBarCannyMin.Value = 0;
            }
            uiLabel_Cs3.Text = tkBarCannyMin.Value.ToString();
        }

        private void tkBarCannyMax_Scroll(object sender, EventArgs e)
        {
            if (tkBarCannyMax.Value < 0)
            {
                tkBarCannyMax.Value = 0;
            }
            uiLabel_Cs4.Text = tkBarCannyMax.Value.ToString();
        }

        private void uiButton1_Click(object sender, EventArgs e)
        {
            Canny();
        }
    }
}

五、资料

xaiqpl的博客  https://blog.csdn.net/xaiqpl/article/details/118597812?spm=1001.2014.3001.5502
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,968评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,682评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,254评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,074评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,964评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,055评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,484评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,170评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,433评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,512评论 2 308
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,296评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,184评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,545评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,150评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,437评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,630评论 2 335

推荐阅读更多精彩内容