65.9K
CodeProject 正在变化。 阅读更多。
Home

新的边缘检测方法

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.38/5 (9投票s)

2010 年 9 月 17 日

CPOL

2分钟阅读

viewsIcon

58533

downloadIcon

4323

这是一种灵活且可扩展的边缘检测方法。

引言

这是一种新的边缘检测方法,它具有灵活性和可扩展性。

背景

我需要一种灵活且可扩展的边缘检测方法。因此,我可以使用 Sobel、Prewitt 或 Canny。在 Sobel 和 Prewitt 中,很难改变边缘的厚度。但我的边缘检测方法只有阈值,如果你改变它,输出结果会不同。

为什么是新的

Sobel 和 Prewitt 边缘检测对图像上的所有像素执行 3X3 矩阵乘法运算,其复杂度为宽度 * 高度 * 3 * 3。但我的边缘检测方法找到相邻像素之间的差异,如果任何差异大于或等于阈值(通常为 90),则将其视为边缘,其复杂度为宽度 * 高度。如果增加阈值,边缘会减少;如果减少阈值,边缘会增加。因此,边缘和阈值之间存在反比关系。但在 Sobel 和 Prewitt 中,我们无法增加或减少边缘。对于不同的图像,有时我们需要增加或减少边缘。

概念

边缘相反方向的两个相邻像素的颜色差异很大。没有边缘时,相邻像素的颜色差异很小。

它是如何工作的?

Edge_1.PNG

每个像素都有 8 个邻居。如果像素坐标为 x 和 y,则其相邻像素为 (x+1,y+1)、(x,y+1)、(x+1,y)、(x-1,y-1)、(x,y-1)、(x-1,y)、(x-1,y+1) 和 (x+1,y-1)。两个像素的颜色差异是指两个像素之间的 RGB 差异。如果两个像素是 (x,y) 和 (a,b),则颜色差异为

int total = Math.Abs(b.GetPixel(a, b).B - b.GetPixel(x, y).B) + 
		Math.Abs(b.GetPixel(a, b).R - b.GetPixel(x, y).R) + 
		Math.Abs(b.GetPixel(a, b).G - b.GetPixel(x, y).G);

在我的边缘检测方法中,首先获取一个高度和宽度与原始图像相似的位图,并且所有像素的颜色为白色。

int n, m;
n = b.Height;
m = b.Width;
int total = 0;
Bitmap B1 = new Bitmap(m, n);
for (int i = 0; i < m; i++)
    for (int j = 0; j < n; j++)
    {
        B1.SetPixel(i, j, Color.White);
    }

然后,对于图像的每个像素,它确定其相邻像素的颜色差异。如果任何相邻像素的颜色差异大于或等于阈值,则它是一个边缘,并将像素值设置为黑色。通常阈值为 90。但如果我们增加阈值,边缘会减少;如果减少阈值,边缘会增加。

for (int i = 1; i < m - 1; i++)
for (int j = 1; j < n - 1; j++)
{
    total = Math.Abs(b.GetPixel(i + 1, j + 1).B - b.GetPixel(i, j).B) + 
    	Math.Abs(b.GetPixel(i + 1, j + 1).R - b.GetPixel(i, j).R) + 
    	Math.Abs(b.GetPixel(i + 1, j + 1).G - b.GetPixel(i, j).G);
    if (total > _proposedThresoldValue)
    { B1.SetPixel(i, j, Color.Black); continue; }
    
    total = Math.Abs(b.GetPixel(i, j + 1).B - b.GetPixel(i, j).B) + 
    	Math.Abs(b.GetPixel(i, j + 1).R - b.GetPixel(i, j).R) + 
    	Math.Abs(b.GetPixel(i, j + 1).G - b.GetPixel(i, j).G);
    if (total > _proposedThresoldValue)
    { B1.SetPixel(i, j, Color.Black); continue; }
    
    total = Math.Abs(b.GetPixel(i + 1, j).B - b.GetPixel(i, j).B) + 
    	Math.Abs(b.GetPixel(i + 1, j).R - b.GetPixel(i, j).R) + 
    	Math.Abs(b.GetPixel(i + 1, j).G - b.GetPixel(i, j).G);
    if (total > _proposedThresoldValue)
    { B1.SetPixel(i, j, Color.Black); continue; }
    
    total = Math.Abs(b.GetPixel(i - 1, j - 1).B - b.GetPixel(i, j).B) + 
    	Math.Abs(b.GetPixel(i - 1, j - 1).R - b.GetPixel(i, j).R) + 
    	Math.Abs(b.GetPixel(i - 1, j - 1).G - b.GetPixel(i, j).G);
    if (total > _proposedThresoldValue)
    { B1.SetPixel(i, j, Color.Black); continue; }
    
    total = Math.Abs(b.GetPixel(i, j - 1).B - b.GetPixel(i, j).B) + 
    	Math.Abs(b.GetPixel(i, j - 1).R - b.GetPixel(i, j).R) + 
    	Math.Abs(b.GetPixel(i, j - 1).G - b.GetPixel(i, j).G);
    if (total > _proposedThresoldValue)
    { B1.SetPixel(i, j, Color.Black); continue; }
    
    total = Math.Abs(b.GetPixel(i - 1, j).B - b.GetPixel(i, j).B) + 
    	Math.Abs(b.GetPixel(i - 1, j).R - b.GetPixel(i, j).R) + 
    	Math.Abs(b.GetPixel(i - 1, j).G - b.GetPixel(i, j).G);
    if (total > _proposedThresoldValue)
    { B1.SetPixel(i, j, Color.Black); continue; }
    
    total = Math.Abs(b.GetPixel(i - 1, j + 1).B - b.GetPixel(i, j).B) + 
    	Math.Abs(b.GetPixel(i - 1, j + 1).R - b.GetPixel(i, j).R) + 
    	Math.Abs(b.GetPixel(i - 1, j + 1).G - b.GetPixel(i, j).G);
    if (total > _proposedThresoldValue)
    { B1.SetPixel(i, j, Color.Black); continue; }
    
    total = Math.Abs(b.GetPixel(i + 1, j - 1).B - b.GetPixel(i, j).B) + 
    	Math.Abs(b.GetPixel(i + 1, j - 1).R - b.GetPixel(i, j).R) + 
    	Math.Abs(b.GetPixel(i + 1, j - 1).G - b.GetPixel(i, j).G);
    if (total > _proposedThresoldValue)
    { B1.SetPixel(i, j, Color.Black); continue; }
}

Edge_2.PNG

我们可以将我的边缘检测方法与 Sobel 或 Prewitt 边缘检测进行比较。为了进行比较,我们必须选择 Sobel 或 Prewitt 复选框和提议的复选框。黑色像素表示该像素对于提议方法和 Sobel/Prewitt 都是通用的。红色像素表示该像素仅对于 Sobel/Prewitt 有效。蓝色像素表示该像素仅对于提议方法有效。

if (checkBox_sobel.Checked && checkBox_pro.Checked)
{
    Bitmap b1 = (Bitmap)pictureBox2.Image;
    Bitmap b2 = (Bitmap)pictureBox4.Image;
    Bitmap map = new Bitmap(pictureBox2.Image.Width, pictureBox2.Image.Height);
    
    for (int i = 1; i < b1.Width - 1; i++)
        for (int j = 1; j < b1.Height - 1; j++)
        {
            if (b1.GetPixel(i, j).R == 0 && b2.GetPixel(i, j).R == 0)
                map.SetPixel(i, j, Color.Black);
            else if (b1.GetPixel(i, j).R == 0)
                map.SetPixel(i, j, Color.Red);
            else if (b2.GetPixel(i, j).R == 0)
                map.SetPixel(i, j, Color.Blue);
        }
        
    pictureBox5.Image = map;
}
else if (checkBox_prewitt.Checked && checkBox_pro.Checked)
{
    Bitmap b1 = (Bitmap)pictureBox3.Image;
    Bitmap b2 = (Bitmap)pictureBox4.Image;
    Bitmap map = new Bitmap(pictureBox3.Image.Width, pictureBox3.Image.Height);
    
    for (int i = 1; i < b1.Width - 1; i++)
        for (int j = 1; j < b1.Height - 1; j++)
        {
            if (b1.GetPixel(i, j).R == 0 && b2.GetPixel(i, j).R == 0)
                map.SetPixel(i, j, Color.Black);
            else if (b1.GetPixel(i, j).R == 0)
                map.SetPixel(i, j, Color.Red);
            else if (b2.GetPixel(i, j).R == 0)
                map.SetPixel(i, j, Color.Blue);
        }
        
    pictureBox5.Image = map;
}

如果我们减少阈值,边缘会更粗;如果我们增加阈值,边缘会更细。

历史

  • 2010 年 9 月 10 日:初始发布
© . All rights reserved.