使用Python中OpenCV和深度学习进行全面嵌套边缘检测
作者:程序媛一枚~ 发布时间:2021-04-21 10:21:34
这篇博客将介绍如何使用OpenCV和深度学习应用全面嵌套的边缘检测。并将对图像和视频流应用全面嵌套边缘检测,然后将结果与OpenCV的标准Canny边缘检测器进行比较。
1. 效果图
愤怒的小鸟——原始图 VS Canny边缘检测图 VS HED边缘检测图
花朵——原始图 VS Canny边缘检测图 VS HED边缘检测图
视频效果图GIF 如下
2. 全面嵌套边缘检测与Canny边缘检测
2.1 Hed与Canny边缘检测对比
Holistically-Nested Edge Detection (HED) 全面嵌套边缘检测
Canny Edge Detection Canny边缘检测
OpenCV 利用Canny边缘检测能够找到图像中对象的边界。但是Canny边缘检测器存在一些问题,即:
需要手动验证(将下部和上值设置为滞后阈值,是一种需要实验和视觉验证的手动过程);
不具备通用性(对不同照明条件下捕获的相同图像,适用于一个图像,却不适用于另一个图像);
通常需要许多预处理步骤(即转换为灰度,模糊/平滑等),以获得良好的边缘图。
整体嵌套边缘检测(HED)试图通过端到端深神经网络解决Canny边缘检测器的局限性。
该网络接受RGB图像作为输入,然后将边缘图作为输出产生。而且通过HED产生的边缘图在图像中很好的保留了对象边界。
2.2. 项目结构
2.3 deploy.prototxt, hed_pretrained_bsds.caffemodel下载
执行代码的关键是获取deploy.prototxt, hed_pretrained_bsds.caffemodel
https://github.com/opencv/opencv/blob/master/samples/dnn/edge_detection.py
https://github.com/seminar2012/hed
This sample shows how to define custom OpenCV deep learning layers in Python.
Holistically-Nested Edge Detection (https://arxiv.org/abs/1504.06375) neural network is used as an example model.
Find a pre-trained model at https://github.com/s9xie/hed. We provide the pretrained model and training/testing code for the edge detection framework Holistically-Nested Edge Detection (HED).
Please see the Arxiv or ICCV paper for technical details. The pretrained model (fusion-output) gives ODS=.790 and OIS=.808 result on BSDS benchmark dataset.
Download the pretrained model (56MB) from (http://vcl.ucsd.edu/hed/hed_pretrained_bsds.caffemodel) and place it in examples/hed/ folder.
3. 源码
3.1 对图像进行HED检测
# USAGE
# python detect_edges_image.py --edge-detector hed_model --image images/bird.jpg
# 导入必要的包
import argparse
import cv2
import os
import imutils
# 构建命令行参数及解析
# --edge-detector Holistically-Nested Edge Detection检测器模型路径
# --image 图片路径
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--edge-detector", type=str, required=True,
help="path to OpenCV's deep learning edge detector")
ap.add_argument("-i", "--image", type=str, required=True,
help="path to input image")
args = vars(ap.parse_args())
class CropLayer(object):
def __init__(self, params, blobs):
# 初始化剪切区域开始和结束点的坐标
self.xstart = 0
self.ystart = 0
self.xend = 0
self.yend = 0
# 计算输入图像的体积
def getMemoryShapes(self, inputs):
# 剪切类将接收俩个参数
# 剪切第一个输入blob以匹配第二个blob,保持批次和通道数
# 输出输入容积的形状及目标形状
# 提取批量大小及通道数
# 分别提取目标形状的高和宽
(inputShape, targetShape) = (inputs[0], inputs[1])
(batchSize, numChannels) = (inputShape[0], inputShape[1])
(H, W) = (targetShape[2], targetShape[3])
# 计算开始和结束剪切坐标的值
self.xstart = int((inputShape[3] - targetShape[3]) // 2)
self.ystart = int((inputShape[2] - targetShape[2]) // 2)
self.xend = self.xstart + W
self.yend = self.ystart + H
# 返回体积,接下来进行实际裁剪
return [[batchSize, numChannels, H, W]]
def forward(self, inputs):
return [inputs[0][:, :, self.ystart:self.yend, self.xstart:self.xend]]
# 从磁盘加载序列化的边缘检测器模型
print("[INFO] loading edge detector...")
protoPath = os.path.sep.join([args["edge_detector"],
"deploy.prototxt"])
modelPath = os.path.sep.join([args["edge_detector"],
"hed_pretrained_bsds.caffemodel"])
net = cv2.dnn.readNetFromCaffe(protoPath, modelPath)
# 绑定剪裁类到模型
cv2.dnn_registerLayer("Crop", CropLayer)
# 加载输入图像,获取其维度
image = cv2.imread(args["image"])
image = imutils.resize(image, width=400)
(H, W) = image.shape[:2]
# 转换图像为灰度图,高斯平滑,执行Canny边缘检测
print("[INFO] performing Canny edge detection...")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
canny = cv2.Canny(blurred, 30, 150)
# 根据输入图像为全面的嵌套边缘检测器(Holistically-Nested Edge Detector)构建一个输出blob
blob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size=(W, H),
mean=(104.00698793, 116.66876762, 122.67891434),
swapRB=False, crop=False)
# # 设置blob作为网络的输入并执行算法以计算边缘图
print("[INFO] performing holistically-nested edge detection...")
net.setInput(blob)
hed = net.forward()
# 调整输出为原始图像尺寸的大小
hed = cv2.resize(hed[0, 0], (W, H))
# 将图像像素缩回到范围[0,255]并确保类型为“UINT8”
hed = (255 * hed).astype("uint8")
# 展示HED边缘检测的结果及Canny边缘检测的结果
cv2.imshow("Input", image)
cv2.imshow("Canny", canny)
cv2.imshow("HED", hed)
cv2.waitKey(0)
3.2 对视频进行HED检测
# USAGE 默认使用电脑自带的摄像头
# python detect_edges_video.py --edge-detector hed_model
# 使用视频文件流
# python detect_edges_video.py --edge-detector hed_model --input xl.mp4
# 导入必要的包
from imutils.video import VideoStream
import argparse
import imutils
import time # 此模块允许放置睡眠命令以允许视频流建立和“热身”。
import cv2
import os
# 构建命令行参数及解析
# --edge-detector Holistically-Nested Edge Detection检测器模型路径
# --input 视频源:网络摄像头,视频文件或其他源。
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--edge-detector", type=str, required=True,
help="path to OpenCV's deep learning edge detector")
ap.add_argument("-i", "--input", type=str,
help="path to optional input video (webcam will be used otherwise)")
args = vars(ap.parse_args())
class CropLayer(object):
def __init__(self, params, blobs):
# 初始化剪切区域开始和结束点的坐标
self.xstart = 0
self.ystart = 0
self.xend = 0
self.yend = 0
# 计算输入图像的体积
def getMemoryShapes(self, inputs):
# 剪切类将接收俩个参数
# 剪切第一个输入blob以匹配第二个blob,保持批次和通道数
# 输出输入容积的形状及目标形状
# 提取批量大小及通道数
# 分别提取目标形状的高和宽
(inputShape, targetShape) = (inputs[0], inputs[1])
(batchSize, numChannels) = (inputShape[0], inputShape[1])
(H, W) = (targetShape[2], targetShape[3])
# 计算开始和结束剪切坐标的值
self.xstart = int((inputShape[3] - targetShape[3]) // 2)
self.ystart = int((inputShape[2] - targetShape[2]) // 2)
self.xend = self.xstart + W
self.yend = self.ystart + H
# 返回体积,接下来进行实际裁剪
return [[batchSize, numChannels, H, W]]
def forward(self, inputs):
# 使用派生(x,y)-oordinate来执行裁剪
return [inputs[0][:, :, self.ystart:self.yend, self.xstart:self.xend]]
# 初始化视频流,脚本将动态选取使用视频文件流还是网络摄像头流
webcam = not args.get("input", False)
# 如果未提供视频文件路径,则使用电脑自带摄像头
if webcam:
print("[INFO] starting video stream...")
vs = VideoStream(src=0).start()
time.sleep(2.0)
# 否则,获取视频文件流指针
else:
print("[INFO] opening video file...")
vs = cv2.VideoCapture(args["input"])
# 从磁盘加载序列化的HED检测器模型
print("[INFO] loading edge detector...")
protoPath = os.path.sep.join([args["edge_detector"],
"deploy.prototxt"])
modelPath = os.path.sep.join([args["edge_detector"],
"hed_pretrained_bsds.caffemodel"])
net = cv2.dnn.readNetFromCaffe(protoPath, modelPath)
# 将剪裁类注册到模型
cv2.dnn_registerLayer("Crop", CropLayer)
# 遍历视频流的帧
while True:
# 获取每一帧,如果使用网络摄像头,获取下一帧
frame = vs.read()
frame = frame if webcam else frame[1]
# 如果在处理视频文件流,没有获取到帧则代表已经到了文件尾部,则跳出循环
if not webcam and frame is None:
break
# 等比例缩放帧为宽度500,并获取其维度
frame = imutils.resize(frame, width=300)
(H, W) = frame.shape[:2]
# 转换灰度图,高斯模糊并执行Canny边缘检测
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
canny = cv2.Canny(blurred, 30, 150)
# 为HED边缘检测器构建输入帧的blob,设置blob,并执行检测以计算边缘图
blob = cv2.dnn.blobFromImage(frame, scalefactor=1.0, size=(W, H),
mean=(104.00698793, 116.66876762, 122.67891434),
swapRB=False, crop=False)
net.setInput(blob)
hed = net.forward()
hed = cv2.resize(hed[0, 0], (W, H))
hed = (255 * hed).astype("uint8")
# 展示Canny、HED的检测结果
cv2.imshow("Frame", frame)
cv2.imshow("Canny", canny)
cv2.imshow("HED", hed)
key = cv2.waitKey(1) & 0xFF
# 按下‘q'键表示退出循环
if key == ord("q"):
break
# 如果在使用网络摄像头流,则终止相机视频流
if webcam:
vs.stop()
# 否则,释放视频文件流指针
else:
vs.release()
# 关闭所有打开的window
cv2.destroyAllWindows()
参考
https://www.pyimagesearch.com/2019/03/04/holistically-nested-edge-detection-with-opencv-and-deep-learning/
来源:https://blog.csdn.net/qq_40985985/article/details/116495758


猜你喜欢
- 学习Python,基本语法不是特别难,有了C的基本知识,理解比较容易。本文的主要内容是Python基础语法,学完后,能熟练使用就好。(开发环
- 下面看下Ubuntu 18.04.4安装mysql的过程,内容如下所示:1 sudo apt-get update2 sudo a
- 事件循环(Event Loop),是每个JS开发者都会接触到的概念,但是刚接触时可能会存在各种疑惑。众所周知,JS是单线程的,即同一时间只能
- 回滚段管理一直是ORACLE数据库管理的一个难题,本文通过实例介绍ORACLE回滚段的概念,用法和规划及问题的解决。 回滚段概述 回滚段用于
- 直接上代码:1. 第一种情况如果没有select{}, main 主线程不会等待coroutine运行,导致coroutine得不到机会运行
- 前言神经网络在设置的神经网络足够复杂的情况下,可以无限逼近一段非线性连续函数,但是如果神经网络设置的足够复杂,将会导致过拟合(overfit
- 关于代码调试的技巧,我之前写过很多的文章,关注比较早的同学,也应该都有看过。还没看过的同学,欢迎前往查阅:更多Python代码调试技巧其中有
- image.func.php<?php require_once('string.func.php');functio
- 背景:Python是一种解释性的语言,执行速度相比C、C++等语言十分缓慢;因此我们需要在其它地方上下功夫来提高代码的执行速度。首先需要对代
- 一、前言卷起来好吧,元旦已经过了,就开始写文章模式了。这篇文章会对完全数的各种侦测进行详细解释。写作不易,支持一波~二、完全数是什么1、定义
- 问题描述使用 Navicat 导入之前转储好的 sql 文件,报错错误原因在信息日志当中往上翻,发现没有选择数据库,所以报错的原因就是没有提
- canal简介由阿里巴巴开源 github地址:https://github.com/alibaba/canalCanal是阿里巴巴开源的一
- 上拉加载以及下拉刷新都是移动端很常见的功能,在搜索或者一些分类列表页面常常会用到。跟横向滚动一样,我们还是采用better-scroll这个
- Sqlserver2005日志文件太大,使其减小的方法如下所示:运行下面的三行 dbName为数据库名: backup log dbName
- 运行多进程 每个子进程的内存空间是互相隔离的 进程之间数据不能共享的互斥锁但是进程之间都是运行在一个操作系统上,进程之间数据不共享,但是共享
- 首先要声明一下:一般情况下,修改MySQL密码,授权,是需要有mysql里的root权限的。 注:本操作是在WIN命令提示符下,phpMyA
- 在SQL SERVER 2005下还原数据库1、新建数据库A,右键还原数据库,此时目标数据库为A,选择备份文件B_db_2013110402
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&
- 本文实例为大家分享了js文字列表无缝滚动的具体代码,供大家参考,具体内容如下HTML代码:<div id="rule&quo
- 本文实例讲述了php+redis实现注册、删除、编辑、分页、登录、关注等功能。分享给大家供大家参考,具体如下:主要界面连接redisredi