边缘检测算子
要得到一张图片的边缘,我们可以通过边缘算子,下面着重介绍Sobel算子。
Sobel算子是典型的基于一阶导数的边缘检测算子,由于该算子中引入了类似局部平均的运算,因此对噪声具有平滑作用,能很好的消除噪声的影响。Sobel算子对于象素的位置的影响做了加权。
Sobel算子包含两组3x3的矩阵,分别为横向及纵向模板,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。实际使用中,常用如下两个模板来检测图像边缘。
检测水平边沿 横向模板:
检测垂直平边沿 纵向模板:
图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小。
最后用以下公式计算梯度方向:
最后代码如下:
import cv2
import numpy as np
img = cv2.imread("./image.jpg", 0)
x = cv2.Sobel(img,cv2.CV_16S,1,0)
y = cv2.Sobel(img,cv2.CV_16S,0,1)
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
dst = cv2.addWeighted(absX,0.5,absY,0.5,0)
cv2.imshow("absX", absX)
cv2.imshow("absY", absY)
cv2.imshow("Result", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
Holistically-Nested Edge Detection
这篇文章使用深度学习的方法,其中Holistically表示该算法试图训练一个image-to-image的网络;Nested则强调在生成的输出过程中通过不断的集成和学习得到更精确的边缘预测图的过程。文章把HED和传统Canny算法进行边缘检测的效果对比,如下图我们可以看到HED的效果要明显优于Canny算子的。
网络具体实现:
使用VGG-16作为骨干网络,并且使用迁移学习初始化网络权重。
文章中列举了几种multi scale的deeplearning方法,具体如下图
(a) Multi-stream learning: 使用不同结构,不同参数的网络训练同一副图片,类似的结构有Inception;
(b) Skip-layer network learning:该结构有一个主干网络,在主干网络中添加若干条到输出层的skip-layer,类似的结构有FPN;
(c) Single model on multiple inputs: 该方法使用同一个网络,不同尺寸的输入图像得到不同尺度分Feature Map,YOLOv2采用了该方法;
(d) Training independent network: 使用完全独立的网络训练同一张图片,得到多个尺度的结果,该方法类似于集成模型;
(e) Holistically-Nested networks: HED采用的方法。
Holistically-Nested networks的具体结构如图:
VGG-16作为backbone。在VGG-16的5个block的Max Pooling降采样之前,HED通过side_branch函数产生了5个分支,最后这5个side_branch的输出通过Concatenate操作合并在一起。网络的5个side_branch和一个fuse branch通过sigmoid激活函数后共同作为网络的输出,每个输出的尺寸均和输入图像相同。
损失函数
损失函数主要涉及关于side branch的目标函数和fuse层的损失函数。
网络最后的目标就是最小化这个两个损失之和: