前面我们刚完成了二邻域感知,我们来对比一下最好完成版canny,前面只能说是自己最好版非极大值抑制结果。先看图:
(二邻域感知插值)
(自己最好完成版canny,梯度幅值版本)
显然二邻域感知插值没有canny效果好,二邻域感知插值是建立在非极大值抑制结果上。
其实我最喜欢这个版本的canny。
但有人马上就会发现问题,canny是单线条的,你这个好粗啊!没错,你的眼光太厉害,太毒辣,高手!问题在于tracedge不同,对比一下代码:
for (int i = 0; i < hh; i++)
{
for (int j = 0; j < ww; j++)
{
int fangbian = i * ww + j;
if ((非极大值抑制后图像[fangbian] > dThrHigh))
{
输出图像[fangbian] = 255;
if (checkBox幅值默认.Checked)
{ TraceEdge(i, j, dThrLow, ref 梯度幅值, ref 输出图像, ww); }
else
{ TraceEdge(i, j, dThrLow, ref 非极大值抑制后图像, ref 输出图像, ww); }
// TraceEdge(i, j, dThrLow, ref 梯度幅值, ref 输出图像,ww); //梯度幅值版本20221017第一版本
// TraceEdge(i, j, dThrLow, ref 非极大值抑制后图像, ref 输出图像, ww); //第二版本20221018,这两个版本效果都可以
}
}
}
对比一下:
左边是二邻域感知插值结果,右边是canny(正宗)结果,高门槛60,低门槛30.插值版本好于canny,canny(tracedge幅值)版本更好。
从上面观察可知,非极大值抑制二邻域感知版本应该不如canny二邻域感知插值版本,但有时侯,要考虑效率。
但我还是喜欢canny(tracedge幅值)版本,因为我更喜欢使用图像处理后用斑找特征。有时有一种感觉,连续和封闭,特征更稳定,或许是先入为主,多年这种经验导致,前几天用离散短线轮廓找特征也不错,不过,hu矩就很差了。
private void TraceEdge(int y, int x, int nThrLow, ref double[] 输入图像, ref byte[] 输出图像,int width)
{//这个版本非常精彩,自己又一次突破自己202210172008
Point start = new Point(x, y);
Stack<Point> s = new Stack<Point>();
int[] xNum = new int[8] { 1, 1, 0, -1, -1, -1, 0, 1 };
int[] yNum = new int[8] { 0, 1, 1, 1, 0, -1, -1, -1 };
long xx = 0, yy = 0;
s.Push(start);
do
{
// //Point pt1 = s.ElementAt(0);
Point pt1 = s.Peek();
s.Pop();
for (int k = 0; k < 8; k++)
{
yy = y + yNum[k];
xx = x + xNum[k];
if (输入图像[yy*width+ xx] > nThrLow&& 输出图像[yy * width + xx] != 255)
{
输出图像[yy * width + xx] = 255;
Point pt = new Point((int)xx, (int)yy);
s.Push(pt);
}
}
} while (s.Count != 0);
}
canny有一个自动高低门槛版本,效果不好,可以看一下: