
我自己使用的图像检测方法只有两个主要操作: canny边缘检测和hough线检测. 这些都是前辈已经实现并且非常成熟的算法. 但是,考虑到我们希望将来在不同的硬件上实现该算法,一方面,用C编写它有助于深入了解算法原理(当然,直接将matlab移植到dsp,FPGA也是a,另一方面,将来的硬件实现需要考虑存储的分配,如果您自己编写,则必须知道存储的使用.
Canny边缘检测的实现大致有4个步骤: 1.高斯滤波以对图像进行降噪. 2.从原始灰度图中找到两个在垂直和水平方向上的渐变图,以及一个完整的渐变图(有很多运算符可找到该渐变). 3.组合3个梯度图以进行非最大抑制(此步骤之后,检测到的图像边缘已经很细). 4.执行边缘连接(个人认为,尽管此步骤称为连接,但该算法确实反映了connection,但这是从强边到弱边的连接,并且在非最大抑制之后所有可能的连接点都不会超出范围,因此此步骤更准确的目的应该是去除结果中的假边非最大抑制并保持真实的边缘,同时使保留的边缘尽可能一致. 5.优化边缘(此步骤在matlab的canny算法中,但考虑到通过上述4个步骤获得的边缘,特别是第3步,已经很薄了,通常不需要精修边缘,因此可以省略此步骤)
在以上四个步骤中,前两个步骤相对简单,实现的关键在于后两个步骤. 这是第二步的摘要,有很多算子可以找到垂直和水平梯度,例如3×3 sobel算子,卷积核为[1,0,-1; 1,0,-1; 1,0,-1]和[1,1,1; 0,0,0; -1,-1,-1]; 2×2 robert运算符,其卷积核为[1,-1; 1,-1]和[1,1; -1,-1]. 在学习Matlab中Canny检测算法的同时,第一步过滤中使用高斯模板,第二步中使用高斯模板查找垂直和水平梯度. 注意,滤波后的模板系数的总和为1,并且梯度模板系数的总和为0,这是卷积模板的规则. 我们的滤波和梯度模板是二维高斯模板,但是使用两个具有两个垂直和水平方向的一维高斯卷积模板进行卷积可以达到与二维模板相同的效果,同时减少了计算总量. ,因此,在滤波的第一步中canny算子边缘检测原理,我们使用两个一维高斯模板而不是二维高斯模板,但是第二步高斯模板涉及梯度方向,因此我们仍然使用二维高斯模板直接卷积.
步骤3中的非最大值抑制使用步骤2中获得的三个梯度图. 实际上,步骤2中的“复合梯度图”已经可以看到图像边缘的轮廓,但是边缘较粗,我们该梯度图上的边缘强度尚未二值化(因为稍后会有双阈值). 这里的边缘包含大量的“假边缘”. 它们的灰度值可能不如真实边缘大,而是渐近的. 在更改过程中,非最大抑制的目的是通过组合``梯度方向''和``梯度强度''来消除这些``错误边缘''.
步骤4中的边缘连接实际上是从强边缘到弱边缘的连接. 我们执行步骤3,得到二值化的“非最大抑制边缘图”,与在步骤2中获得的图相同. “综合梯度图”不同. 首先,去除大量错误边缘,其次,它已将边缘灰度二值化以使其均匀. 目前,为什么我们需要步骤4?我在上面的概述的开头说过,这是要进一步消除错误边缘,这是有道理的,但是此处的“错误边缘”本质上与第三步将要执行的“错误边缘”不同. 步骤3的假边缘边缘可以理解为假边缘,该假边缘确实附着在真边缘周围(这样的边缘在步骤3之后留下非常细的真边缘),甚至是假边缘也附着在假边缘周围(这样的边缘)都是假边缘,在步骤3)之后会有一部分假边缘,这两者中的最后一个恰好是在步骤4中处理的,步骤4中最重要的参数是两个自适应阈值,因此步骤4假边缘是基于其灰度等级是否太弱(小于强阈值),而不是第三步,而是基于其灰度值与周围的灰度值进行识别. 通过强阈值确定真实边缘后,将使用弱阈值连接真实边缘以确保边缘的平滑度. 请注意canny算子边缘检测原理,步骤4中的“连接方法”是自定义“染色嵌套函数”以对一个点的8个邻点执行染色操作. 这种编程方法在图像中具有相同的属性(灰度值等). 在连接区域进行染色操作很有用.
附录: (一些关键代码)
滤波和去噪的第一步是使用两个一维模板来实现二维模板的功能
for(i = 0; i <5; i ++){
conv [i] = exp(-(i-2)*(i-2)/(2 * sigma * sigma))/(sqrt(2 * 3.1415926)* sigma);
sum + = conv [i];
}
for(i = 0; i <5; i ++)
conv [i] = conv [i] / sum;
for(i = 0; i for(j = 0; j v = 0; for(m = 0; m <5; m ++) if(i-m + 2> = 0 && i-m + 2 v + = conv [m] *((float)indata [i-m + 2] [j]); outdata [i] [j] =(int)v; } for(i = 0; i for(j = 0; j v = 0; for(n = 0; n <5; n ++) if(j-n + 2> = 0 && j-n + 2 v + = conv [n] *((float)outdata [i] [j-n + 2]); indata [i] [j] =(int)v; } 第二步是找到垂直和水平渐变图. 在Matlab中使用二维高斯梯度模板 for(i = 0; i <5; i ++) for(j = 0; j <5; j ++){ convv [i] [j] =(2-j)* exp(-((i-2)*(i-2)+(j-2)*(j-2))/(2 * sigma * sigma))/(sigma * sigma * 3.1415926); } // j和x for(i = 0; i for(j = 0; j v = 0; for(m = 0; m <5; m ++) for(n = 0; n <5; n ++) if(i-m + 2> = 0 && i-m + 2 v + = convv [m] [n] *((float)indata [i-m + 2] [j-n + 2]); outdata [i] [j] =(int)v; } 第三步是执行非最大抑制. 我们的想法与matlab完全相同,只是在相关方向上使用了“梯度方向”和“梯度强度”. 八个邻域分区如下: %X标记有问题的像素,并且每个 梯度向量的 %3 2象限 %O ---- 0 ---- 0分为两种情况,除以45 %4 | | 1度线. 在一种情况下,梯度 %||向量更水平,而另一个 %O X O,它更垂直. 有八个 %| 划分,但用于非最大抑制 %(1)| | (4)自从我们 以来,我们只担心其中的4个 %O ---- O ---- O使用围绕中心像素的对称点. %(2)(3) 第四步是边缘连接,它使用强和弱阈值,涉及直方图自适应;另一个是前面提到的“在特定条件域中着色的嵌套函数” 自适应阈值 convvv =(int *)malloc((k + 1)* sizeof(int)); for(i = 1; i <= k; i ++) convvv [i] = 0; for(i = 0; i for(j = 0; j if(indata [i] [j] == 254) convvv [fdata [i] [j]] ++; sum = 0; for(i = 1; i <= k; i ++) sum + = convvv [i]; v = 0; for(i = 1; i <= k; i ++){ v + = convvv [i]; if(v> = 0.85 * sum){ high = i; 休息; } } low =(int)(0.4 *((float)high)); free(convvv); “某些条件域中的染色嵌套功能” trace(int low,int x,int y,unsigned char ** indata,int ** fdata,long width,long height) { int i,j; for(i = -1; i <2; i ++) for(j = -1; j <2; j ++)//这里我不考虑图像4的边界,因为边界灰度预先设置为0. 不能是254 if(indata [x + i] [y + j] == 254 && fdata [x + i] [y + j]>低){ indata [x + i] [y + j] = 255; trace(low,x + i,y + j,indata,fdata,width,height); } }



本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-250357-1.html
从此再也不买了