使用OpenCV对车道进行实时检测的实现示例代码

项目介绍

下图中的两条线即为车道:

我们的任务就是通过 OpenCV 在一段视频(或摄像头)中实时检测出车道并将其标记出来。其效果如下图所示:

这里使用的代码来源于磐怼怼大神,此文章旨在对其代码进行解释。

实现步骤

1、将视频的所有帧读取为图片;

2、创建掩码并应用到这些图片上;

3、图像阈值化;

4、用霍夫线变换检测车道;

5、将车道画到每张图片上;

6、将所有图片合并为视频。

代码实现

1、导入需要的库

import os
import re
import cv2
import numpy as np
from tqdm import notebook
import matplotlib.pyplot as plt

其中 tqdm.notebook 是用来显示进度条的。

2、将图片(视频的每一帧)加载进来

这里我们已经将视频的每一帧读取为图片了,并将它们都放进 frames 文件夹。

# 获取帧的文件名
col_frames = os.listdir('frames/') # 读取 frames 文件夹下的所有图片
col_frames.sort(key=lambda f: int(re.sub('\D', '', f))) # 按名称对图片进行排序

# 加载帧
col_images=[]
for i in notebook.tqdm(col_frames):
  img = cv2.imread('frames/'+i)
  col_images.append(img) # 将所有图片添加进 col_images 列表

3、选择一张图片进行处理

3.1 选定一张图片

# 指定一个索引
idx = 457

# plot frame
plt.figure(figsize=(10,10))
plt.imshow(col_images[idx][:,:,0], cmap= "gray")
plt.show()

3.2 创建掩码

# 创建0矩阵
stencil = np.zeros_like(col_images[idx][:,:,0])

# 指定多边形的坐标
polygon = np.array([[50,270], [220,160], [360,160], [480,270]])

# 用1填充多边形
cv2.fillConvexPoly(stencil, polygon, 1)

# 画出多边形
plt.figure(figsize=(10,10))
plt.imshow(stencil, cmap= "gray")
plt.show()

3.3 将掩码应用到图片上

# 应用该多边形作为掩码
img = cv2.bitwise_and(col_images[idx][:,:,0], col_images[idx][:,:,0], mask=stencil)

# 画出掩码后的图片
plt.figure(figsize=(10,10))
plt.imshow(img, cmap= "gray")
plt.show()

这里的按位与操作 cv2.bitwise_and() 可以参考OpenCV 之按位运算举例解析一文。

3.4 图像阈值化

# 应用图像阈值化
ret, thresh = cv2.threshold(img, 130, 145, cv2.THRESH_BINARY)

# 画出图像
plt.figure(figsize=(10,10))
plt.imshow(thresh, cmap= "gray")
plt.show()

其中 cv2.threshold 函数的用法可以参考Opencv之图像阈值一文。

3.5 霍夫线变换检测车道

lines = cv2.HoughLinesP(thresh, 1.0, np.pi/180, 30, maxLineGap=200)

# 创建原始帧的副本
dmy = col_images[idx][:,:,0].copy()

# 霍夫线
for line in lines:
  x1, y1, x2, y2 = line[0] # 提取出霍夫线的坐标
  cv2.line(dmy, (x1, y1), (x2, y2), (255, 0, 0), 3) # 将霍夫线画在帧上

# 画出帧
plt.figure(figsize=(10,10))
plt.imshow(dmy, cmap= "gray")
plt.show()

cv2.HoughLinesP() 函数介绍:

lines = HoughLinesP(image, rho, theta, threshold, minLineLength=None, maxLineGap=None)

输入:

  • image: 必须是二值图像;
  • rho: 线段以像素为单位的距离精度,double类型的,推荐用1.0
  • theta: 线段以弧度为单位的角度精度,推荐用numpy.pi/180
  • threshod: 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。
  • minLineLength:线段以像素为单位的最小长度。
  • maxLineGap:同一方向上两条线段判定为一条线段的最大允许间隔,超过了设定值,则把两条线段当成一条线段。

输出:

lines:一个三维矩阵,其形状符合 (m, 1, n),其中 m 表示直线个数,n 表示每条直线的两端坐标。

4、对每张图片进行上一步骤的处理后写入视频

4.1 定义视频格式

# 输出视频路径
pathOut = 'roads_v2.mp4'

# 视频每秒的帧数
fps = 30.0

# 视频中每一帧的尺寸
height, width = img.shape
size = (width,height)

# 写入视频
out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'DIVX'), fps, size)

4.2 处理所有图片并写入视频文件

for img in notebook.tqdm(col_images):

  # 应用帧掩码
  masked = cv2.bitwise_and(img[:,:,0], img[:,:,0], mask=stencil)

  # 应用图像阈值化
  ret, thresh = cv2.threshold(masked, 130, 145, cv2.THRESH_BINARY)

  # 应用霍夫线变换
  lines = cv2.HoughLinesP(thresh, 1, np.pi/180, 30, maxLineGap=200)
  dmy = img.copy()

  #画出检测到的线
  try:
    for line in lines:
      x1, y1, x2, y2 = line[0]
      cv2.line(dmy, (x1, y1), (x2, y2), (255, 0, 0), 3)

    out.write(dmy)

  except TypeError:
    out.write(img)

out.release()

完整代码

import os
import re
import cv2
import numpy as np
from tqdm import notebook
import matplotlib.pyplot as plt

col_frames = os.listdir('frames/')
col_frames.sort(key=lambda f: int(re.sub('\D', '', f)))

col_images=[]
for i in notebook.tqdm(col_frames):
  img = cv2.imread('frames/'+i)
  col_images.append(img)

stencil = np.zeros_like(col_images[0][:,:,0])
polygon = np.array([[50,270], [220,160], [360,160], [480,270]])
cv2.fillConvexPoly(stencil, polygon, 1)

pathOut = 'roads_v2.mp4'

fps = 30.0

height, width = img.shape
size = (width,height)

out = cv2.VideoWriter(pathOut,cv2.VideoWriter_fourcc(*'DIVX'), fps, size)

for img in notebook.tqdm(col_images):

  masked = cv2.bitwise_and(img[:,:,0], img[:,:,0], mask=stencil)

  ret, thresh = cv2.threshold(masked, 130, 145, cv2.THRESH_BINARY)

  lines = cv2.HoughLinesP(thresh, 1, np.pi/180, 30, maxLineGap=200)
  dmy = img.copy()

  try:
    for line in lines:
      x1, y1, x2, y2 = line[0]
      cv2.line(dmy, (x1, y1), (x2, y2), (255, 0, 0), 3)

    out.write(dmy)

  except TypeError:
    out.write(img)

out.release()

到此这篇关于使用OpenCV对车道进行实时检测的实现示例代码的文章就介绍到这了,更多相关OpenCV 车道实时检测内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

时间: 2020-06-19

opencv车道线检测的实现方法

车道线检测,需要完成以下功能: 图像裁剪:通过设定图像ROI区域,拷贝图像获得裁剪图像 反透视变换:用的是室外采集到的视频,没有对应的变换矩阵.所以建立二维坐标,通过四点映射的方法计算矩阵,进行反透视变化.后因ROI区域的设置易造成变换矩阵获取困难和插值得到的透视图效果不理想,故没应用 二值化:先变化为灰度图,然后设定阈值直接变成二值化图像. 形态学滤波:对二值化图像进行腐蚀,去除噪点,然后对图像进行膨胀,弥补对车道线的腐蚀. 边缘检测:canny变化.sobel变化和laplacian变化中选

OpenCV实现人脸检测

前段日子,写了个人脸检测的小程序,可以检测标记图片.视频.摄像头中的人脸.效果还行吧,用的是opencv提供人脸库.至于具体的人脸检测原理,找资料去啃吧. 环境:VS2013+OPENCV2.4.10+Win8.1 一.基于对话框的MFC 首先,新建一个基于对话框的MFC应用程序,命名为myFaceDetect(取消"安全开发周期(SDL)检查"勾选,我自己习惯取消这个). 放置Button,设置Button的ID和Caption. 图片按钮--ID:IDC_FACEDETECT 视频

C++利用opencv实现人脸检测

小编所有的帖子都是基于unbuntu系统的,当然稍作修改同样试用于windows的,经过小编的绞尽脑汁,把刚刚发的那篇python 实现人脸和眼睛的检测的程序用C++ 实现了,当然,也参考了不少大神的博客,下面我们就一起来看看: Linux系统下安装opencv我就再啰嗦一次,防止有些人没有安装没调试出来喷小编的程序是个坑, sudo apt-get install libcv-dev sudo apt-get install libopencv-dev 看看你的usr/share/opencv

Java+OpenCV实现人脸检测并自动拍照

java+opencv实现人脸检测,调用笔记本摄像头实时抓拍,人脸会用红色边框标识出来,并且将抓拍的目录存放在src下,图片名称是时间戳. 环境配置:win7 64位,jdk1.8 CameraBasic.java package com.njupt.zhb.test; import java.awt.EventQueue; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; im

Python下应用opencv 实现人脸检测功能

使用OpenCV's Haar cascades作为人脸检测,因为他做好了库,我们只管使用. 代码简单,除去注释,总共有效代码只有10多行. 所谓库就是一个检测人脸的xml 文件,可以网上查找,下面是一个地址: https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml 如何构造这个库,学习完本文后可以参考: http://note.sonots.com/Sc

Oracle字符函数应用检测汉字的方法

-- 验证是否包含汉字 create table test(a varchar2(10)); insert into test values('鸟'); insert into test values('深刻'); insert into test values('aaa'); insert into test values('bbb'); insert into test values('b鸟bb'); SELECT * FROM TEST; -- 对于全角字符,ascii值的范围是\uFF0

C++ 网络连通性检测的实现方法

C++ 网络连通性检测的实现方法 有时程序需要保持和某个指定网络的连通,有人的情况下我们直接用ping命令查看即可,然而程序自身检测会稍微麻烦一点. 实现思路如下: 用程序打开控制台->运行ping命令,并指定控制台返回值写入到文件中->分析文件,得到ping命令返回状态->得到网络连通情况 代码如下: #include <windows.h> #include <stdio.h> #include <string> using namespace s

php实现html标签闭合检测与修复方法

本文实例讲述了php实现html标签闭合检测与修复方法.分享给大家供大家参考.具体如下: html标签闭合检测与修复,说的有点大 , 并没有考虑的很完整,没有使用正则表达式, 适用于html文件中只有开始标签没有结束标签, 是有结束标签没有开始标签的情况.标签闭合的位置需要根据需求调整 <?php $str = ' <div data="<li></li>"> <img src="http://www.baidu.com/123

基于openCV实现人脸检测

openCV的人脸识别主要通过Haar分类器实现,当然,这是在已有训练数据的基础上.openCV安装在 opencv/opencv/sources/data/haarcascades_cuda(或haarcascades)中存在预先训练好的物体检测器(xml格式),包括正脸.侧脸.眼睛.微笑.上半身.下半身.全身等. openCV的的Haar分类器是一个监督分类器,首先对图像进行直方图均衡化并归一化到同样大小,然后标记里面是否包含要监测的物体.它首先由Paul Viola和Michael Jon

vue将对象新增的属性添加到检测序列的方法

vue中将对象中新增的属性增加到检测序列中 deepCopy(o1, o2) { // 将o2的内容拷贝给data中的o1 var key, i if (o2 instanceof Array) { for (i = 0; i < o2.length; i++) { if (o2[i] instanceof Array) { this.$set(o1, i, []) this.deepCopy(o1[i], o2[i]) } else if (o2[i] instanceof Object) {