边缘检测

对图像灰度求梯度,梯度大的就是边缘了。但毕竟图像是离散化的,可以使用另外的方法求梯度,而不用像高数中那样拼命地算偏导数了。有很多学者提出了很多种不同性能的模板,只要按照模板作简单的四则运算就行了,当然这也是能用程序实现的关键。由于作为教学课程,所有的内容都是以简单的灰度图像来说明举例的,当然边缘检测也不例外,所以马上就遇到的一个问题是如何将彩色图像转为灰度图像。

 

    在课程中,都是简单的认为灰度图像只有一个亮度,这自然是没错的,但是放到计算机里,灰度也是一种颜色,是颜色就要使用色彩模式(最常用的自然是 RGB 了),那么这种灰度到底应该是怎样的颜色编码呢?索性取向 Photoshop ,看一看各种灰度色调,终于有所发祥。其实也可以这么想,全黑是 #000000 ,全白是 #FFFFFF ,那么是不是只要 RGB 值都相等,这个颜色就是灰度色呢?试了一下,果然如此。这样就好办了,至少第一步知道了转换的目标是什么了。但马上就又有了一个问题,彩色图片的颜色这么多,那么如何知道哪种彩色颜色对应哪种灰度颜色呢?这一点我从 .net Framework 中找到了答案。其实我从一开始就想在 .net Framework 中寻找有没有直接将 RGB 转成灰度或者是 HIS 模式(因为 HIS 模式中的 I 就使亮度,自然就容易转成灰度了)的,是不是太奢望了,所以我也没抱太大的希望,但是在这过程中却发现 Color 中有关一个实例方法 GetBrightness() ,就是用来获得颜色亮度的,真是踏破铁鞋无觅处,得来全不费功夫。该方法返回一个 0~1 之间的浮点数,那么如果 RGB 每个各占一个字节的话,那么刚好可以用这个值去乘以 255 ,然后拼成一个 RGB ,这个颜色就是原始色彩所对应的灰色。程序代码如下:

//定义两个颜色变量,oColor为原始色彩,gColor为对应的灰度色彩

Color oColor,gColor;

//原始色彩的亮度

float brightness;

//灰度色彩用 RGB 来表示,由于 R=G=B 所以只用一个变量就可以了

int gRGB;

//遍历图像中的每个像素

for (int i = 0; i < oBmp.Width; i ++) {

    for (int j = 0; j < oBmp.Height; j ++) {

        //得到像素的原始色彩        

        oColor = oBmp.GetPixel(i,j);

        //得到该色彩的亮度

        brightness = oColor.GetBrightness();

        //用该亮度计算灰度

        gRGB = (int)(brightness * 255);

        //组成灰度色彩

        gColor = Color.FromArgb(gRGB,gRGB,gRGB);

        //最后将该灰度色彩赋予该像素

        gBmp.SetPixel(i,j,gColor);

    }

}

其实还是很简单的。这之后就可以按照书中所说的模板游历的方法来进行边缘检测了。程序如下:

//template为模板,nThreshold是一个阈值,

//用来将模板游历的结果(也就是梯度)进行划分。

//大于阈值的和小于阈值的分别赋予两种颜色,白或黑来标志边界和背景

private void EdgeDectect(int[,] template,int nThreshold) {

    //取出和模板等大的原图中的区域

    int[,] gRGB = new int[3,3];

    //模板值结果,梯度

    int templateValue = 0;

    //遍历灰度图中每个像素

    for (int i = 1; i < gBmp.Width - 1; i ++) {

        for (int j = 1; j < gBmp.Height - 1; j ++) {

            //取得模板下区域的颜色,即灰度

            gRGB[0,0] = gBmp.GetPixel(i-1,j-1).R;

            gRGB[0,1] = gBmp.GetPixel(i-1,j).R;

            gRGB[0,2] = gBmp.GetPixel(i-1,j+1).R;

            gRGB[1,0] = gBmp.GetPixel(i,j-1).R;

            gRGB[1,1] = gBmp.GetPixel(i,j).R;

            gRGB[1,2] = gBmp.GetPixel(i,j+1).R;

            gRGB[2,0] = gBmp.GetPixel(i+1,j-1).R;

            gRGB[2,1] = gBmp.GetPixel(i+1,j).R;

            gRGB[2,2] = gBmp.GetPixel(i+1,j+1).R;

            //按模板计算

            for (int m = 0; m < 3; m ++) {

                for (int n = 0; n < 3; n ++) {

                    templateValue += template[m,n] * gRGB[m,n];

                }

            }

            //将梯度之按阈值分类,并赋予不同的颜色

            if (templateValue > nThreshold) {

                eBmp.SetPixel(i,j,Color.FromArgb(255,255,255)); //白

            } else {

                eBmp.SetPixel(i,j,Color.FromArgb(0,0,0)); //黑

            }

            templateValue = 0;

        }

    }

}

 

效果:边缘检测

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值