收藏关注不迷路!!

🌟文末获取源码+数据库🌟

感兴趣的可以先收藏起来,还有大家在毕设选题(免费咨询指导选题),项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人


前言

近年来,智能驾驶技术在国内外学者中成为研究的热门领域。其中,车道线识别技术作为智能驾驶的关键技术之一,需要准确地识别各种条件下的车道线。本文提出了一种基于OpenCV图像处理的车道线识别算法
首先,该算法对输入的图像进行色彩空间转换,这是因为不同的色彩空间对车道线的特征有不同的表现,通过转换可以提高车道线的可见性。常用的色彩空间包括灰度、HSV和RGB等。
接下来,使用大津法(OTSU)和Canny算子对图像进行分割。大津法是一种自适应阈值分割方法,可以根据图像的直方图自动确定最佳阈值,将图像分为背景和前景两部分。Canny算子则用于边缘检测,它通过计算图像中的梯度来找到边缘。
然后,设计掩膜来找出图像中的感兴趣区域。由于车道线通常位于图像的底部,通过设置一个合适的掩膜,可以限定在该区域内进行车道线的检测,减少干扰。
接着,采用渐近概率式Hough变换对直线车道线进行检测。Hough变换是一种常用的直线检测方法,可以将图像中的点映射到参数空间,并通过寻找交叉点来确定直线。渐近概率式Hough变换通过随机选择图像中的点进行检测,可以大幅度减少计算量。
最后,借助OpenCV平台对算法进行实现。OpenCV是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉功能,可以方便地实现车道线识别算法。

详细视频演示

文章底部名片,联系我看更详细的演示视频

一、项目介绍

环境:Python3.7.4、OpenCV3.4.9.31

————————————————

二、功能介绍

1:进行边缘检测,为获取车道边缘作预处理;
2:进行感兴趣区域RO I提取获取确切的车道线边缘;
3:利用概率霍夫变换获取直线,并将斜率正数和复数的线段给分割开来;
4:离群值过滤,剔除斜率相差过大的线段;
5:最小二乘拟合,实现将左边和右边的线段互相拟合成一条直线,形成车道线。

三、核心代码

部分代码:


import sys
import time

import cv2
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

from lanedetection import LaneDetection


class Ui_MainWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)
        self.setupUi(self)

        self.format = 0                        # 0 空格式 1 图片格式 2 视频格式
        self.data = None                       # 数据

        self.lanedetection = LaneDetection()   # 车道线检测类
        
        self.timer1 = VideoTimer()             # 视频显示多线程
        self.timer1._signal.connect(self.show_input_video)

        self.timer2 = VideoTimer()             # 视频显示多线程
        self.timer2._signal.connect(self.show_output_video)

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")

        MainWindow.resize(1000, 600)
        MainWindow.setFixedSize(1000, 600)
        self.centralwidget = QWidget(MainWindow)

        # 图片控件
        self.label_inputs = QLabel(self.centralwidget)
        self.label_inputs.setGeometry(QRect(50, 70, 400, 400))
        self.label_inputs.setFrameShape(QFrame.Box)
        self.label_inputs.setObjectName("label_inputs")

        self.label_inputsName = QLabel(self.centralwidget)
        self.label_inputsName.setGeometry(QRect(175, 25, 150, 50))
        self.label_inputsName.setObjectName("label_inputsname")
        
        self.label_outputs = QLabel(self.centralwidget)
        self.label_outputs.setGeometry(QRect(550, 70, 400, 400))
        self.label_outputs.setFrameShape(QFrame.Box)
        self.label_outputs.setObjectName("label_outputs")

        self.label_outputsName = QLabel(self.centralwidget)
        self.label_outputsName.setGeometry(QRect(685, 25, 150, 50))
        self.label_outputsName.setObjectName("label_outputsname")
        
        # 按钮控件
        # 打开图片或视频
        self.pushButton_open = QPushButton(self.centralwidget)
        self.pushButton_open.setGeometry(QRect(150, 500, 150, 50))
        self.pushButton_open.setObjectName("pushButton_open")
        self.pushButton_open.clicked.connect(self.open)
        self.pushButton_open.setEnabled(True)
        
        # 运行图片或视频
        self.pushButton_run = QPushButton(self.centralwidget)
        self.pushButton_run.setGeometry(QRect(665, 500, 150, 50))
        self.pushButton_run.setObjectName("pushButton_run")
        self.pushButton_run.clicked.connect(self.run)
        self.pushButton_run.setEnabled(False)

        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))

        self.label_inputs.setText(_translate("MainWindow", "原始图片或视频"))
        self.label_inputsName.setText(_translate("MainWindow", "原始图片或视频"))
        self.label_outputs.setText(_translate("MainWindow", "处理图片或视频"))
        self.label_outputsName.setText(_translate("MainWindow", "处理图片或视频"))
        
        self.pushButton_open.setText(_translate("MainWindow", "打开图片或视频"))
        self.pushButton_run.setText(_translate("MainWindow", "处理图片或视频"))
        
    def open(self):
        # 打开图片文件
        file_name = QFileDialog.getOpenFileName(self.centralwidget, "选择图片或视频", "./assets", "ALL Files(*.*)")
        if not file_name[0]:
            result=QMessageBox.question(
                QWidget(),
                '问题提示', 
                '路径未选择', 
                QMessageBox.Yes,
                QMessageBox.Yes  # 默认关闭界面选择No
            )
            return
        
        if file_name[0].endswith('.jpg'):
            self.format = 1
            # 读取图片
            self.data = cv2.imread(file_name[0], 1)
            self.show_input_image(self.data)
            self.pushButton_open.setEnabled(False)
            self.pushButton_run.setEnabled(True)
            
        elif file_name[0].endswith('.mp4'):
            self.format = 2
            # 创建一个视频读写类
            self.data = cv2.VideoCapture(file_name[0])
            # self.outputs = cv.VideoCapture(0)
            if not self.data.isOpened():
                result=QMessageBox.question(
                QWidget(),
                '问题提示', 
                '打开mp4文件失败', 
                QMessageBox.Yes,
                QMessageBox.Yes  # 默认关闭界面选择No
            )
                return
            self.pushButton_open.setEnabled(False)
            self.timer1.start()
            self.pushButton_run.setEnabled(True)
            
        else:
            result=QMessageBox.question(
                QWidget(),
                '问题提示', 
                '文件格式不存在,请重新选择', 
                QMessageBox.Yes,
                QMessageBox.Yes  # 默认关闭界面选择No
            )
            return
                
    def run(self):
        if self.data is None:
            result=QMessageBox.question(
                QWidget(),
                '问题提示', 
                '数据未打开', 
                QMessageBox.Yes,
                QMessageBox.Yes  # 默认关闭界面选择No
            )  
            return
        
        if self.format is 1 and self.data is not None:
            res = self.lanedetection(self.data)
            self.show_output_image(res)
            
            self.pushButton_open.setEnabled(True)
            self.pushButton_run.setEnabled(False)
            
        elif self.format is 2 and self.data is not None:
            self.pushButton_run.setEnabled(False)
            self.timer2.start()
            self.pushButton_open.setEnabled(True)
            
    def show_input_video(self):
        if self.format is 2 and self.data.isOpened():
            success, frame = self.data.read()
            if success:
              self.show_input_image(frame)
            else:
                self.timer1.stop()
                # 从视频头开始
                self.data.set(cv2.cv2.CAP_PROP_POS_AVI_RATIO, 0)
                
    def show_output_video(self):
        if self.format is 2 and self.data.isOpened():
            success, frame = self.data.read()
            if success:
                res = self.lanedetection(frame)
                self.show_output_image(res)
            else:
                self.timer2.stop()
                self.data.release()
       
    def show_input_image(self, image):
        # 等比例缩放图片
        img = cv2.resize(image, (self.label_inputs.size().height(), self.label_inputs.size().width()))
        # 图片格式从BGR 转换为RGB
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # 显示图片:先从opencv转换到pyqt5种QImage格式,再通过setPixmap设置图片
        QImg = QImage(
            img.data, 
            img.shape[1], 
            img.shape[0],
            img.shape[1] * 3, 
            QImage.Format_RGB888
        )
        self.label_inputs.setPixmap(QPixmap.fromImage(QImg))

    def show_output_image(self, image):
        # 等比例缩放图片
        img = cv2.resize(image, (self.label_inputs.size().height(), self.label_inputs.size().width()))
        # 图片格式从BGR 转换为RGB
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        # 显示图片:先从opencv转换到pyqt5种QImage格式,再通过setPixmap设置图片
        QImg = QImage(
            img.data, 
            img.shape[1], 
            img.shape[0],
            img.shape[1] * 3, 
            QImage.Format_RGB888
        )
        self.label_outputs.setPixmap(QPixmap.fromImage(QImg))

      
class VideoTimer(QThread):
    # refetence: https://github.com/fengtangzheng/pyqt5-opencv-video
    _signal = pyqtSignal()
    def __init__(self):
        QThread.__init__(self)
        self.stopped = False
        self.fps = 50  # 设置显示快慢
        
        self.mutex = QMutex()
        
    def run(self):
        with QMutexLocker(self.mutex):
            self.stopped = False
        while True:
            if self.stopped:
                return
            self._signal.emit()
            time.sleep(1 / self.fps)
    def stop(self):
        with QMutexLocker(self.mutex):
            self.stopped = True
            
  
if __name__ == "__main__":
    app = QApplication(sys.argv)
    ui = Ui_MainWindow()
    ui.show()
    sys.exit(app.exec_())



四、效果图

请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述
请添加图片描述

五、文章目录

目录

摘要 III
Abstract IV
目录 V
第1章 绪论 1
1.1 研究背景 1
2.1 国内外研究现状 1
1.2.1 国外研究现状 2
1.2.2 国内研究现状 2
3.1 论文主要内容 3
第2章 车道线的预处理 4
2.1 认识车道线 6
2.1.1 车道线的基本分类 6
2.1.2 车道线的标划区分 7
2.1.3 车道线的基本形状 7
2.2 感兴趣区域 8
2.3 平滑滤波 9
2.3.1 均值滤波 10
2.3.2 中值滤波 11
2.3.3 高斯滤波 12
2.3.4 本章总结 13
2.4 二值化 13
2.4.1 二值化的基本概念 13
2.4.2 大津法自适应阈值分割 13
2.5 边缘提取 14
2.5.1 Sobel算子 15
2.5.2 Canny算子 16
2.5.3 Sobel算子和Canny算子的比较 17
第3章 Hough变换直线和椭圆的检测 18
3.1 Hough变换直线检测的基本原理 18
3.2 Hough变换的缺陷和改进 19
第4章 车道线的识别 20
结论 24
参考文献: 25
致谢 28

六 、源码获取

下方名片联系我即可!!


大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻

Logo

音视频技术社区,一个全球开发者共同探讨、分享、学习音视频技术的平台,加入我们,与全球开发者一起创造更加优秀的音视频产品!

更多推荐