新的边缘检测方法






4.38/5 (9投票s)
这是一种灵活且可扩展的边缘检测方法。
引言
这是一种新的边缘检测方法,它具有灵活性和可扩展性。
背景
我需要一种灵活且可扩展的边缘检测方法。因此,我可以使用 Sobel、Prewitt 或 Canny。在 Sobel 和 Prewitt 中,很难改变边缘的厚度。但我的边缘检测方法只有阈值,如果你改变它,输出结果会不同。
为什么是新的
Sobel 和 Prewitt 边缘检测对图像上的所有像素执行 3X3 矩阵乘法运算,其复杂度为宽度 * 高度 * 3 * 3。但我的边缘检测方法找到相邻像素之间的差异,如果任何差异大于或等于阈值(通常为 90),则将其视为边缘,其复杂度为宽度 * 高度。如果增加阈值,边缘会减少;如果减少阈值,边缘会增加。因此,边缘和阈值之间存在反比关系。但在 Sobel 和 Prewitt 中,我们无法增加或减少边缘。对于不同的图像,有时我们需要增加或减少边缘。
概念
边缘相反方向的两个相邻像素的颜色差异很大。没有边缘时,相邻像素的颜色差异很小。
它是如何工作的?

每个像素都有 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; }
}
我们可以将我的边缘检测方法与 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 日:初始发布