开篇:润墨网以专业的文秘视角,为您筛选了一篇一种彩色图像的边缘检测方法及实现范文,如需获取更多写作素材,在线客服老师一对一协助。欢迎您的阅读与分享!
摘要:在数字图像处理的研究和应用中,人们往往仅对图像中的某些部分感兴趣,这些感兴趣的部分常称为目标或对象(ROI),它们一般对应图像定的,具有独特性质的区域。图像处理的重要任务就是对图像进行分析和理解,该文讲述了图像边缘检测和边缘跟踪的原由,归纳出了几种图像边缘检测的算子,最后介绍了一种基于RGB分量直接梯度法的彩色图像图像边缘检测方法以及该方法的C#实现。
关键词:边缘检测;数学算子;C#
中图分类号:TP18文献标识码:A文章编号:1009-3044(2010)20-5579-03
1 灰度图像的边缘检测
图像的边缘是图像的最基本特征。所谓边缘是指其周围像素灰度有阶跃变化或屋顶变化的那些像素的集合,是图像中灰度发生急剧变化的区域。图像灰度的变化可以用图像的梯度反映,边缘检测就是求连续图像f(x,y)梯度的局部最大值和方向。
f(x,y)沿r的梯度为:
(1)
使最大的条件是:
(2)
梯度最大值及其方向由(1)、(2)式求得:
梯度最大值:
在离散情况下常用梯度算子来检测边缘,给定图像f(m,n)在两个正交方向H1和H2上的梯度φ1(m,n)和φ2(m,n)如下:
边缘的强度和方向由下式给出:
常用边缘检测算子有Roberts算子、Prewitt算子和Sobel算子等。
Roberts算子的卷积模板是:
Prewitt算子的卷积模板是:
Sobel算子的卷积模板是:
Roberts算子特点是边缘定位准,但对噪声敏感;Sobel算子的两个模板能够最好地响应图像的垂直边缘和水平边缘,因此能够取得比较好的效果。
另外有一种二阶导数算子拉普拉斯算子(Laplacian)也借助模板来实现,其模板定义有一个基本要求:模板中心的系数为正数,其余相邻系数为负数,所有系数的和应该为零。常用形式如下:
Laplacian算子在检测到图像强边缘的同时也可以检测到弱边缘,对噪声比较敏感,容易对ROI造成干扰。
2 彩色图像的边缘检测
彩色图像的边缘检测比灰度图像复杂,因为它不仅要考虑亮度,还要考虑不同的颜色,,这种图像以R(红)、G(绿)、B(蓝)三基色的亮度为一组,代表每个像素在色彩空间的颜色。与索引图像不同,RGB图像的各象素的亮度值直接存在图像数组中,
图像数组的维数:m,z3,m、,z表示图像像素的长、宽。
传统的梯度边缘提取通常是对单一的灰度图进行处理,不能直接对彩色位图图像操作,通常的做法是在先将彩色图像转化成灰度图,然后再进行边缘提取。这样做的后果是丧失原图像中的一些边缘信息,通常提取出来的边缘不连续,还需进行边界跟踪和插值连接。
另一种做法是,先将位图图像投影分解3幅伪彩色图:R灰度图、G灰度图、B灰度图,对每一幅图像都可用梯度法将边缘提取出来,得到Gr、Gg、Gb 三幅梯度图像,由于图像易受环境干扰、背景照明不均,这样提取出来的3种图像边缘不一致。对此可做这样的处理:将每一幅梯度图表示出的边缘综合起来,然后再取适当的阈值门限T,直接将彩色图像二值化就可得到很好效果的边缘。其数学描述如下:
(3)
对公式选定门限T,最后得:
这种方法的优点是:1)直接对彩色图像处理,避免了先将彩色图像转化为灰度图,再处理所造成的信息丢失。2)由于采用了同一像素多个梯度求和算法,忽略了环境干扰对边缘提取的影响,能得到较好的边缘的特征。
对三种颜色分量采用Sobel算子进行灰度边缘检测后,通过人为选择阈值的方法生成二值边缘图像的C#实现关键代码如下:
private void edgeC_Click(object sender, EventArgs e)
{ if (Btmap != null)
{ edgeColor edgedetC = new edgeColor();
if (edgedetC.ShowDialog() == DialogResult.OK)
{ Rectangle rect = new Rectangle(0, 0, Btmap.Width, Btmap.Height);
System.Drawing.Imaging.BitmapData bmpData = Btmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, Btmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = Btmap.Width * Btmap.Height;
byte[] rgbValues = new byte[bytes * 3];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes * 3);
int thresh = edgedetC.GetThresholding;
byte[] grayValues = new byte[bytes];
double[] tempArray = new double[bytes];
byte[] rValues = new byte[bytes];
byte[] gValues = new byte[bytes];
byte[] bValues = new byte[bytes];
for (int i = 0; i < bytes; i++)
{ rValues[i] = rgbValues[i * 3 + 2];
gValues[i] = rgbValues[i * 3 + 1];
bValues[i] = rgbValues[i * 3];}
double maxV = 0.0;
double minV = 1000.0;
double[] rvg = new double[bytes];
double[] gvg = new double[bytes];
double[] bvg = new double[bytes];
double gh, gv;
double[] maxValue = new double[3] { 0.0, 0.0, 0.0 };
double[] minValue = new double[3] { 1000.0, 1000.0, 1000.0 };
for (int i = 0; i < Btmap.Height; i++)
{ for (int j = 0; j < Btmap.Width; j++)
{
//以下为对红色分量进行soble边缘检测的代码
gh = rValues[((Math.Abs(i - 1)) % Btmap.Height) * Btmap.Width + ((j + 1) % Btmap.Width)] + 2 * rValues[i * Btmap.Width + ((j + 1) % Btmap.Width)] + rValues[((i + 1) % Btmap.Height) * Btmap.Width + ((j + 1) % Btmap.Width)] -rValues[((Math.Abs(i - 1)) % Btmap.Height) * Btmap.Width + ((Math.Abs(j - 1)) % Btmap.Width)] - 2 * rValues[i * Btmap.Width + ((Math.Abs(j - 1)) % Btmap.Width)] - rValues[((i + 1) % Btmap.Height) * Btmap.Width + ((Math.Abs(j - 1)) % Btmap.Width)];
gv = rValues[((Math.Abs(i - 1)) % Btmap.Height) * Btmap.Width + ((Math.Abs(j - 1)) % Btmap.Width)] + 2 * rValues[((Math.Abs(i - 1)) % Btmap.Height) * Btmap.Width + j] + rValues[((Math.Abs(i - 1)) % Btmap.Height) * Btmap.Width + ((j + 1) % Btmap.Width)] - rValues[((i + 1) % Btmap.Height) * Btmap.Width + ((Math.Abs(j - 1)) % Btmap.Width)] - 2 * rValues[((i + 1) % Btmap.Height) * Btmap.Width + j] - rValues[((i + 1) % Btmap.Height) * Btmap.Width + ((j + 1) % Btmap.Width)];
rvg[i * Btmap.Width + j] = Math.Sqrt(gh * gh + gv * gv);
if (rvg[i * Btmap.Width + j] > maxValue[0])
maxValue[0] = rvg[i * Btmap.Width + j];
else if (rvg[i * Btmap.Width + j] < minValue[0])
minValue[0] = rvg[i * Btmap.Width + j];
//将rValues更换为gValues、bValues,将rvg更换为gvg、bvg再各写一次其他两种颜色分量的灰度边缘检测的代码
//略}}
for (int i = 0; i < bytes; i++)
{ rgbValues[i * 3 + 2] = (byte)((rvg[i] - minValue[0]) * 255 / (maxValue[0] - minValue[0]));
rgbValues[i * 3 + 1] = (byte)((gvg[i] - minValue[1]) * 255 / (maxValue[1] - minValue[1]));
rgbValues[i * 3] = (byte)((bvg[i] - minValue[2]) * 255 / (maxValue[2] - minValue[2]));
gh = Math.Max((rvg[i] - minValue[0]) * 255 / (maxValue[0] - minValue[0]), (gvg[i] - minValue[1]) * 255 / (maxValue[1] - minValue[1]));
gv = Math.Max(gh, (bvg[i] - minValue[2]) * 255 / (maxValue[2] - minValue[2]));
grayValues[i] = (byte)(gv);}
if (thresh != 0)
{for (int i = 0; i < bytes; i++)
{ if (grayValues[i] > thresh)
grayValues[i] = 255;
else
grayValues[i] = 0; } }
Btmap = new Bitmap(Btmap.Width, Btmap.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
System.Drawing.Imaging.ColorPalette cp = Btmap.Palette;
for (int i = 0; i < 256; i++)
{ cp.Entries[i] = Color.FromArgb(i, i, i);}
Btmap.Palette = cp;
bmpData = Btmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, Btmap.PixelFormat);
ptr = bmpData.Scan0;
System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
Btmap.UnlockBits(bmpData);
Invalidate();} } }
图1 RGB分量直接梯度法边缘检测效果图
参考文献:
[1] 龚声蓉,刘纯平.数字图像处理与分析[M].北京: 清华大学出版社,2006.
[2] 何斌.Visual C++数字图像处理[M].北京:人民邮电出版社,2002.
[3] 赵春江.C#数字图像处理算法[M].北京:人民邮电出版社,2009.
[4] 赵哲.基于C#的数字图像处理算法的分析研究[J].科技信息,2010(7):92-93.