在Canny算法中,对于其中的非极大值抑制这一点做笔记整理,过程看之前的这一片,注意理解里面的关于梯度相关的概念
原理如下:(需要理解)
依据当前点的周围点的梯度模来推算中心点的模,然后与实际值比较,若小则保留,若大于实际值则舍弃,在边缘检测中也有根据梯度模确定是否边缘,大于一定阈值就判定为是!
由中心点的梯度向量、周围点的梯度模,推断中心点的梯度模,再与实际值比较,梯度模就是梯度程度!
已知ax,ay,a1,a2,求Cm,如下:
用a0与cm,cm’比较确定是否舍弃a0,转90度再计算一次;
推导如上,下面来看一下代码:
在这里插入代码片
public static Bitmap NoNMaximumSupressionOri(this Bitmap sourceBitmap)
{
double factor = 1;
int[,] filterMatrixx = new int[3, 3] { { -1, 0, 1 }, { -2, 0, 2 }, { -1, 0, 1 } };//in X direction
int[,] YfilterMatrixy = new int[3, 3] { { 1, 2, 1 }, { 0, 0, 0 }, { -1, -2, -1 } };//in Y direction
if ((filterMatrixx.GetLength(0) & 1) == 0 || (filterMatrixx.GetLength(1) & 1) == 0 || filterMatrixx.GetLength(0) != filterMatrixx.GetLength(1))
return null;
double[,] data = ToGrayBufferD<double>(sourceBitmap);
int height = data.GetLength(0);
int width = data.GetLength(1);
int filterOffset = (filterMatrixx.GetLength(1) - 1) / 2;
double[,] dx = new double[height, width];
double[,] dy = new double[height, width];
double[,] dxy = new double[height, width];
double[,] mag = new double[height, width];
double[,] output = new double[height, width];
unsafe
{
int toffset = filterOffset * width;
fixed (double* source = data, pdx = dx, pdy = dy, pdxy = dxy, pm = mag)
{
double* src = source + toffset, Dx = pdx + toffset, Dy = pdy + toffset, Dxy = pdxy + toffset, Dm = pm + toffset;
double a11, a12, a13, a21, a23, a31, a32, a33, h, v;
for (int i = filterOffset; i < height - filterOffset; i++)
{
src += filterOffset;
Dx += filterOffset;
Dy += filterOffset;
Dxy += filterOffset;
Dm += filterOffset;
for (int j = filterOffset; j < width - filterOffset; j++, src++, Dx++, Dy++, Dxy++, Dm++)
{
a11 = src[+width + 1]; a12 = src[+1]; a13 = src[-width + 1];
a21 = src[+width + 0]; /* a22 */ a23 = src[-width + 0];
a31 = src[+width - 1]; a32 = src[-1]; a33 = src[-width - 1];
h = ((a11 + a12 + a13) - (a31 + a32 + a33)) * 0.166666667f;
v = ((a11 + a21 + a31) - (a13 + a23 + a33)) * 0.166666667f;
*Dx = h;
*Dy = v;
*Dxy = h * v;
*Dm = Math.Sqrt((*Dx * *Dx) + (*Dy * *Dy));
}
src += filterOffset;
Dx += filterOffset;
Dy += filterOffset;
Dxy += filterOffset;
Dm += filterOffset;
}
}
double a1, a2, b1, b2, A, B, point, val, max = 0;
int cdx, cdy;
fixed (double* pdx = dx, pdy = dy, pm = mag, pout = output)
{
double* Dx = pdx + toffset, Dy = pdy + toffset, Dout = pout + toffset, Dm = pm + toffset;
for (int i = filterOffset; i < height - filterOffset; i++)
{
Dout += filterOffset;
Dx += filterOffset;
Dy += filterOffset;
Dm += filterOffset;
for (int j = filterOffset; j < width - filterOffset; j++, Dx++, Dy++, Dm++, Dout++)
{
cdx = *Dx > 0 ? 1 : -1;
cdy = *Dy > 0 ? 1 : -1;
if (Math.Abs(*Dx) > Math.Abs(*Dy))
{
a1 = Dm[cdx];
a2 = Dm[cdx - cdy * width];
b1 = Dm[-cdx];
b2 = Dm[-cdx + cdy * width];
A = (Math.Abs(*Dx) - Math.Abs(*Dy)) * a1 + Math.Abs(*Dy) * a2;
B = (Math.Abs(*Dx) - Math.Abs(*Dy)) * b1 + Math.Abs(*Dy) * b2;
point = *Dm * Math.Abs(*Dx);
if (point >= A && point > B)
*Dout = Math.Abs(*Dx);
else
*Dout = 0;
}
else
{
a1 = Dm[-cdy * width];
a2 = Dm[cdx - cdy * width];
b1 = Dm[cdy * width];
b2 = Dm[-cdx + cdy * width];
A = (Math.Abs(*Dy) - Math.Abs(*Dx)) * a1 + Math.Abs(*Dx) * a2;
B = (Math.Abs(*Dy) - Math.Abs(*Dx)) * b1 + Math.Abs(*Dx) * b2;
point = *Dm * Math.Abs(*Dy);
if (point >= A && point > B)
*Dout = Math.Abs(*Dy);
else
*Dout = 0;
}
if (*Dout > max)
max = *Dout;
}
Dout += filterOffset;
Dx += filterOffset;
Dy += filterOffset;
Dm += filterOffset;
}
}
double ratio = 255 / max;
fixed (double* pout = output)
{
double* Dout = pout + toffset;
for (int i = filterOffset; i < height - filterOffset; i++)
{
Dout += filterOffset;
for (int j = filterOffset; j < width - filterOffset; j++, Dout++)
{
*Dout *= ratio;
}
Dout += filterOffset;
}
}
}
Bitmap resultBitmap = GetBmpFromArray<double>(output);
return resultBitmap;
}
这里做简要解释:
代码附上,下载学习