导读
在这篇文章中,我们将学习如何在OpenCV中使用基于深度学习的边缘检测,它比目前流行的canny边缘检测器更精确。边缘检测在许多用例中是有用的,如视觉显著性检测,目标检测,跟踪和运动分析,结构从运动,3D重建,自动驾驶,图像到文本分析等等。 什么是边缘检测?边缘检测是计算机视觉中一个非常古老的问题,它涉及到检测图像中的边缘来确定目标的边界,从而分离感兴趣的目标。最流行的边缘检测技术之一是Canny边缘检测,它已经成为大多数计算机视觉研究人员和实践者的首选方法。让我们快速看一下Canny边缘检测。 Canny边缘检测算法1983年,John Canny在麻省理工学院发明了Canny边缘检测。它将边缘检测视为一个信号处理问题。其核心思想是,如果你观察图像中每个像素的强度变化,它在边缘的时候非常高。 在下面这张简单的图片中,强度变化只发生在边界上。所以,你可以很容易地通过观察像素强度的变化来识别边缘。 现在,看下这张图片。强度不是恒定的,但强度的变化率在边缘处最高。(微积分复习:变化率可以用一阶导数(梯度)来计算。) Canny边缘检测器通过4步来识别边缘:
梯度方向垂直于边缘,它被映射到四个方向中的一个(水平、垂直和两个对角线方向)。
迟滞阈值化 Canny 边缘检测的问题:由于Canny边缘检测器只关注局部变化,没有语义(理解图像的内容)理解,精度有限(很多时候是这样)。 Canny边缘检测器在这种情况下会失败,因为没有理解图像的上下文 语义理解对于边缘检测是至关重要的,这就是为什么使用机器学习或深度学习的基于学习的检测器比canny边缘检测器产生更好的结果。 OpenCV中基于深度学习的边缘检测OpenCV在其全新的DNN模块中集成了基于深度学习的边缘检测技术。你需要OpenCV 3.4.3或更高版本。这种技术被称为整体嵌套边缘检测或HED,是一种基于学习的端到端边缘检测系统,使用修剪过的类似vgg的卷积神经网络进行图像到图像的预测任务。 HED利用了中间层的输出。之前的层的输出称为side output,将所有5个卷积层的输出进行融合,生成最终的预测。由于在每一层生成的特征图大小不同,它可以有效地以不同的尺度查看图像。 网络结构:整体嵌套边缘检测 HED方法不仅比其他基于深度学习的方法更准确,而且速度也比其他方法快得多。这就是为什么OpenCV决定将其集成到新的DNN模块中。以下是这篇论文的结果: 在OpenCV中训练深度学习边缘检测的代码OpenCV使用的预训练模型已经在Caffe框架中训练过了,可以这样加载: sh download_pretrained.sh 网络中有一个crop层,默认是没有实现的,所以我们需要自己实现一下。
现在,我们可以重载这个类,只需用一行代码注册该层。 cv.dnn_registerLayer('Crop', CropLayer) 现在,我们准备构建网络图并加载权重,这可以通过OpenCV的dnn.readNe函数。
现在,下一步是批量加载图像,并通过网络运行它们。为此,我们使用cv2.dnn.blobFromImage方法。该方法从输入图像中创建四维blob。 blob = cv.dnn.blobFromImage(image, scalefactor, size, mean, swapRB, crop) 其中: image:是我们想要发送给神经网络进行推理的输入图像。 scalefactor:图像缩放常数,很多时候我们需要把uint8的图像除以255,这样所有的像素都在0到1之间。默认值是1.0,不缩放。 size:输出图像的空间大小。它将等于后续神经网络作为blobFromImage输出所需的输入大小。 swapRB:布尔值,表示我们是否想在3通道图像中交换第一个和最后一个通道。OpenCV默认图像为BGR格式,但如果我们想将此顺序转换为RGB,我们可以将此标志设置为True,这也是默认值。 mean:为了进行归一化,有时我们计算训练数据集上的平均像素值,并在训练过程中从每幅图像中减去它。如果我们在训练中做均值减法,那么我们必须在推理中应用它。这个平均值是一个对应于R, G, B通道的元组。例如Imagenet数据集的均值是R=103.93, G=116.77, B=123.68。如果我们使用swapRB=False,那么这个顺序将是(B, G, R)。 crop:布尔标志,表示我们是否想居中裁剪图像。如果设置为True,则从中心裁剪输入图像时,较小的尺寸等于相应的尺寸,而其他尺寸等于或大于该尺寸。然而,如果我们将其设置为False,它将保留长宽比,只是将其调整为固定尺寸大小。 在我们这个场景下:
现在,我们只需要调用一下前向方法。 net.setInput(inp)out = net.forward()out = out[0, 0]out = cv.resize(out, (frame.shape[1], frame.shape[0]))out = 255 * outout = out.astype(np.uint8)out=cv.cvtColor(out,cv.COLOR_GRAY2BGR)con=np.concatenate((frame,out),axis=1)cv.imshow(kWinName,con) 结果: 中间的图像是人工标注的图像,右边是HED的结果 中间的图像是人工标注的图像,右边是HED的结果 文中的代码:https://github.com/sankit1//tree/master/OpenCV/Edge_detection 英文原文:https:///opencv-dnn/edge-detection-hed/ |
|
来自: taotao_2016 > 《图像处理》