cv2 python 获取斑马线_opencv 斑马线,条纹检测

2023-11-05

斑马线检测 基于OpenCV

效果不是很好

设置DEBUG变量为True时会输出每一步图像用于逐帧debug和调参(按下任意键或者按住不放下一步),设为False则只画最后结果图。

红色方框是判断为斑马线的滑窗,紫色方框是最终输出的斑马线位置(紫框计算目前默认了图内只会出现一条斑马线)

github: https://github.com/TomMao23/ZebraCrossing_Detection

基本思路

总结斑马线的四个特征:

梯度一致性

等间隔

多根线

斑马线比车道线宽

梯度一致性和等间隔是两个强分类特征,其中梯度一致性特征易召回,等间隔特征强精度。目前算法未使用等间隔特征,主要利用梯度一致,另外两个特征辅助。

转逆透视图, 中值滤波,开运算,闭运算预处理后Canny边缘检测,对边缘检测图用sobel求横纵梯度,得到梯度的模值和方向(方向归为0到90度, 即不区分正反),先过滤梯度太小的点。在滑窗内统计0:70度间隔5度的点直方图,取峰值方向的点数作为判断量,高于阈值判为斑马线。

问题及当前解决思路

过滤减速带:减速带同样具有梯度一致性,等间隔和线多的三个特征,但是有线短的特点,所以滑窗高度取得越大减速带越容易过滤,这是永远管用的。另一方面, 减速带是黄色(红+绿)黑色相间的,所以单使用蓝色通道而不是正常RGB转成的灰度图可以大大衰减减速带的梯度影响。

开运算有两个作用:能够减少噪点,可以利用斑马线比车道线更宽的特点用多iterations参数的开运算在保留斑马线的同时直接去除车道线干扰(缺点:若斑马线有磨损开运算会有一定损失,灰度图开运算可能会产生弱的虚假边缘,可以调参不检测出来)。

闭运算有两个作用:一是能够填补线磨损增强斑马线的边缘识别效果, 二是路面箭头破损时容易产生少量梯度杂乱的边缘增加误检的概率(如果斑马线无破损,阈值可以设得很高就没有这个问题)。即使无破损闭运算仍然很好地减少了其他元素的虚假边缘。

中值滤波的重要性:比起均值滤波等滤波器,同样是平滑的效果,并提升边缘检测效果,中值滤波保留了原始梯度大小更利于边缘的检出,同时可以完美地消除人行道的小砖缝纹理,所以中值滤波是必选。

canny的重要性:试过直接用sobel x,y来做但是:

噪点虚假边缘较多。

一个边缘多个点,斑马线线多的特征被衰弱。

这么做只有一个梯度阈值判断过滤边缘,之后再根据梯度方向过滤,canny两个阈值并考虑连通性解决了前两个问题并且调参更方便,好效果的参数的范围也更大。所以用canny。

过滤停止线:由于当前方法利用线多特征,是在宽大于高的矩形滑窗内统计峰值梯度方向的点数(纵线斜线自然是线越多这样统计的点越多),直行时的停止线恰好在滑窗内且是横线峰值梯度方向点也会较多,所以统计时只取到0到70度(x轴方向梯度为0度),当转弯或斜行时停止线在滑窗内峰值梯度方向点不多,自然过滤。

主要干扰:停止线和减速带的干扰很小,容易调节阈值, 不成问题。路面箭头等标志是目前主要干扰,因为斑马线有缺损综合考虑召回不能把阈值调得非常高(目前阈值是1500,无缺损的清晰斑马线值会在4000到6000),当前阈值在测试图上无误检但有风险(部分箭头图最高值达到1300), 若是无缺损的清晰的斑马线可以把阈值调高解决这个问题。可能干扰:路面外边缘可能造成干扰,目前无,若出现此干扰可以调整滑窗位置大小尽可能不扫路面外解决这个问题。

结果示例

e806239b33e4b0ca01929e2954047a35.png

0f1bca5d1fe55846db08e4e2ab046991.png

代码示例

//处理逆透视后的图

#coding=utf-8

import time

import os

import cv2

import numpy as np

from numpy.linalg import inv

def sliding_window(img1, img2, patch_size=(100,302), istep=50):#, jstep=1, scale=1.0):

"""

get patches and thier upper left corner coordinates

The size of the sliding window is currently fixed.

patch_size: sliding_window's size'

istep: Row stride

"""

Ni, Nj = (int(s) for s in patch_size)

for i in range(0, img1.shape[0] - Ni+1, istep):

#for j in range(0, img1.shape[1] - Nj, jstep):

#patch = (img1[i:i + Ni, j:j + Nj], img2[i:i + Ni, j:j + Nj])

patch = (img1[i:i + Ni, 39:341], img2[i:i + Ni, 39:341])

yield (i, 39), patch

def predict(patches, DEBUG):

"""

predict zebra crossing for every patches 1 is zc 0 is background

"""

#print(len(patches))

labels = np.zeros(len(patches))

index = 0

for Amplitude, theta in patches:

mask = (Amplitude>25).astype(np.float32)

h, b = np.histogram(theta[mask.astype(np.bool)], bins=range(0,80,5))

low, high = b[h.argmax()], b[h.argmax()+1]

newmask = ((Amplitude>25) * (theta<=high) * (theta>=low)).astype(np.float32)

value = ((Amplitude*newmask)>0).sum()

if value > 1500:

labels[index] = 1

index += 1

if(DEBUG):

print(h)

print(low, high)

print(value)

cv2.imshow("newAmplitude", Amplitude*newmask)

cv2.waitKey(0)

return labels

def preprocessing(img):

"""

Take the blue channel of the original image and filter it smoothly

"""

kernel1 = np.ones((3,3),np.uint8)

kernel2 = np.ones((5,5),np.uint8)

gray = img[:,:,0]

gray = cv2.medianBlur(gray,5)

gray = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel1,iterations=4)

gray = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, kernel2,iterations=3)

return gray

def getGD(canny):

"""

return gradient mod and direction

"""

sobelx=cv2.Sobel(canny,cv2.CV_32F,1,0,ksize=3)

sobely=cv2.Sobel(canny,cv2.CV_32F,0,1,ksize=3)

theta = np.arctan(np.abs(sobely/(sobelx+1e-10)))*180/np.pi

Amplitude = np.sqrt(sobelx**2+sobely**2)

mask = (Amplitude>30).astype(np.float32)

Amplitude = Amplitude*mask

return Amplitude, theta

def getlocation(indices, labels, Ni, Nj):

"""

return if there is a zebra cossing

if true, Combine all the rectangular boxes as its position

assume a picture has only one zebra crossing

"""

zc = indices[labels == 1]

if len(zc) == 0:

return 0, None

else:

xmin = int(min(zc[:,1]))

ymin = int(min(zc[:,0]))

xmax = int(xmin + Nj)

ymax = int(max(zc[:,0]) + Ni)

return 1, ((xmin, ymin), (xmax, ymax))

if __name__ == "__main__":

DEBUG = False #if False, won't draw all step

srcs = sorted(os.listdir('images'))

Ni, Nj = (100, 302)

for ii, src in enumerate(srcs):

print("frame: ", ii)

# Load frame

img = cv2.imread('images/'+src)

img = cv2.resize(img, (400,400))

gray = preprocessing(img)

if DEBUG:

cv2.imshow("gray", gray)

canny = cv2.Canny(gray,30,90,apertureSize = 3)

if DEBUG:

cv2.imshow("canny",canny)

Amplitude, theta = getGD(canny)

if DEBUG:

cv2.imshow("Amplitude", Amplitude)

indices, patches = zip(*sliding_window(Amplitude, theta, patch_size=(Ni, Nj))) #use sliding_window get indices and patches

labels = predict(patches, DEBUG) #predict zebra crossing for every patches 1 is zc 0 is background

indices = np.array(indices)

ret, location = getlocation(indices, labels, Ni, Nj)

#draw

if DEBUG:

for i, j in indices[labels == 1]:

cv2.rectangle(img, (j, i), (j+Nj, i+Ni), (0, 0, 255), 3)

if ret:

cv2.rectangle(img, location[0], location[1], (255, 0, 255), 3)

cv2.imshow("img", img)

cv2.waitKey(0)

优点

若无缺损可以把阈值调很高,此时直行斑马线判断非常准且不会有误检。在有缺损时适当调节阈值也能有较好效果。

后续改进方向

利用等间隔特征增强精确度同时消除路边干扰, 适当降低转弯时的阈值, 利用边缘共线特征处理掉孤立点或不成线点(路面破损箭头)

之前试过深度学习的目标检测或滑窗加分类, 效果在当前数据集不错, 但由于可获取的数据太少后续不易调参遂放弃, 后续将继续采用传统图像处理改进识别效果

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cv2 python 获取斑马线_opencv 斑马线,条纹检测 的相关文章

  • vue项目开发 实现自定义Transfer穿梭框效果(结合el-tree)

    vue项目开发 实现自定义Transfer穿梭框效果 结合el tree 效果图 实现代码 效果图 实现代码 直接上代码 An highlighted block
  • event.preventDefault();

    event preventDefault 阻止默认行为 例如 为复选框注册click事件 事件中执行e preventDefault 后 复选框将不会被选中
  • 小白快速搭建网站

    小白快速搭建网站包含宝塔 1 购买域名 登录阿里云 gt 域名 gt 域名注册 2 购买服务器复制公网ip 3 域名解析 开放端口号 宝塔所需端口号 20 21 39000 40000端口 linux 系统 3000 4000 window
  • SSH安全防护

    SSH 用于安全访问远程服务器的协议 一 密码登录工作原理 服务器启动时 自己产生了一个密钥 768bits公钥 本地ssh客户端发送连接请求到ssh服务器 服务器检查连接点客户端发送的数据和ip地址 确认合法后发送密钥 768bits 给
  • opengl 先旋转后平移和先平移后旋转解惑

    我们知道 在opengl中 如果模型中点不在原点 先平移后旋转会导致模型的位移发生变化 但在项目中遇到这么一个问题 如果不知道模型中点 或者知道模型中点一定不在原点 但我们也只需要模型方向 那么我们直接将模型旋转会得到我们想要的方向吗 即如
  • bugku--never_give_up

    考察知识点 1 对编码的敏感度 2 php伪协议 以及POST流 3 通配符 4 弱比较 初步工作 进入页面 是这个样子 查看源代码 发现有提示 那我们访问 ip 1p html 我这里就是http 114 67 175 224 10713
  • r语言 整理、处理数据步骤_R语言万能数据清洗整理包Tidyverse(一)

    数据整理和清洗是任何统计分析的前提 也是最为困难的一个环节 很多软件也提供了数据整理和清洗的功能 甚至连我们常用的EXCEL也可以做这个工作 但是效率很低 而且容易出错 且无法完整保存清洗过程 R语言作为一种开源语言 在这个方面还是很有优势
  • 黑盒测试的测试方法及其案例

    黑盒测试案例设计技术 测试用例 测试用例对测试的作用 黑盒测试 什么是黑盒测试 测试方法 等价类划分法 概念 划分等价类的原则 例题 等价类扩展 边界值分析法 概念 选择测试用例的原则 例题 错误推测法 概念 因果图法 因果图法是什么 利用
  • 2022年高教社杯全国大学生数学建模竞赛解题思路

    2022年高教社杯全国大学生数学建模竞赛试题和最新解题思路 文末可领取各题最新的解题思路和方法 1 试题 A 题 波浪能最大输出功率设计 随着经济和社会的发展 人类面临能源需求和环境污染的双重挑战 发展可再生能源产业已成为世界各国的共识 波
  • java开发常用代码

    基础类型转换 https www cnblogs com expiator p 12602446 html BigDecimal计算 涉及金额之类的运算 不要用 Double Float 这些类型 用 BigDecimal 才能精确计算 详
  • Tensorflow: Model parallelism 模型并行计算

    在tensorflow官方tutorial上给出了多GPU的用法 但那是基于data parallelism的计算 主要思想是将数据划分成不同部分 用同一个模型进行计算 但是我在写代码中发现 会出现单个模型过大无法再单个GPU上运行 这时候
  • JAVA的三大特征之多态

    多态 什么是多态 多态就是同一个行为的不同表现形式 换句话说就是同一个方法因为对象的不同所产生不同的结果 多态存在的条件 继承 重写 父类引用指向子类对象 例 public static void main String args a是人的
  • iOS面试小贴士

    最全的iOS面试题及答案 iOS面试小贴士 回答好下面的足够了 多线程 特别是NSOperation 和 GCD 的内部原理 运行时机制的原理和运用场景 SDWebImage的原理 实现机制 如何解决TableView卡的问题 block和
  • jQuery的Ajax操作小结——$.ajax和$.getJSON等用法小结

    一 ajax用法与举例 jQuery ajax url settings 返回值 XMLHttpRequest 通过 HTTP 请求加载远程数据 这个是jQuery 的底层 AJAX 实现 简单易用的高层实现见 get post 等 最简单
  • 你们公司的【前端项目】是如何做测试的?字节10年测试经验的我这样做的...

    前端项目也叫web端项目 通俗讲就是网页上的功能 是我们能够在屏幕上看到并产生交互的体验 前端项目如何做测试 要讲清楚这个问题 先需要你对测试流程现有一个全局的了解 先上一张测试流程图 测试流程图 接下来下面我们从需求阶段 开发阶段 测试阶
  • vivo的Android升级包,【原厂固件】vivo y66ia系统升级rom刷机包_卡刷包_PD1621B_A_1.9.6...

    今天小编跟大家分享下vivo Y66iA手机固件rom的刷机教程 此版本固件主要是优化了系统安全性 及系统运行的稳定性以及与一些第三方App的兼容性 版本区分方法如下 请在打开手机设置 关于手机 版本里看看是PD1621B A字样 然后下载
  • (解决方案) node: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28‘ not found (node required by node)

    您可能会遇到安装在 ubuntu 操作系统上的 NodeJS 问题 当您运行 node v或pm2 list 命令时出现错误 node lib x86 64 linux gnu libc so 6 version GLIBC 2 28 no
  • 编写shell脚本实现tomcat定时重启的方法

    我的环境是 centos 7 1 在某个目录新建一个 sh 脚本文件 一般cron安装在var spool cron这里 于是我就将脚本创建在这 vim var spool cron tomcatStart sh 2 在 tomcatSta
  • 数据结构复习总结

    第一章 绪论 这里介绍了数据结构的基本概念和术语 以及算法和算法时间复杂度的分析方法 主要内容如下 1 数据结构是一门研究非数值计算程序设计中操作对象 以及这些对象之间的关系和操作的学科 2 数据结构包括两个方面的内容 数据的逻辑结构和存储

随机推荐

  • 挖矿kdevtmpfsi病毒处理

    通过top命令可以看到kdevtmpfsi导致CPU 700 多 导致该病毒只要是通过redis漏洞进来的 1 该病毒还有守护进程 如果光kill掉该病毒 过段时间又起来的 守护进程 kinsing 2 该病毒还有定时任务 如果光杀死kde
  • android中实现登录功能实现原理,用一个最简单的登录例子来了解Android的MVC和MVP架构的原理和实现...

    在目前的Android开发中 MVP与MVC架构还有MVVM都非常流行 三者在不同的场景下都有各自的优势和劣势 一般而言会根据具体的业务场景来选择不同的模式 所以并不是说开发一个App一定完全遵循那种模式 完全可以根据业务场景不同混合多种模
  • 书写中断服务函数的时候注意的问题:

    书写中断服务函数的时候注意的问题 1 中断服务函数名尽量用复制 不要自己写 因为只要你写错一个字母 这个函数就变成普通函数了 2 如果中断服务函数是公共入口 进入到中断服务函数后先要查询是哪种中断 3 先清中断标志 然后再做中断处理 不要把
  • python项目之弹球小游戏 2

    Hello 大家好 我们又见面了 本来我是想再拖几天再发布的 可我的良心不允许我这么做 毕竟在 python项目之弹球小游戏 1 中我们只是写了窗口的程序 还没有加入我们的主题元素呢 所以今天 我们就来加入 小球 这个关键因素 小球的图片素
  • Android 获取apk中的所有类

    直接把下面代码放到工具类调用即可 import android content Context import android os Build import android util Log import com duole games s
  • vue移动端适配(px转vw)postcss-px-to-viewport配置

    安装postcss px to viewport npm install postcss px to viewport 根目录新建postcss config js文件 postcss config js文件 module exports
  • FPGA自学之路4(按键消抖)

    先看框图 按键消抖意思就是前面和后面会有一系列信号抖动 中间才是我们要的信号 这里预设中间需要的信号 gt 20ms 用计数器计数 key in低电平就开始计数 高电平就清零 等计数器能计数到M 1 20ms 时输出一个高电平 这个按键消抖
  • Windows在线安装Qt5.15.2教程、Qt组件模块选择

    1 Qt5 15 2安装包 https download qt io 从archive qt里选 2 Qt5 15 2在线安装教程 https blog csdn net Qi 1337 article details 121249717
  • 关于:Error:java:java.lang.ExceptionInInitializerError 问题的解决

    本地运行项目的时候报上面错误 原因是jdk版本过高导致 解决方法步骤如下 idea 1 点击 File Project Structrue 2 把这两个圈起来的选项改成如下 3 保存 再次运行问题解决
  • 冒泡排序、插入排序、希尔排序、选择排序、堆排序、快速排序六大排序详解

    1 冒泡排序 思路 左右相邻的两个数互相比较 大的交换到序列后边 每次遍历排出剩余的最大的数 如下图所示 代码如下 void BubbleSort int a int n n为数组元素个数 int i 0 j 0 for i 0 i lt
  • 【已解决】No qualifying bean of type ‘service.Service‘ available

    Exception in thread main org springframework beans factory NoSuchBeanDefinitionException No qualifying bean of type serv
  • MySql优化实战案例

    文章目录 建立测试表 联合索引第一个字段用范围不走索引 覆盖索引优化 in和or在表数据量比较大的情况会走索引 在表记录不多的情况下会选择全表扫描 like KK 一般情况都会走索引 Order by 和 group by优化 Order
  • [LeetCode] Valid Anagram - 字符串排序比较系列

    题目概述 Given two strings s and t write a function to determine if t is an anagram of s For example s anagram t nagaram ret
  • Matplotlib:Adding an axes using the same arguments as a previous axes

    学习 机器学习实战 kNN时 在使用Matplotlib画图时 发现了一个Warining MatplotlibDeprecationWarning Adding an axes using the same arguments as a
  • discuz手机端修改url

    discuz的站需要做伪静态 修改url 本来是直接在最外层用ob函数来替换 pc端的可以 但是这个方法用在手机端的时候 发现失效 后来发现是手机端的php文件使用了函数清空了缓存 ob end clean source class hel
  • python随机性实验

    20210408 0 引言 在另外一篇文章中说明了在使用深度学习库的时候 实验结果的可复现的属性 深度学习实验结果可复现所需设置 随机数等内容设置 文中提到 如果是用GPU加速的话 那么很可能导致实验无法复现 那么就只能使用CPU 好在手里
  • LeetCode:第302场周赛【总结】

    这场比赛用C 写了两个题 在赛后用python补题收获很多 学习了一些python的内置函数 方法学习源于其他优秀的博主 6120 数组能形成多少数对 A题 思路 方法一 我自己写的算法 先对nums排序 之后遍历数组找相邻的位置是否相同
  • 【Docker】Docker安装

    1 添加内核参数 1 通过实训平台进入到操作系统界面 在 后输入vi etc sysctl conf命令 然后按Enter键 进入编辑模式 示例代码如下 root xxx vi etc sysctl conf 2 编辑配置文件 etc sy
  • 行为型模式-命令模式

    package per mjn pattern command import java util HashMap import java util Map 订单类 public class Order 餐桌号码 private int di
  • cv2 python 获取斑马线_opencv 斑马线,条纹检测

    斑马线检测 基于OpenCV 效果不是很好 设置DEBUG变量为True时会输出每一步图像用于逐帧debug和调参 按下任意键或者按住不放下一步 设为False则只画最后结果图 红色方框是判断为斑马线的滑窗 紫色方框是最终输出的斑马线位置