边缘检测在图像的检测中是经常会用到的。图片的边缘会包含大量的信息,因此在图像的分割、识别、分析中通常可以取边缘作为图像特征。边缘检测最经典的应用就是图像的锐化了,想必大家都用过。
为了进行边缘检测,我们通常会用到以下的一些算子,即一阶算子(梯度算子)和二阶算子(拉普拉斯算子)。
拉普拉斯算子(Laplacian Operator)
拉普拉斯算子其实就是二阶微分算子,具有各向同性。他也会增强噪声,因此在使用拉普拉斯算子之前需要进行平滑处理。他的主要用处其实是判断一个像素是处于图像的亮区还是暗区。
拉普拉斯算子定义式:
$$\begin{aligned}\nabla^2 f(x,y)&=\frac{\partial^2 f}{\partial x}+\frac{\partial^2 f}{\partial y}\\&=f(x+1,y)+f(x-1,y)+f(x,y+1)+f(x,y-1)-4f(x,y)\end{aligned}$$
常用模板公式:(1)$\begin{bmatrix}0&1&0\\1&-4&1\\0&1&0\end{bmatrix}$(2)$\begin{bmatrix}1&1&1\\1&-8&1\\1&1&1\end{bmatrix}$
拉普拉斯模板有多个变种,上面是常用的两个,对于每一个像素,我们把他作为模板的中心元素,套用公式进行更新。需要注意的是,与梯度算子不同,他是各向同性的,因此不需要$G_x$,$G_y$两个模板,也就不能区分边缘的方向了。
还有一个常用的高斯-拉普拉斯算子(Gauss-Laplacian Operator),将平滑滤波器和拉普拉斯边缘检测算子结合起来的:
高斯-拉普拉斯算子模板:$\begin{bmatrix}-2&-4&-4&-4&-2\\-4&0&8&0&-4\\-4&8&24&8&-4\\-4&0&8&0&-4\\-2&-4&-4&-4&-2\end{bmatrix}$
另外,拉普拉斯算子有一个很实用的用途,就是对图像进行锐化,这时候只要将常用模板稍微改动一下即可得到锐化模板:
(1)$\begin{bmatrix}0&-1&0\\-1&5&-1\\0&-1&0\end{bmatrix}$(2)$\begin{bmatrix}-1&-1&-1\\-1&9&-1\\-1&-1&-1\end{bmatrix}$
测试
OK,最后就是用代码实现一下了,总体还是很简单的,而且类似于OpenCV之类的库都有实现的函数。不过我还是用pil来简单实现一下:
1 | import Image,matplotlib,sys,ImageEnhance,ImageFont,ImageDraw |
最后用他来处理一下lena.png,会的到上面的结果。