├── Image ├── v0.1_QT界面.jpg └── v0.2_QT界面.jpg ├── README.md ├── LaneLine-and-Sign-Detection ├── main.cpp ├── mythread.h ├── lanedetector.h ├── mainwindow.h ├── LaneLine-and-Sign-Detection.pro ├── mythread.cpp ├── mainwindow.ui ├── worker.cpp ├── mainwindow.cpp ├── lanedetector.cpp └── LaneLine-and-Sign-Detection.pro.user ├── CourseDesign ├── main.cpp ├── lanedetector.h ├── CourseDesign.pro ├── lanedetector.cpp └── CourseDesign.pro.user └── LICENSE /Image/v0.1_QT界面.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomLao/LaneLine-and-Sign-Detection/HEAD/Image/v0.1_QT界面.jpg -------------------------------------------------------------------------------- /Image/v0.2_QT界面.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TomLao/LaneLine-and-Sign-Detection/HEAD/Image/v0.2_QT界面.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laneline-and-Sign-Detection 2 | 车道线和路牌的简单识别,使用qt界面 3 | 4 | 5 | **v0.2_QT界面效果图** 6 | ![v0.1_QT界面.jpg](Image/v0.2_QT界面.jpg) 7 | 8 | 9 | **V0.1_QT界面效果图** 10 | ![v0.1_QT界面.jpg](Image/v0.1_QT界面.jpg) 11 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include 3 | 4 | int main(int argc, char *argv[]) 5 | { 6 | QApplication a(argc, argv); 7 | MainWindow w; 8 | w.show(); 9 | 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /CourseDesign/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "lanedetector.h" 5 | #include 6 | using namespace std; 7 | using namespace cv; 8 | 9 | 10 | 11 | int main() { 12 | 13 | LaneDetector lanedetector; // 创建类对象 14 | lanedetector.doDetection("F:\\QT_code\\LiuWenguo_homework\\CourseDesign\\loadVideo1.mp4"); 15 | } 16 | 17 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/mythread.h: -------------------------------------------------------------------------------- 1 | #ifndef MYTHREAD_H 2 | #define MYTHREAD_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace cv; 9 | 10 | namespace Ui { 11 | class MainWindow; 12 | } 13 | 14 | class ThreadFromQThread : public QThread 15 | { 16 | Q_OBJECT 17 | 18 | signals: 19 | void message(const QString& info); 20 | void progress(int present); 21 | 22 | public slots: 23 | void stopImmediately(); 24 | void ThreadFromQThread::setVideoPath(std::string videoPath, Ui::MainWindow* &ui); 25 | 26 | public: 27 | ThreadFromQThread(QObject* par); 28 | ~ThreadFromQThread(); 29 | void setSomething(); 30 | void getSomething(); 31 | void setRunCount(int count); 32 | void run(); 33 | void doSomething(); 34 | 35 | QMutex myPause; 36 | 37 | private: 38 | int m_runCount; 39 | QMutex myLock; 40 | bool myIsCanRun; 41 | std::string videoPath; 42 | Ui::MainWindow* &ui; 43 | }; 44 | 45 | 46 | #endif // MYTHREAD_H 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 HezeLao 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /CourseDesign/lanedetector.h: -------------------------------------------------------------------------------- 1 | #ifndef LANEDETECTOR_H 2 | #define LANEDETECTOR_H 3 | #include "iostream"; 4 | using namespace std; 5 | using namespace cv; 6 | class LaneDetector 7 | { 8 | private: 9 | double img_size; 10 | double img_center; 11 | bool left_flag = false; // 告诉我们是否检测到车道的左边界 12 | bool right_flag = false; // 告诉我们是否检测到车道的右边界 13 | Point right_b; // 车道边界线方程的两个成员: 14 | double right_m; // y = m*x + b 15 | Point left_b; // 16 | double left_m; // 17 | 18 | public: 19 | void doDetection(String videoPath); //开始检测 20 | Mat deNoise(Mat inputImage); // 对输入图像应用高斯模糊 21 | Mat edgeDetector(Mat img_noise); // 过滤图像,只获取边缘 22 | Mat mask(Mat img_edges); // 掩盖边缘图像,只关心ROI 23 | void streetSign(Mat img_original);//路牌检测 24 | vector houghLines(Mat img_mask); // 检测蒙面边缘图像中的霍夫线 25 | vector > lineSeparation(vector lines, Mat img_edges); // Sprt通过直线的斜率检测出左右直线 26 | vector regression(vector > left_right_lines, Mat inputImage); //每条车道只能排一条线 27 | string predictTurn(); //通过计算消失点的位置来确定车道是否在转弯 28 | int plotLane(Mat inputImage, vector lane, string turn); //绘制合成车道并在框架中进行转弯预测。 29 | }; 30 | #endif // LANEDETECTOR_H 31 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/lanedetector.h: -------------------------------------------------------------------------------- 1 | #ifndef LANEDETECTOR_H 2 | #define LANEDETECTOR_H 3 | #include 4 | #include 5 | #include 6 | #include "iostream"; 7 | using namespace std; 8 | using namespace cv; 9 | class LaneDetector 10 | { 11 | private: 12 | double img_size; 13 | double img_center; 14 | bool left_flag = false; // 告诉我们是否检测到车道的左边界 15 | bool right_flag = false; // 告诉我们是否检测到车道的右边界 16 | Point right_b; // 车道边界线方程的两个成员: 17 | double right_m; // y = m*x + b 18 | Point left_b; // 19 | double left_m; // 20 | 21 | public: 22 | void LaneDetector::myDetector(Mat frame); //qt检测算法运行模块 23 | void doDetection(String videoPath); //开始检测 24 | Mat deNoise(Mat inputImage); // 对输入图像应用高斯模糊 25 | Mat edgeDetector(Mat img_noise); // 过滤图像,只获取边缘 26 | Mat mask(Mat img_edges); // 掩盖边缘图像,只关心ROI 27 | bool streetSign(Mat img_original);//路牌检测 28 | vector houghLines(Mat img_mask); // 检测蒙面边缘图像中的霍夫线 29 | vector > lineSeparation(vector lines, Mat img_edges); // Sprt通过直线的斜率检测出左右直线 30 | vector regression(vector > left_right_lines, Mat inputImage); //每条车道只能排一条线 31 | string predictTurn(); //通过计算消失点的位置来确定车道是否在转弯 32 | void plotLane(Mat inputImage, vector lane); //绘制合成车道并在框架中进行转弯预测。 33 | }; 34 | #endif // LANEDETECTOR_H 35 | -------------------------------------------------------------------------------- /CourseDesign/CourseDesign.pro: -------------------------------------------------------------------------------- 1 | 2 | ##D:\\app\\opencv\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt2.xml 3 | 4 | #TEMPLATE = app 5 | #CONFIG += console c++11 6 | #CONFIG -= app_bundle 7 | #CONFIG -= qt 8 | 9 | #SOURCES += \ 10 | main.cpp 11 | QT += core gui 12 | 13 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 14 | 15 | TARGET = CourseDesign 16 | TEMPLATE = app 17 | 18 | # The following define makes your compiler emit warnings if you use 19 | # any feature of Qt which has been marked as deprecated (the exact warnings 20 | # depend on your compiler). Please consult the documentation of the 21 | # deprecated API in order to know how to port your code away from it. 22 | DEFINES += QT_DEPRECATED_WARNINGS 23 | 24 | # You can also make your code fail to compile if you use deprecated APIs. 25 | # In order to do so, uncomment the following line. 26 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 27 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 28 | 29 | SOURCES += \ 30 | main.cpp \ 31 | lanedetector.cpp 32 | 33 | INCLUDEPATH += D:\app\opencv\opencv\build\include \ 34 | D:\app\opencv\opencv\build\include\opencv \ 35 | D:\app\opencv\opencv\build\include\opencv2 36 | 37 | LIBS += D:\app\opencv\opencv\build\x64\vc15\lib\opencv_world341d.lib 38 | 39 | HEADERS += \ 40 | lanedetector.h 41 | 42 | DISTFILES += 43 | 44 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | using namespace cv; 21 | using namespace std; 22 | 23 | namespace Ui { 24 | class MainWindow; 25 | } 26 | 27 | class MainWindow : public QMainWindow 28 | { 29 | Q_OBJECT 30 | 31 | public: 32 | explicit MainWindow(QWidget *parent = nullptr); 33 | ~MainWindow(); 34 | 35 | 36 | protected: 37 | int MyRunner(bool isSign); 38 | Mat start(Mat frame); 39 | 40 | 41 | private slots: 42 | void on_pushButton_open_clicked(); 43 | void on_pushButton_start_line_clicked(); 44 | void on_pushButton_start_sign_clicked(); 45 | void on_pushButton_pause_clicked(); 46 | void on_pushButton_stop_clicked(); 47 | 48 | private: 49 | Ui::MainWindow *ui; 50 | Mat srcFrame; 51 | string videoPath; 52 | bool isOpen; //是否选择并打开页面 53 | bool isStart; //是否开始检测了 54 | bool isPause; //是否暂停检测 55 | bool isStop; //是否结束检测 56 | bool isLaneLine; //是否检测到车道线 57 | bool isSign; //是否检测到标志 58 | QTimer *timer; 59 | QImage qimg, qsign; 60 | 61 | void closeEvent(QCloseEvent *enent); 62 | }; 63 | 64 | 65 | #endif // MAINWINDOW_H 66 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/LaneLine-and-Sign-Detection.pro: -------------------------------------------------------------------------------- 1 | #------------------------------------------------- 2 | # 3 | # Project created by QtCreator 2018-12-24T19:33:27 4 | # 5 | #------------------------------------------------- 6 | 7 | QT += core gui 8 | 9 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 10 | 11 | TARGET = LaneLine-and-Sign-Detection 12 | TEMPLATE = app 13 | 14 | # The following define makes your compiler emit warnings if you use 15 | # any feature of Qt which has been marked as deprecated (the exact warnings 16 | # depend on your compiler). Please consult the documentation of the 17 | # deprecated API in order to know how to port your code away from it. 18 | DEFINES += QT_DEPRECATED_WARNINGS 19 | 20 | # You can also make your code fail to compile if you use deprecated APIs. 21 | # In order to do so, uncomment the following line. 22 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 23 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 24 | 25 | CONFIG += c++11 26 | 27 | SOURCES += \ 28 | main.cpp \ 29 | mainwindow.cpp \ 30 | # worker.cpp 31 | lanedetector.cpp 32 | 33 | HEADERS += \ 34 | mainwindow.h \ 35 | lanedetector.h 36 | 37 | FORMS += \ 38 | mainwindow.ui 39 | 40 | # Default rules for deployment. 41 | qnx: target.path = /tmp/$${TARGET}/bin 42 | else: unix:!android: target.path = /opt/$${TARGET}/bin 43 | !isEmpty(target.path): INSTALLS += target 44 | 45 | INCLUDEPATH += D:\Software\opencv\build\include \ 46 | D:\Software\opencv\build\include\opencv \ 47 | D:\Software\opencv\build\include\opencv2 48 | 49 | LIBS += D:\Software\opencv\build\x64\vc14\lib\opencv_world343d.lib 50 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/mythread.cpp: -------------------------------------------------------------------------------- 1 | #include "mythread.h" 2 | #include 3 | 4 | ThreadFromQThread::ThreadFromQThread(QObject* par) : QThread(par) 5 | ,m_runCount(20) 6 | { 7 | 8 | } 9 | 10 | ThreadFromQThread::~ThreadFromQThread() 11 | { 12 | qDebug() << "ThreadFromQThread::~ThreadFromQThread()"; 13 | } 14 | 15 | 16 | /** 17 | * @brief ThreadFromQThread::stopImmediately 终止线程 18 | * @author HezeLao 19 | * @date 2018-12-28 15:40 20 | */ 21 | void ThreadFromQThread::stopImmediately(){ 22 | QMutexLocker locker(&myLock); 23 | myIsCanRun = false; 24 | } 25 | 26 | void ThreadFromQThread::setSomething() 27 | { 28 | msleep(500); 29 | QString str = QString("%1->%2,thread id:%3").arg(__FUNCTION__).arg(__FILE__).arg((int)QThread::currentThreadId()); 30 | emit message(str); 31 | } 32 | 33 | void ThreadFromQThread::getSomething() 34 | { 35 | msleep(500); 36 | emit message(QString("%1->%2,thread id:%3").arg(__FUNCTION__).arg(__FILE__).arg((int)QThread::currentThreadId())); 37 | } 38 | 39 | void ThreadFromQThread::setRunCount(int count) 40 | { 41 | m_runCount = count; 42 | emit message(QString("%1->%2,thread id:%3").arg(__FUNCTION__).arg(__FILE__).arg((int)QThread::currentThreadId())); 43 | } 44 | 45 | 46 | 47 | void ThreadFromQThread::setVideoPath(std::string videoPath, Ui::MainWindow* &ui){ 48 | this->videoPath = videoPath; 49 | this->ui = ui; 50 | } 51 | void ThreadFromQThread::doSomething() 52 | { 53 | msleep(500); 54 | emit message(QString("%1->%2,thread id:%3").arg(__FUNCTION__).arg(__FILE__).arg((int)QThread::currentThreadId())); 55 | } 56 | 57 | void ThreadFromQThread::run() 58 | { 59 | int count = 0; 60 | myIsCanRun = true; //标记可以运行 61 | // QString str = QString("%1->%2,thread id:%3").arg(__FILE__).arg(__FUNCTION__).arg((int)QThread::currentThreadId()); 62 | // emit message(str); 63 | // while(1) 64 | // { 65 | // sleep(1); 66 | // ++count; 67 | // emit progress(((float)count / m_runCount) * 100); 68 | // emit message(QString("ThreadFromQThread::run times:%1").arg(count)); 69 | // doSomething(); 70 | // if(m_runCount == count) 71 | // { 72 | // break; 73 | // } 74 | // QMutexLocker locker(&myLock); 75 | 76 | //获取帧数,不然会播放速度不对 77 | VideoCapture videoCapture(this->videoPath); 78 | Mat srcFrame; 79 | int length = videoCapture.get(CAP_PROP_FRAME_COUNT)/videoCapture.get(CAP_PROP_FPS); 80 | double FPS = videoCapture.get(CAP_PROP_FPS); 81 | Mat res; 82 | while(1){ 83 | waitKey(1000.0 / FPS); 84 | this->myPause.lock(); 85 | 86 | videoCapture>>srcFrame; 87 | 88 | // if(srcFrame.empty() || isStop == true){ 89 | // ui->label_video->clear(); //视频结束或按下结束按钮,清理播放窗口,退出 90 | // videoCapture.release(); 91 | // break; 92 | // } 93 | 94 | cv::resize(srcFrame, srcFrame, Size(576, 324), 0, 0, INTER_LINEAR); 95 | //TODO:从这里出发执行检测算法 96 | cvtColor(srcFrame, srcFrame, CV_BGR2RGB); 97 | 98 | QImage qimg = QImage((const uchar*)(res.data),srcFrame.cols,srcFrame.rows, QImage::Format_RGB888); //简单地转换一下为Image对象,rgbSwapped是为了显示效果色彩好一些。 99 | // QPixmap fitpixmap = QPixmap::fromImage(qimg).scaled(576, 324, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); // 饱满填充 100 | // ui->label_video->setPixmap(fitpixmap); 101 | ui->label_video->setPixmap(QPixmap::fromImage(qimg)); 102 | ui->label_video->show(); 103 | this->myPause.unlock(); 104 | } 105 | videoCapture.release(); 106 | if(myIsCanRun == false){ //在每次循环判断是否可以运行,如果不想就退出循环 107 | return; 108 | } 109 | // } 110 | } 111 | 112 | 113 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 808 10 | 605 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 190 21 | 30 22 | 576 23 | 324 24 | 25 | 26 | 27 | 点击打开-选择视频 28 | 29 | 30 | 31 | 32 | 33 | 40 34 | 90 35 | 111 36 | 41 37 | 38 | 39 | 40 | 车道线检测 41 | 42 | 43 | 44 | 45 | 46 | 40 47 | 30 48 | 111 49 | 41 50 | 51 | 52 | 53 | 打开 54 | 55 | 56 | 57 | 58 | 59 | 40 60 | 210 61 | 111 62 | 41 63 | 64 | 65 | 66 | 暂停 67 | 68 | 69 | 70 | 71 | 72 | 40 73 | 270 74 | 111 75 | 41 76 | 77 | 78 | 79 | 结束 80 | 81 | 82 | 83 | 84 | 85 | 120 86 | 370 87 | 211 88 | 121 89 | 90 | 91 | 92 | 路牌1 93 | 94 | 95 | 96 | 97 | 98 | 40 99 | 150 100 | 111 101 | 41 102 | 103 | 104 | 105 | 路牌检测 106 | 107 | 108 | 109 | 110 | 111 | 420 112 | 370 113 | 211 114 | 121 115 | 116 | 117 | 118 | 路牌2 119 | 120 | 121 | 122 | 123 | 124 | 125 | 0 126 | 0 127 | 808 128 | 25 129 | 130 | 131 | 132 | 133 | 车道线和路牌识别 134 | 135 | 136 | 137 | 138 | 139 | 140 | TopToolBarArea 141 | 142 | 143 | false 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/worker.cpp: -------------------------------------------------------------------------------- 1 | //#include "mainwindow.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace cv; 9 | using namespace std; 10 | 11 | //转为hls颜色空间 12 | Mat convertHls(Mat image) { 13 | Mat converted; 14 | cvtColor(image, converted, CV_RGB2HLS); 15 | return converted; 16 | } 17 | 18 | //根据hls颜色空间选取白黄车道线 19 | Mat selectWhiteYellow(Mat image) { 20 | Mat converted = convertHls(image); 21 | Mat mask, maskWhite, maskYellow; 22 | //取白色和黄色mask 23 | inRange(converted, Scalar(0, 200, 0), Scalar(255, 255, 255), maskWhite); 24 | inRange(converted, Scalar(10, 0, 100), Scalar(40, 255, 255), maskYellow); 25 | //合并 26 | bitwise_or(maskWhite, maskYellow, mask); 27 | bitwise_and(image, image, mask); 28 | return image; 29 | } 30 | 31 | //灰度化 32 | Mat convertGrayScale(Mat image) { 33 | Mat converted; 34 | cvtColor(image, converted, CV_RGB2GRAY); 35 | return converted; 36 | } 37 | 38 | //高斯模糊 39 | Mat smoothing(Mat image, int kernelSize) { 40 | Mat smoothed; 41 | GaussianBlur(image, smoothed, Size(kernelSize, kernelSize), 0); 42 | return smoothed; 43 | } 44 | 45 | //canny边缘检测 46 | Mat detectEdge(Mat image, int lowThreshold, int highThreshold) { 47 | Mat edge; 48 | Canny(image, edge, lowThreshold, highThreshold); 49 | return edge; 50 | } 51 | 52 | //选取车道线,区域过滤,去除噪声 53 | Mat selectRegion(Mat image) { 54 | float rows = image.rows, cols = image.cols; 55 | Point rootPoints[1][4]; 56 | rootPoints[0][0] = Point(cols * 0.1, rows * 0.95); 57 | rootPoints[0][1] = Point(cols * 0.4, rows * 0.6); 58 | rootPoints[0][2] = Point(cols * 0.6, rows * 0.6); 59 | rootPoints[0][3] = Point(cols * 0.9, rows * 0.95); 60 | const Point *ppt[1] = {rootPoints[0]}; 61 | Mat mask = image.clone(); 62 | int npt[] = {255}; 63 | fillPoly(mask, ppt, npt, 1, Scalar(255, 255, 255)); 64 | return mask; 65 | } 66 | 67 | //Hough线变换 68 | vector houghLine(Mat image) { 69 | vector lines; 70 | HoughLinesP(image, lines, 1, CV_PI / 180, 20, 20, 300); 71 | return lines; 72 | } 73 | 74 | //在原图上画线 75 | Mat drawLines(Mat image, vector lines, Scalar color, int thickness, bool makeCopy) { 76 | Mat copy; 77 | if (makeCopy) { 78 | image.copyTo(copy); 79 | } 80 | for (size_t i = 0; i < lines.size(); i++) { 81 | line(copy, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), color, thickness); 82 | } 83 | return copy; 84 | } 85 | 86 | //主控函数 87 | Mat start(Mat frame) { 88 | int gaussianKernelSize = 15; 89 | int lowThreshold = 50; 90 | int highThreshold = 150; 91 | 92 | // Mat converted = convertHls(frame); 93 | // imshow("converted", converted); 94 | // Mat whiteYellowLines = selectWhiteYellow(converted); 95 | // imshow("whiteYellowLines", whiteYellowLines); 96 | // Mat gray = convertGrayScale(whiteYellowLines); 97 | // imshow("gray", gray); 98 | // Mat smoothed = smoothing(gray, gaussianKernelSize); 99 | // imshow("smoothed", smoothed); 100 | // Mat edge = detectEdge(smoothed, lowThreshold, highThreshold); 101 | // imshow("edge", edge); 102 | // Mat roi = selectRegion(edge); 103 | // imshow("roi", roi); 104 | // vector lines = houghLine(roi); 105 | // Mat lineImage = drawLines(roi, lines, Scalar(255, 0, 0), 3, true); 106 | // imshow("lineImage", lineImage); 107 | // return lineImage; 108 | 109 | Mat res; 110 | cvtColor(frame, res, COLOR_BGR2HLS); 111 | 112 | Mat mask, maskWhite, maskYellow; 113 | 114 | //取白色和黄色mask 115 | inRange(res, Scalar(0, 200, 0), Scalar(255, 255, 255), maskWhite); 116 | inRange(res, Scalar(10, 0, 100), Scalar(40, 255, 255), maskYellow); 117 | //合并 118 | bitwise_or(maskWhite, maskYellow, mask); 119 | bitwise_and(frame, frame, res, mask); 120 | 121 | cvtColor(res, res, CV_RGB2GRAY); 122 | 123 | GaussianBlur(res, res, Size(gaussianKernelSize, gaussianKernelSize), 0); 124 | 125 | Canny(res, res, lowThreshold, highThreshold); 126 | 127 | int rows = frame.rows, cols = frame.cols; 128 | Point rootPoints[1][4]; 129 | cout< lines; 144 | HoughLinesP(res, lines, 1, CV_PI / 180, 20, 20, 300); 145 | Mat copy = frame.clone(); 146 | for( size_t i = 0; i < lines.size(); i++ ) 147 | { 148 | Vec4i l = lines[i]; 149 | line(copy , Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA); 150 | } 151 | 152 | 153 | // imshow("copy", copy); 154 | // waitKey(0); 155 | return copy; 156 | 157 | } 158 | 159 | int main() { 160 | String path = "FinalProject/test_video/solidYellowLeft.mp4"; 161 | VideoCapture videoCapture(path); 162 | double FPS = videoCapture.get(CAP_PROP_FPS); 163 | Mat frame; 164 | while (1) { 165 | videoCapture >> frame; 166 | if (frame.empty()) 167 | break; 168 | Mat res = start(frame); 169 | imshow("detect", res); 170 | if (waitKey(1000.0 / FPS) == 27) 171 | break; 172 | } 173 | // Mat image = imread(path); 174 | // Mat res = start(image); 175 | // imshow("detect", res); 176 | // waitKey(0); 177 | } -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "lanedetector.h" 3 | #include "ui_mainwindow.h" 4 | 5 | MainWindow::MainWindow(QWidget *parent) : 6 | QMainWindow(parent), 7 | ui(new Ui::MainWindow) 8 | { 9 | ui->setupUi(this); 10 | 11 | QString title = QString::fromLocal8Bit("HezeLao-RuiweiXie-车道线识别和路牌识别"); 12 | setWindowTitle(title); 13 | 14 | //初始化 15 | videoPath = ""; 16 | isOpen = false; 17 | isStart = false; 18 | isPause = false; 19 | isStop = false; 20 | isLaneLine = true; 21 | isSign = true; 22 | } 23 | 24 | MainWindow::~MainWindow() 25 | { 26 | delete ui; 27 | } 28 | 29 | 30 | /** 31 | * @brief MainWindow::MyRunner 检测控制函数 32 | * @author HezeLao 33 | * @date 2018-12-28 23:24 34 | */ 35 | int MainWindow::MyRunner(bool isSign){ 36 | isStart = true; 37 | 38 | VideoCapture videoCapture(videoPath); 39 | if(!videoCapture.isOpened()){ 40 | QMessageBox::critical(NULL, "critical", QString::fromLocal8Bit("视频打开失败"), QMessageBox::Yes); 41 | isStart = false; 42 | isOpen = false; 43 | return -1; 44 | } 45 | 46 | //获取帧数,不然会播放速度不对 47 | int length = videoCapture.get(CAP_PROP_FRAME_COUNT)/videoCapture.get(CAP_PROP_FPS); 48 | double FPS = videoCapture.get(CAP_PROP_FPS); 49 | Mat res; 50 | bool haveSign; 51 | int countShow=1; 52 | LaneDetector lanedetector; // 创建类对象 53 | while(1){ 54 | // waitKey(1000.0 / FPS); 55 | waitKey(5); 56 | if(isPause == true) //暂停检测 57 | continue; 58 | 59 | videoCapture>>srcFrame; 60 | 61 | if(srcFrame.empty() || isStop == true){ 62 | ui->label_video->clear(); //视频结束或按下结束按钮,清理播放窗口,退出 63 | ui->label_sign_1->clear(); 64 | ui->label_sign_2->clear(); 65 | videoCapture.release(); 66 | break; 67 | } 68 | 69 | cv::resize(srcFrame, srcFrame, Size(576, 324), 0, 0, INTER_LINEAR); 70 | cvtColor(srcFrame, srcFrame, COLOR_BGR2RGB); 71 | 72 | //TODO:从这里出发执行检测算法,分别调用路牌检测和车道线检测 73 | if(isSign){ 74 | haveSign = lanedetector.streetSign(srcFrame); 75 | qimg = QImage((const uchar*)(srcFrame.data),srcFrame.cols,srcFrame.rows, QImage::Format_RGB888); //简单地转换一下为Image对象,rgbSwapped是为了显示效果色彩好一些。 76 | ui->label_video->setPixmap(QPixmap::fromImage(qimg)); 77 | ui->label_video->show(); 78 | if(haveSign){ 79 | qsign = QImage("cut.jpg"); //读取截取的路牌 80 | if(countShow%50==0){ 81 | ui->label_sign_1->setPixmap(QPixmap::fromImage(qsign)); 82 | ui->label_sign_1->show(); 83 | } 84 | else if(countShow%50==25){ 85 | ui->label_sign_2->setPixmap(QPixmap::fromImage(qsign)); 86 | ui->label_sign_2->show(); 87 | } 88 | countShow++; 89 | } 90 | }else{ 91 | lanedetector.myDetector(srcFrame); 92 | qimg = QImage((const uchar*)(srcFrame.data),srcFrame.cols,srcFrame.rows, QImage::Format_RGB888); //简单地转换一下为Image对象,rgbSwapped是为了显示效果色彩好一些。 93 | ui->label_video->setPixmap(QPixmap::fromImage(qimg)); 94 | ui->label_video->show(); 95 | } 96 | 97 | 98 | } 99 | videoCapture.release(); 100 | return 0; 101 | } 102 | 103 | 104 | /** 105 | * @brief MainWindow::on_pushButton_open_clicked 点击选择文件 106 | * @author HezeLao 107 | * @date 2018-12-28 21:50 108 | */ 109 | void MainWindow::on_pushButton_open_clicked(){ 110 | cout << "debug:开始选择文件事件" << endl; 111 | auto fileName = QFileDialog::getOpenFileName(nullptr, "Open Video!", QDir::currentPath(), "video files(*.avi;*.mp4;*.wmv;*.flv;);;all files(*.*)"); 112 | if(fileName.isEmpty()){ 113 | cout << "debug:打开文件失败" << endl; 114 | } 115 | else{ 116 | videoPath = fileName.toStdString(); 117 | isOpen = true; 118 | cout << "debug:打开文件成功" << endl; 119 | cout << "debug:路径是:" << videoPath << endl; 120 | } 121 | cout << "debug:结束选择文件事件" << endl; 122 | } 123 | 124 | 125 | /** 126 | * @brief MainWindow::on_pushButton_start_line_clicked 点击开始检测车道线 127 | * @author HezeLao 128 | * @date 2018-12-28 21:50 129 | */ 130 | void MainWindow::on_pushButton_start_line_clicked(){ 131 | //正在运行检测中 132 | if(isStart == true && isPause == false){ 133 | cout << "debug:正在检测中" << endl; 134 | return; 135 | } 136 | 137 | //从暂停恢复检测 138 | if(isPause == true){ 139 | isPause = false; 140 | cout << "debug:从暂停恢复检测" << endl; 141 | return; 142 | } 143 | 144 | //初次点击开始,检查是否选择目标视频 145 | if(isOpen == true){ 146 | if(!MyRunner(false)){ 147 | //成功开始检测 148 | cout << "debug:成功开始检测" << endl; 149 | isOpen = false; 150 | isStart = false; 151 | isPause = false; 152 | isStop = false; 153 | } 154 | else{ 155 | //检测失败 156 | cout << "debug:检测失败" << endl; 157 | } 158 | } 159 | else{ 160 | cout << "debug:未选择文件" << endl; 161 | QMessageBox box(QMessageBox::Warning,"warning",QString::fromLocal8Bit("请先选择视频文件")); 162 | box.setStandardButtons (QMessageBox::Ok|QMessageBox::Cancel); 163 | box.setButtonText (QMessageBox::Ok,QString::fromLocal8Bit("打开文件")); 164 | box.setButtonText (QMessageBox::Cancel,QString::fromLocal8Bit("取消")); 165 | auto select = box.exec (); 166 | if(select == QMessageBox::Ok){ 167 | on_pushButton_open_clicked(); 168 | } 169 | return; 170 | } 171 | 172 | cout << "debug:结束检测事件" << endl; 173 | } 174 | 175 | 176 | /** 177 | * @brief MainWindow::on_pushButton_sign_clicked 点击开始检测 178 | * @author HezeLao 179 | * @date 2018-12-28 21:50 180 | */ 181 | void MainWindow::on_pushButton_start_sign_clicked(){ 182 | //正在运行检测中 183 | if(isStart == true && isPause == false){ 184 | cout << "debug:正在检测中" << endl; 185 | return; 186 | } 187 | 188 | //从暂停恢复检测 189 | if(isPause == true){ 190 | isPause = false; 191 | cout << "debug:从暂停恢复检测" << endl; 192 | return; 193 | } 194 | 195 | //初次点击开始,检查是否选择目标视频 196 | if(isOpen == true){ 197 | if(!MyRunner(true)){ 198 | //成功开始检测 199 | cout << "debug:成功开始检测" << endl; 200 | isOpen = false; 201 | isStart = false; 202 | isPause = false; 203 | isStop = false; 204 | } 205 | else{ 206 | //检测失败 207 | cout << "debug:检测失败" << endl; 208 | } 209 | } 210 | else{ 211 | cout << "debug:未选择文件" << endl; 212 | QMessageBox box(QMessageBox::Warning,"warning",QString::fromLocal8Bit("请先选择视频文件")); 213 | box.setStandardButtons (QMessageBox::Ok|QMessageBox::Cancel); 214 | box.setButtonText (QMessageBox::Ok,QString::fromLocal8Bit("打开文件")); 215 | box.setButtonText (QMessageBox::Cancel,QString::fromLocal8Bit("取消")); 216 | auto select = box.exec (); 217 | if(select == QMessageBox::Ok){ 218 | on_pushButton_open_clicked(); 219 | } 220 | return; 221 | } 222 | 223 | cout << "debug:结束检测事件" << endl; 224 | } 225 | 226 | 227 | /** 228 | * @brief MainWindow::on_pushButton_pause_clicked 点击暂停 229 | * @author HezeLao 230 | * @date 2018-12-28 21:50 231 | */ 232 | void MainWindow::on_pushButton_pause_clicked(){ 233 | //在已经开始检测的条件下可以暂停 234 | if(isStart == true){ 235 | isPause = true; 236 | cout << "debug:已暂停" << endl; 237 | return; 238 | } 239 | else{ 240 | //未在运行检测,无法暂停 241 | QMessageBox::warning(NULL, "warning", QString::fromLocal8Bit("未在运行检测"), QMessageBox::Yes); 242 | cout << "debug:未在运行检测,无法暂停" << endl; 243 | } 244 | } 245 | 246 | 247 | /** 248 | * @brief MainWindow::on_pushButton_stop_clicked 点击结束 249 | * @author HezeLao 250 | * @date 2018-12-28 21:50 251 | */ 252 | void MainWindow::on_pushButton_stop_clicked(){ 253 | //未在运行检测,无法结束 254 | if(isStart == false){ 255 | QMessageBox::warning(NULL, "warning", QString::fromLocal8Bit("未在运行检测"), QMessageBox::Yes); 256 | cout << "debug:未在运行检测,无法结束" << endl; 257 | } 258 | else{ 259 | //执行结束事件 260 | isOpen = false; 261 | isStart = false; 262 | isPause = false; 263 | isStop = true; 264 | cout << "debug:执行结束事件" << endl; 265 | } 266 | } 267 | 268 | 269 | /** 270 | * @brief MainWindow::closeEvent 关闭窗口事件 271 | * @param event 事件 272 | * @author HezeLao 273 | * @date 2018-12-28 22:20 274 | */ 275 | void MainWindow::closeEvent(QCloseEvent *event){ 276 | auto isExit = QMessageBox::information(this, "Tips", QString::fromLocal8Bit("确认退出?"), QMessageBox::Yes | QMessageBox::No); 277 | if(isExit == QMessageBox::Yes) 278 | event->accept(); 279 | else 280 | event->ignore(); 281 | } 282 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/lanedetector.cpp: -------------------------------------------------------------------------------- 1 | /****************************************************** 2 | author: XiuRuiwei 3 | co-author: LaoHeze 4 | Date: 2019-1-2 5 | 6 | 所有构成LaneDetector类的一部分的函数。 7 | 类将以RGB图像作为输入并输出相同的RGB图像,但是 8 | 带有检测到的车道图和转弯预测。 9 | ********************************************************/ 10 | #include "lanedetector.h" 11 | using namespace std; 12 | 13 | 14 | /** 15 | * @brief LaneDetector::detector qt检测算法运行模块 16 | * @param frame 结果缩放的原始图像 17 | * @author HezeLao 18 | */ 19 | void LaneDetector::myDetector(Mat frame){ 20 | Mat img_denoise; 21 | Mat img_edges; 22 | Mat img_mask; 23 | Mat img_lines; 24 | vector lines; 25 | vector > left_right_lines; 26 | vector lane; 27 | 28 | img_denoise = deNoise(frame); // 使用高斯滤波器去噪图像 29 | img_edges = edgeDetector(img_denoise); // 检测图像中的边缘 30 | img_mask = mask(img_edges); // 对图像进行掩码,只得到ROI 31 | lines = houghLines(img_mask); //霍夫变换 32 | 33 | if (!lines.empty()) { 34 | left_right_lines = lineSeparation(lines, img_edges);// 把线分成左行和右行 35 | lane = regression(left_right_lines, frame); // 应用回归法,使每条泳道的每一侧只能得到一条直线 36 | plotLane(frame, lane); // 画出车道线 37 | } 38 | } 39 | 40 | 41 | /** 42 | * @brief LaneDetector::streetSign 运用HSV颜色空间进行路牌检测 43 | * @param img_original 44 | * @author XieRuiwei LaoHeze 45 | */ 46 | bool LaneDetector::streetSign(Mat img_original){ 47 | Mat hsv, roi; 48 | cvtColor(img_original, hsv, COLOR_RGB2HSV); //直接转换#HSV颜色空间 49 | 50 | //颜色筛选 51 | Mat mask1; 52 | inRange(hsv, Scalar(155,60,60), Scalar(180,255,255), mask1); //红色 53 | Mat mask2; 54 | inRange(hsv, Scalar(97,80,45), Scalar(124,255,255), mask2); //蓝色 55 | Mat mask = mask1 + mask2; 56 | GaussianBlur(mask, mask,Size(5, 5), 3, 3); //高斯模糊 57 | 58 | Mat binary; 59 | threshold(mask, binary,127, 255, CV_THRESH_BINARY); //二值化 60 | 61 | //定义核,形态学闭运算 62 | Mat closed, kernel = getStructuringElement(MORPH_RECT,Size(21,7)); 63 | morphologyEx(binary,closed, MORPH_CLOSE, kernel); 64 | 65 | Mat img_erode,img_dilate; 66 | erode(closed,img_erode, NULL, Point(-1, -1), 4); //腐蚀 67 | dilate(img_erode,img_dilate, NULL, Point(-1, -1), 4); //膨胀 68 | 69 | vector> contours; 70 | vector hierarchy; //分层 71 | findContours(img_dilate, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); //寻找轮廓 72 | 73 | for (int i = 0; i < contours.size(); i++){ 74 | double area = contourArea(Mat(contours[i]),false); 75 | if(area > 0.055*576*324 || area <0.0012*576*324) 76 | continue; 77 | 78 | //变换为旋转矩阵 79 | RotatedRect rect=minAreaRect(Mat(contours[i])); //最小化矩形区域 80 | //定义一个存储以上四个点的坐标的变量 81 | Point2f fourPoint2f[4]; 82 | //将rectPoint变量中存储的坐标值放到 fourPoint的数组中 83 | rect.points(fourPoint2f); 84 | double x,y,width,height; 85 | x = y = width = height = 0; 86 | x = fourPoint2f[1].x; 87 | y = fourPoint2f[1].y; 88 | width = fabs(fourPoint2f[0].x - fourPoint2f[3].x); 89 | height = fabs(fourPoint2f[0].y - fourPoint2f[1].y); 90 | 91 | if(width/height>1.2 && width/height<10.0){ //根据矩形的长宽比 圈出标志牌 92 | //根据得到的四个点的坐标 绘制矩形 93 | Scalar color = (0, 0, 255); //蓝色线画轮廓 94 | for (int i = 0; i < 3; i++) { 95 | line(img_original, fourPoint2f[i], fourPoint2f[i + 1], color, 3); 96 | } 97 | line(img_original, fourPoint2f[3], fourPoint2f[0], color, 3); 98 | 99 | //显示裁剪后的图片 100 | if(x>50 && y>50 && width >50 && height >30){ 101 | roi.release(); 102 | roi = img_original(Rect(x,y,width,height)).clone(); 103 | //imshow("裁剪后的图片",roi); 104 | cvtColor(roi, roi, COLOR_BGR2RGB); 105 | imwrite("cut.jpg", roi); 106 | return true; 107 | } 108 | } 109 | } 110 | return false; 111 | } 112 | 113 | 114 | /** 115 | *@brief 对输入图像进行高斯滤波去噪 116 | * @param inputImage是一个视频的帧,其中 117 | * @param lane将被检测到 118 | * @return 模糊和去噪图像 119 | */ 120 | Mat LaneDetector::deNoise(Mat inputImage) { 121 | Mat output; 122 | GaussianBlur(inputImage, output, Size(3, 3), 0, 0); 123 | return output; 124 | } 125 | 126 | 127 | /** 128 | * @brief 通过过滤图像检测模糊帧中的所有边缘 129 | * @param img_noise是之前模糊的帧 130 | * @return 只有边缘用白色表示的二进制图像 131 | */ 132 | Mat LaneDetector::edgeDetector(Mat img_noise) { 133 | Mat output; 134 | Mat kernel; 135 | Point anchor; 136 | 137 | cvtColor(img_noise, output, COLOR_RGB2GRAY); //灰度化 138 | threshold(output, output, 140, 255, THRESH_BINARY); //二值化 139 | 140 | //创建内核 kernel[-1 0 1],这个内核是基于,Mathworks的车道偏离警告系统 141 | anchor = Point(-1, -1); 142 | kernel = Mat(1, 3, CV_32F); 143 | kernel.at(0, 0) = -1; 144 | kernel.at(0, 1) = 0; 145 | kernel.at(0, 2) = 1; 146 | 147 | // 对二值图像进行滤波以获得边缘 148 | filter2D(output, output, -1, kernel, anchor, 0, BORDER_DEFAULT); 149 | return output; 150 | } 151 | 152 | 153 | /** 154 | * @brief 蒙版边缘图像,对图像进行掩码,只检测到构成车道一部分的边缘 155 | * @param img_edge是前一个函数的边缘图像 156 | * @return 二进制图像,只有需要的边缘具有代表性d 157 | */ 158 | Mat LaneDetector::mask(Mat img_edges) { 159 | Mat output; 160 | Mat mask = Mat::zeros(img_edges.size(), img_edges.type()); 161 | Point pts[4] = { 162 | //非老师给的视频参数 loadVideo.mp4 163 | Point(80,368), //左下角 164 | Point(120,280), //左上角 165 | Point(600,280), 166 | Point(800,368) //右下角 167 | 168 | //loadVideo1.mp4 2.MP4 169 | //Point(-120,368), //左下角 170 | //Point(50,250), //左上角 171 | //Point(290,250), 172 | //Point(450,368) //右下角 173 | 174 | //loadVideo2.mp4 1.MP4 175 | //Point(-60,368), //左下角 176 | //Point(80,220), //左上角 177 | //Point(450,220), 178 | //Point(600,368) //右下角 179 | 180 | //loadVideo3.mp4 4.mp4 181 | //Point(-90,368), //左下角 182 | //Point(40,235), //左上角 183 | //Point(350,235), 184 | //Point(650,368) //右下角 185 | }; 186 | 187 | fillConvexPoly(mask, pts, 4, Scalar(255, 0, 0)); //掩模填充 188 | bitwise_and(img_edges, mask, output); //取并集 189 | 190 | return output; 191 | } 192 | 193 | 194 | /** 195 | * @brief 获取所有蒙面图像中的线段,这些线段将成为车道边界的一部分 196 | * @param img_mask是前一个函数的屏蔽二进制映像 197 | * @return 包含图像中所有检测到的线的向量 198 | */ 199 | vector LaneDetector::houghLines(Mat img_mask) { 200 | vector line; 201 | HoughLinesP(img_mask, line, 1, CV_PI / 180, 20, 20, 30); // 和是通过反复试验得到的 202 | return line; 203 | } 204 | 205 | 206 | // 对左右行进行排序 207 | /** 208 | * @brief 按坡度对所有检测到的霍夫线进行排序。 209 | * @brief 这些线可以分为左右两种 210 | * @brief 关于他们的坡度符号和大致位置 211 | * @param 线是包含所有检测到的线的向量 212 | * @param img_edge用于确定图像中心 213 | 输出是一个向量(2),它包含所有分类行 214 | */ 215 | vector > LaneDetector::lineSeparation(vector lines, Mat img_edges) { 216 | vector > output(2); 217 | size_t j = 0; 218 | Point ini; 219 | Point fini; 220 | double slope_thresh = 0.3; 221 | vector slopes; 222 | vector selected_lines; 223 | vector right_lines, left_lines; 224 | 225 | // 计算所有被测直线的斜率 226 | for (auto i : lines) { 227 | ini = Point(i[0], i[1]); 228 | fini = Point(i[2], i[3]); 229 | 230 | // 基本代数:斜率 slope = (y1 - y0)/(x1 - x0) 231 | double slope = (static_cast(fini.y) - static_cast(ini.y)) / (static_cast(fini.x) - static_cast(ini.x) + 0.00001); 232 | 233 | //如果坡度太水平,就放弃这条线 234 | //如果没有,保存它们和它们各自的斜率 235 | if (abs(slope) > slope_thresh) { 236 | slopes.push_back(slope); 237 | selected_lines.push_back(i); 238 | } 239 | } 240 | 241 | // 把线分成左右两行 242 | img_center = static_cast((img_edges.cols / 2)); 243 | while (j < selected_lines.size()) { 244 | ini = Point(selected_lines[j][0], selected_lines[j][1]); 245 | fini = Point(selected_lines[j][2], selected_lines[j][3]); 246 | 247 | // 将线分为左边或右边的条件 248 | if (slopes[j] > 0 && fini.x > img_center && ini.x > img_center) { 249 | right_lines.push_back(selected_lines[j]); 250 | right_flag = true; 251 | } 252 | else if (slopes[j] < 0 && fini.x < img_center && ini.x < img_center) { 253 | left_lines.push_back(selected_lines[j]); 254 | left_flag = true; 255 | } 256 | j++; 257 | } 258 | 259 | output[0] = right_lines; 260 | output[1] = left_lines; 261 | 262 | return output; 263 | } 264 | 265 | // 左右线的回归420/5000 266 | /** 267 | * @brief 回归采用所有分类线段的起始点和结束点,用最小二乘法拟合出一条新的线段。 268 | * @brief 左右两边都做了。 269 | * @param left_right_lines是lineSeparation函数的输出 270 | * @param inputImage用于选择行结束的位置 271 | * @return 输出包含两个车道边界线的起始点和终点 272 | */ 273 | vector LaneDetector::regression(vector > left_right_lines, Mat inputImage) { 274 | vector output(4); 275 | Point ini; 276 | Point fini; 277 | Point ini2; 278 | Point fini2; 279 | Vec4d right_line; 280 | Vec4d left_line; 281 | vector right_pts; 282 | vector left_pts; 283 | 284 | // 如果检测到右行,请使用该行的所有初始化和最终点匹配该行 285 | if (right_flag == true) { 286 | for (auto i : left_right_lines[0]) { 287 | ini = Point(i[0], i[1]); 288 | fini = Point(i[2], i[3]); 289 | 290 | right_pts.push_back(ini); 291 | right_pts.push_back(fini); 292 | } 293 | 294 | if (right_pts.size() > 0) { 295 | // 这里形成了一条直线 296 | fitLine(right_pts, right_line, CV_DIST_L2, 0, 0.01, 0.01); 297 | right_m = right_line[1] / right_line[0]; 298 | right_b = Point(right_line[2], right_line[3]); 299 | } 300 | } 301 | 302 | // 如果检测到左行,使用该行的所有init和final点拟合一行 303 | if (left_flag == true) { 304 | for (auto j : left_right_lines[1]) { 305 | ini2 = Point(j[0], j[1]); 306 | fini2 = Point(j[2], j[3]); 307 | 308 | left_pts.push_back(ini2); 309 | left_pts.push_back(fini2); 310 | } 311 | if (left_pts.size() > 0) { 312 | // 左线在这里形成 313 | fitLine(left_pts, left_line, CV_DIST_L2, 0, 0.01, 0.01); 314 | left_m = left_line[1] / left_line[0]; 315 | left_b = Point(left_line[2], left_line[3]); 316 | } 317 | } 318 | 319 | // 首先求出了直线的斜率和偏置点,应用直线方程求出了直线点 320 | int ini_y = inputImage.rows; 321 | int fin_y = 250; 322 | 323 | double right_ini_x = ((ini_y - right_b.y) / right_m) + right_b.x; 324 | double right_fin_x = ((fin_y - right_b.y) / right_m) + right_b.x; 325 | 326 | double left_ini_x = ((ini_y - left_b.y) / left_m) + left_b.x; 327 | double left_fin_x = ((fin_y - left_b.y) / left_m) + left_b.x; 328 | 329 | output[0] = Point(right_ini_x, ini_y); 330 | output[1] = Point(right_fin_x, fin_y); 331 | output[2] = Point(left_ini_x, ini_y); 332 | output[3] = Point(left_fin_x, fin_y); 333 | 334 | return output; 335 | } 336 | 337 | 338 | //绘制结果 339 | /** 340 | * @brief该函数绘制车道两侧、转弯预测信息和覆盖车道边界内区域的透明多边形 341 | * @param inputImage是原始捕获帧 342 | * @param lane是包含两条直线信息的向量 343 | * @param turn是包含转弯信息的输出字符串 344 | */ 345 | void LaneDetector::plotLane(Mat inputImage, vector lane) { 346 | vector poly_points; 347 | Mat output; 348 | 349 | // 创建透明多边形,以便更好地显示车道 350 | inputImage.copyTo(output); 351 | poly_points.push_back(lane[2]); 352 | poly_points.push_back(lane[0]); 353 | poly_points.push_back(lane[1]); 354 | poly_points.push_back(lane[3]); 355 | fillConvexPoly(output, poly_points, Scalar(255, 0, 0), CV_AA, 0); 356 | addWeighted(output, 0.3, inputImage, 1.0 - 0.3, 0, inputImage); 357 | } 358 | -------------------------------------------------------------------------------- /CourseDesign/lanedetector.cpp: -------------------------------------------------------------------------------- 1 | /*** 2 | 所有构成LaneDetector类的一部分的函数。 3 | 类将以RGB图像作为输入并输出相同的RGB图像,但是 4 | 带有检测到的车道图和转弯预测。 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include "lanedetector.h" 10 | #include "iostream" 11 | using namespace std; 12 | 13 | //运行检测代码块 14 | void LaneDetector::doDetection(String videoPath){ 15 | // The input argument is the location of the video 16 | cv::VideoCapture cap(videoPath); 17 | if (!cap.isOpened()) 18 | return ; 19 | 20 | 21 | Mat frame; 22 | Mat img_denoise; 23 | Mat img_edges; 24 | Mat img_mask; 25 | Mat img_lines; 26 | vector lines; 27 | vector > left_right_lines; 28 | vector lane; 29 | string turn; 30 | int flag_plot = -1; 31 | 32 | // 主要算法开始。遍历视频的每一帧 33 | while (true) { 34 | // Capture frame 35 | if (!cap.read(frame)) 36 | break; 37 | if(waitKey(1)==27) 38 | break; 39 | 40 | //图像缩小 41 | resize(frame,frame,Size(576,324),0,0,INTER_LINEAR); 42 | 43 | //交通标志检测及显示 44 | streetSign(frame); 45 | 46 | // 使用高斯滤波器去噪图像 47 | img_denoise = deNoise(frame); 48 | imshow("高斯滤波器去噪图像",frame); 49 | 50 | // 检测图像中的边缘 51 | img_edges = edgeDetector(img_denoise); 52 | imshow("检测图像中的边缘",img_edges); 53 | 54 | // 对图像进行掩码,只得到ROI 55 | img_mask = mask(img_edges); 56 | imshow("对图像进行掩码,只得到ROI",img_mask); 57 | 58 | // 获取裁剪图像中的霍夫线 59 | lines = houghLines(img_mask); 60 | // imshow("裁剪图像中的霍夫线",lines); 61 | 62 | if (!lines.empty()) 63 | { 64 | // 把线分成左行和右行 65 | left_right_lines = lineSeparation(lines, img_edges); 66 | 67 | // 应用回归法,使每条泳道的每一侧只能得到一条直线 68 | lane = regression(left_right_lines, frame); 69 | 70 | // 通过确定直线的消失点来预测转弯 71 | turn = predictTurn(); 72 | 73 | // 情节车道检测 74 | flag_plot = plotLane(frame, lane, turn); 75 | } 76 | else { 77 | flag_plot = -1; 78 | } 79 | } 80 | 81 | return ; 82 | } 83 | 84 | 85 | //路牌检测 86 | void LaneDetector::streetSign(Mat img_original){ 87 | Mat hsv; 88 | cvtColor(img_original, hsv, CV_BGR2HSV); //直接转换#HSV颜色空间 89 | // imshow("颜色空间",hsv); 90 | 91 | 92 | //掩码 93 | Mat mask1; 94 | inRange(hsv, Scalar(155,60,60), Scalar(180,255,255), mask1); 95 | Mat mask2; 96 | inRange(hsv, Scalar(97,80,45), Scalar(124,255,255), mask2); 97 | Mat mask = mask1 + mask2; 98 | GaussianBlur(mask, mask,Size(5, 5), 3, 3);//高斯模糊 99 | // imshow("mask",mask); 100 | 101 | //二值化 102 | Mat binary; 103 | threshold(mask, binary,127, 255, CV_THRESH_BINARY);//二值化 104 | // imshow("二值化",binary); 105 | 106 | //定义核 107 | Mat kernel = getStructuringElement(MORPH_RECT,Size(21,7)); 108 | //进行形态学操作 109 | Mat closed; 110 | morphologyEx(binary,closed, MORPH_CLOSE, kernel); 111 | // imshow("进行形态学操作",closed); 112 | 113 | Mat img_erode,img_dilate; 114 | erode(closed,img_erode, NULL, Point(-1, -1), 4);//腐蚀 115 | dilate(img_erode,img_dilate, NULL, Point(-1, -1), 4);//膨胀 116 | // imshow("腐蚀-膨胀",img_dilate); 117 | 118 | 119 | vector> contours; 120 | vector hierarchy; //分层 121 | findContours(img_dilate, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//寻找轮廓 122 | // cout << contours.size() << endl; 123 | 124 | 125 | for (int i = 0; i < contours.size(); i++){ 126 | double area = contourArea(Mat(contours[i]),false); 127 | if(area > 0.055*576*324 || area <0.0012*576*324) 128 | continue; 129 | 130 | //变换为旋转矩阵 131 | RotatedRect rect=minAreaRect(Mat(contours[i])); 132 | //定义一个存储以上四个点的坐标的变量 133 | Point2f fourPoint2f[4]; 134 | //将rectPoint变量中存储的坐标值放到 fourPoint的数组中 135 | rect.points(fourPoint2f); 136 | double x,y,width,height; 137 | x = y = width = height = 0; 138 | x = fourPoint2f[1].x; 139 | y = fourPoint2f[1].y; 140 | width = fabs(fourPoint2f[0].x - fourPoint2f[3].x); 141 | height = fabs(fourPoint2f[0].y - fourPoint2f[1].y); 142 | 143 | 144 | if(width/height>1.2 && width/height<2.5){ //根据矩形的长宽比 圈出标志牌 145 | //根据得到的四个点的坐标 绘制矩形 146 | Scalar color = (0, 0, 255);//蓝色线画轮廓 147 | for (int i = 0; i < 3; i++) { 148 | line(img_original, fourPoint2f[i], fourPoint2f[i + 1], color, 3); 149 | } 150 | line(img_original, fourPoint2f[3], fourPoint2f[0], color, 3); 151 | 152 | //显示裁剪后的图片 153 | if(x>50 && y>50 && width >50 && height >20){ 154 | Mat roi = img_original(Rect(x,y,width,height)); 155 | imshow("裁剪后的图片",roi); 156 | } 157 | } 158 | } 159 | } 160 | 161 | // 图像模糊 162 | /** 163 | *@brief对输入图像进行高斯滤波去噪 164 | *@param inputImage是一个视频的帧,其中 165 | *@param lane将被检测到 166 | *@return模糊和去噪图像 167 | */ 168 | Mat LaneDetector::deNoise(Mat inputImage) { 169 | Mat output; 170 | GaussianBlur(inputImage, output, Size(3, 3), 0, 0); 171 | return output; 172 | } 173 | 174 | // 边缘检测 175 | /** 176 | *@brief通过过滤图像检测模糊帧中的所有边缘 177 | *@param img_noise是之前模糊的帧 178 | *@return只有边缘用白色表示的二进制图像 179 | */ 180 | Mat LaneDetector::edgeDetector(Mat img_noise) { 181 | Mat output; 182 | Mat kernel; 183 | Point anchor; 184 | 185 | // 将图像从RGB转换为灰色 186 | cvtColor(img_noise, output, COLOR_RGB2GRAY); 187 | // Binarize灰度图像 188 | threshold(output, output, 140, 255, THRESH_BINARY); 189 | 190 | //创建内核 kernel[-1 0 1] 191 | //这个内核是基于 192 | // Mathworks的车道偏离警告系统 193 | anchor = Point(-1, -1); 194 | kernel = Mat(1, 3, CV_32F); 195 | kernel.at(0, 0) = -1; 196 | kernel.at(0, 1) = 0; 197 | kernel.at(0, 2) = 1; 198 | 199 | // 对二值图像进行滤波以获得边缘 200 | filter2D(output, output, -1, kernel, anchor, 0, BORDER_DEFAULT); 201 | // imshow("output", output); 202 | return output; 203 | } 204 | 205 | // 蒙版边缘图像 206 | /** 207 | *@brief对图像进行掩码,只检测到构成车道一部分的边缘 208 | *@param img_edge是前一个函数的边缘图像 209 | *@return二进制图像,只有需要的边缘具有代表性d 210 | */ 211 | Mat LaneDetector::mask(Mat img_edges) { 212 | Mat output; 213 | Mat mask = Mat::zeros(img_edges.size(), img_edges.type()); 214 | Point pts[4] = { 215 | // //非刘文果给的视频参数 loadVideo.mp4 216 | // Point(80,368), //左下角 217 | // Point(120,280), //左上角 218 | // Point(600,280), 219 | // Point(800,368) //右下角 220 | 221 | //刘文果给的视频参数 loadVideo1.mp4 222 | Point(-120,368), //左下角 223 | Point(50,250), //左上角 224 | Point(290,250), 225 | Point(450,368) //右下角 226 | 227 | // //刘文果给的视频参数 loadVideo2.mp4 228 | // Point(-60,368), //左下角 229 | // Point(80,220), //左上角 230 | // Point(450,220), 231 | // Point(600,368) //右下角 232 | 233 | // //刘文果给的视频参数 loadVideo3.mp4 234 | // Point(-90,368), //左下角 235 | // Point(40,235), //左上角 236 | // Point(350,235), 237 | // Point(650,368) //右下角 238 | }; 239 | 240 | // 创建一个二元多边形掩模 241 | fillConvexPoly(mask, pts, 4, Scalar(255, 0, 0)); 242 | // 将边缘图像和蒙版相乘得到输出 243 | bitwise_and(img_edges, mask, output); 244 | 245 | imshow("mask",mask); 246 | return output; 247 | } 248 | 249 | // HOUGH LINES 250 | /** 251 | *@brief获取所有蒙面图像中的线段,这些线段将成为车道边界的一部分 252 | *@param img_mask是前一个函数的屏蔽二进制映像 253 | *@return包含图像中所有检测到的线的向量 254 | */ 255 | vector LaneDetector::houghLines(Mat img_mask) { 256 | vector line; 257 | // 和是通过反复试验得到的 258 | HoughLinesP(img_mask, line, 1, CV_PI / 180, 20, 20, 30); 259 | return line; 260 | } 261 | 262 | // 对左右行进行排序 263 | /** 264 | *@brief按坡度对所有检测到的霍夫线进行排序。 265 | *@brief这些线可以分为左右两种 266 | *@brief关于他们的坡度符号和大致位置 267 | *@param线是包含所有检测到的线的向量 268 | *@param img_edge用于确定图像中心 269 | 输出是一个向量(2),它包含所有分类行 270 | */ 271 | vector > LaneDetector::lineSeparation(vector lines, Mat img_edges) { 272 | vector > output(2); 273 | size_t j = 0; 274 | Point ini; 275 | Point fini; 276 | double slope_thresh = 0.3; 277 | vector slopes; 278 | vector selected_lines; 279 | vector right_lines, left_lines; 280 | 281 | // 计算所有被测直线的斜率 282 | for (auto i : lines) { 283 | ini = Point(i[0], i[1]); 284 | fini = Point(i[2], i[3]); 285 | 286 | // 基本代数:斜率 slope = (y1 - y0)/(x1 - x0) 287 | double slope = (static_cast(fini.y) - static_cast(ini.y)) / (static_cast(fini.x) - static_cast(ini.x) + 0.00001); 288 | 289 | //如果坡度太水平,就放弃这条线 290 | //如果没有,保存它们和它们各自的斜率 291 | if (abs(slope) > slope_thresh) { 292 | slopes.push_back(slope); 293 | selected_lines.push_back(i); 294 | } 295 | } 296 | 297 | // 把线分成左右两行 298 | img_center = static_cast((img_edges.cols / 2)); 299 | while (j < selected_lines.size()) { 300 | ini = Point(selected_lines[j][0], selected_lines[j][1]); 301 | fini = Point(selected_lines[j][2], selected_lines[j][3]); 302 | 303 | // 将线分为左边或右边的条件 304 | if (slopes[j] > 0 && fini.x > img_center && ini.x > img_center) { 305 | right_lines.push_back(selected_lines[j]); 306 | right_flag = true; 307 | } 308 | else if (slopes[j] < 0 && fini.x < img_center && ini.x < img_center) { 309 | left_lines.push_back(selected_lines[j]); 310 | left_flag = true; 311 | } 312 | j++; 313 | } 314 | 315 | output[0] = right_lines; 316 | output[1] = left_lines; 317 | 318 | return output; 319 | } 320 | 321 | // 左右线的回归 322 | /** 323 | 324 | 420/5000 325 | *@brief回归采用所有分类线段的起始点和结束点,用最小二乘法拟合出一条新的线段。 326 | *@brief左右两边都做了。 327 | *@param left_right_lines是lineSeparation函数的输出 328 | *@param inputImage用于选择行结束的位置 329 | *@return输出包含两个车道边界线的起始点和终点 330 | */ 331 | vector LaneDetector::regression(vector > left_right_lines, Mat inputImage) { 332 | vector output(4); 333 | Point ini; 334 | Point fini; 335 | Point ini2; 336 | Point fini2; 337 | Vec4d right_line; 338 | Vec4d left_line; 339 | vector right_pts; 340 | vector left_pts; 341 | 342 | // 如果检测到右行,请使用该行的所有初始化和最终点匹配该行 343 | if (right_flag == true) { 344 | for (auto i : left_right_lines[0]) { 345 | ini = Point(i[0], i[1]); 346 | fini = Point(i[2], i[3]); 347 | 348 | right_pts.push_back(ini); 349 | right_pts.push_back(fini); 350 | } 351 | 352 | if (right_pts.size() > 0) { 353 | // 这里形成了一条直线 354 | fitLine(right_pts, right_line, CV_DIST_L2, 0, 0.01, 0.01); 355 | right_m = right_line[1] / right_line[0]; 356 | right_b = Point(right_line[2], right_line[3]); 357 | } 358 | } 359 | 360 | // 如果检测到左行,使用该行的所有init和final点拟合一行 361 | if (left_flag == true) { 362 | for (auto j : left_right_lines[1]) { 363 | ini2 = Point(j[0], j[1]); 364 | fini2 = Point(j[2], j[3]); 365 | 366 | left_pts.push_back(ini2); 367 | left_pts.push_back(fini2); 368 | } 369 | if (left_pts.size() > 0) { 370 | // 左线在这里形成 371 | fitLine(left_pts, left_line, CV_DIST_L2, 0, 0.01, 0.01); 372 | left_m = left_line[1] / left_line[0]; 373 | left_b = Point(left_line[2], left_line[3]); 374 | } 375 | } 376 | 377 | // 首先求出了直线的斜率和偏置点,应用直线方程求出了直线点 378 | int ini_y = inputImage.rows; 379 | int fin_y = 250; 380 | 381 | double right_ini_x = ((ini_y - right_b.y) / right_m) + right_b.x; 382 | double right_fin_x = ((fin_y - right_b.y) / right_m) + right_b.x; 383 | 384 | double left_ini_x = ((ini_y - left_b.y) / left_m) + left_b.x; 385 | double left_fin_x = ((fin_y - left_b.y) / left_m) + left_b.x; 386 | 387 | output[0] = Point(right_ini_x, ini_y); 388 | output[1] = Point(right_fin_x, fin_y); 389 | output[2] = Point(left_ini_x, ini_y); 390 | output[3] = Point(left_fin_x, fin_y); 391 | 392 | return output; 393 | } 394 | 395 | // 预测 396 | /** 397 | *@brief预测车道是左转、右转还是直走 398 | *@brief通过查看消失点相对于图像中心的位置来完成 399 | *@return字符串,表示是否有左或右转弯或道路是否笔直 400 | */ 401 | string LaneDetector::predictTurn() { 402 | string output; 403 | double vanish_x; 404 | double thr_vp = 10; 405 | 406 | // 消失点是两个车道边界线相交的点 407 | vanish_x = static_cast(((right_m*right_b.x) - (left_m*left_b.x) - right_b.y + left_b.y) / (right_m - left_m)); 408 | 409 | // 消失点的位置决定了道路转弯的位置 410 | if (vanish_x < (img_center - thr_vp)) 411 | output = "Left Turn"; 412 | else if (vanish_x >(img_center + thr_vp)) 413 | output = "Right Turn"; 414 | else if (vanish_x >= (img_center - thr_vp) && vanish_x <= (img_center + thr_vp)) 415 | output = "Straight"; 416 | 417 | return output; 418 | } 419 | 420 | //绘制结果 421 | /** 422 | *@brief该函数绘制车道两侧、转弯预测信息和覆盖车道边界内区域的透明多边形 423 | *@param inputImage是原始捕获帧 424 | *@param lane是包含两条直线信息的向量 425 | *@param turn是包含转弯信息的输出字符串 426 | *@return函数返回0 427 | */ 428 | int LaneDetector::plotLane(Mat inputImage, vector lane, string turn) { 429 | vector poly_points; 430 | Mat output; 431 | 432 | // 创建透明多边形,以便更好地显示车道 433 | inputImage.copyTo(output); 434 | poly_points.push_back(lane[2]); 435 | poly_points.push_back(lane[0]); 436 | poly_points.push_back(lane[1]); 437 | poly_points.push_back(lane[3]); 438 | fillConvexPoly(output, poly_points, Scalar(255, 0, 0), CV_AA, 0); 439 | addWeighted(output, 0.3, inputImage, 1.0 - 0.3, 0, inputImage); 440 | 441 | // 绘制车道边界的两条线 442 | /* line(inputImage, lane[0], lane[1], Scalar(0, 0, 255), 5, CV_AA); 443 | line(inputImage, lane[2], lane[3], Scalar(0, 0, 255), 5, CV_AA);*/ 444 | 445 | // 绘制转弯信息 446 | // putText(inputImage, turn, Point(50, 90), FONT_HERSHEY_COMPLEX_SMALL, 3, cvScalar(0, 255, 0), 1, CV_AA); 447 | 448 | // 显示最终输出图像 449 | namedWindow("Lane", CV_WINDOW_AUTOSIZE); 450 | imshow("Lane", inputImage); 451 | return 0; 452 | } 453 | -------------------------------------------------------------------------------- /LaneLine-and-Sign-Detection/LaneLine-and-Sign-Detection.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {a83f0298-4107-422b-9c94-8efa73b95d34} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 0 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | -fno-delayed-template-parsing 60 | 61 | true 62 | 63 | 64 | 65 | ProjectExplorer.Project.Target.0 66 | 67 | Desktop Qt 5.11.2 MSVC2015 64bit 68 | Desktop Qt 5.11.2 MSVC2015 64bit 69 | qt.qt5.5112.win64_msvc2015_64_kit 70 | 0 71 | 0 72 | 0 73 | 74 | D:/MyProject/LaneLine-and-Sign-Detection/build-LaneLine-and-Sign-Detection-Desktop_Qt_5_11_2_MSVC2015_64bit-Debug 75 | 76 | 77 | true 78 | qmake 79 | 80 | QtProjectManager.QMakeBuildStep 81 | true 82 | 83 | false 84 | false 85 | false 86 | 87 | 88 | true 89 | Make 90 | 91 | Qt4ProjectManager.MakeStep 92 | 93 | false 94 | 95 | 96 | 97 | 2 98 | Build 99 | 100 | ProjectExplorer.BuildSteps.Build 101 | 102 | 103 | 104 | true 105 | Make 106 | 107 | Qt4ProjectManager.MakeStep 108 | 109 | true 110 | clean 111 | 112 | 113 | 1 114 | Clean 115 | 116 | ProjectExplorer.BuildSteps.Clean 117 | 118 | 2 119 | false 120 | 121 | Debug 122 | Debug 123 | Qt4ProjectManager.Qt4BuildConfiguration 124 | 2 125 | true 126 | 127 | 128 | D:/MyProject/LaneLine-and-Sign-Detection/build-LaneLine-and-Sign-Detection-Desktop_Qt_5_11_2_MSVC2015_64bit-Release 129 | 130 | 131 | true 132 | qmake 133 | 134 | QtProjectManager.QMakeBuildStep 135 | false 136 | 137 | false 138 | false 139 | true 140 | 141 | 142 | true 143 | Make 144 | 145 | Qt4ProjectManager.MakeStep 146 | 147 | false 148 | 149 | 150 | 151 | 2 152 | Build 153 | 154 | ProjectExplorer.BuildSteps.Build 155 | 156 | 157 | 158 | true 159 | Make 160 | 161 | Qt4ProjectManager.MakeStep 162 | 163 | true 164 | clean 165 | 166 | 167 | 1 168 | Clean 169 | 170 | ProjectExplorer.BuildSteps.Clean 171 | 172 | 2 173 | false 174 | 175 | Release 176 | Release 177 | Qt4ProjectManager.Qt4BuildConfiguration 178 | 0 179 | true 180 | 181 | 182 | D:/MyProject/LaneLine-and-Sign-Detection/build-LaneLine-and-Sign-Detection-Desktop_Qt_5_11_2_MSVC2015_64bit-Profile 183 | 184 | 185 | true 186 | qmake 187 | 188 | QtProjectManager.QMakeBuildStep 189 | true 190 | 191 | false 192 | true 193 | true 194 | 195 | 196 | true 197 | Make 198 | 199 | Qt4ProjectManager.MakeStep 200 | 201 | false 202 | 203 | 204 | 205 | 2 206 | Build 207 | 208 | ProjectExplorer.BuildSteps.Build 209 | 210 | 211 | 212 | true 213 | Make 214 | 215 | Qt4ProjectManager.MakeStep 216 | 217 | true 218 | clean 219 | 220 | 221 | 1 222 | Clean 223 | 224 | ProjectExplorer.BuildSteps.Clean 225 | 226 | 2 227 | false 228 | 229 | Profile 230 | Profile 231 | Qt4ProjectManager.Qt4BuildConfiguration 232 | 0 233 | true 234 | 235 | 3 236 | 237 | 238 | 0 239 | 部署 240 | 241 | ProjectExplorer.BuildSteps.Deploy 242 | 243 | 1 244 | Deploy Configuration 245 | 246 | ProjectExplorer.DefaultDeployConfiguration 247 | 248 | 1 249 | 250 | 251 | false 252 | false 253 | 1000 254 | 255 | true 256 | 257 | false 258 | false 259 | false 260 | false 261 | true 262 | 0.01 263 | 10 264 | true 265 | 1 266 | 25 267 | 268 | 1 269 | true 270 | false 271 | true 272 | valgrind 273 | 274 | 0 275 | 1 276 | 2 277 | 3 278 | 4 279 | 5 280 | 6 281 | 7 282 | 8 283 | 9 284 | 10 285 | 11 286 | 12 287 | 13 288 | 14 289 | 290 | 2 291 | 292 | LaneLine-and-Sign-Detection 293 | 294 | Qt4ProjectManager.Qt4RunConfiguration:D:/MyProject/LaneLine-and-Sign-Detection/LaneLine-and-Sign-Detection/LaneLine-and-Sign-Detection.pro 295 | true 296 | 297 | LaneLine-and-Sign-Detection.pro 298 | 299 | D:/MyProject/LaneLine-and-Sign-Detection/build-LaneLine-and-Sign-Detection-Desktop_Qt_5_11_2_MSVC2015_64bit-Debug 300 | 3768 301 | false 302 | true 303 | false 304 | false 305 | true 306 | 307 | 1 308 | 309 | 310 | 311 | ProjectExplorer.Project.TargetCount 312 | 1 313 | 314 | 315 | ProjectExplorer.Project.Updater.FileVersion 316 | 18 317 | 318 | 319 | Version 320 | 18 321 | 322 | 323 | -------------------------------------------------------------------------------- /CourseDesign/CourseDesign.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {42412c90-f425-49d0-b9f0-41bce2e2b7b0} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 0 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | 60 | ProjectExplorer.Project.Target.0 61 | 62 | Desktop Qt 5.10.1 MSVC2017 64bit 63 | Desktop Qt 5.10.1 MSVC2017 64bit 64 | qt.qt5.5101.win64_msvc2017_64_kit 65 | 0 66 | 0 67 | 0 68 | 69 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug 70 | 71 | 72 | true 73 | qmake 74 | 75 | QtProjectManager.QMakeBuildStep 76 | true 77 | 78 | false 79 | false 80 | false 81 | 82 | 83 | true 84 | Make 85 | 86 | Qt4ProjectManager.MakeStep 87 | 88 | false 89 | 90 | 91 | 92 | 2 93 | 构建 94 | 95 | ProjectExplorer.BuildSteps.Build 96 | 97 | 98 | 99 | true 100 | Make 101 | 102 | Qt4ProjectManager.MakeStep 103 | 104 | true 105 | clean 106 | 107 | 108 | 1 109 | 清理 110 | 111 | ProjectExplorer.BuildSteps.Clean 112 | 113 | 2 114 | false 115 | 116 | Debug 117 | 118 | Qt4ProjectManager.Qt4BuildConfiguration 119 | 2 120 | true 121 | 122 | 123 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Desktop_Qt_5_10_1_MSVC2017_64bit-Release 124 | 125 | 126 | true 127 | qmake 128 | 129 | QtProjectManager.QMakeBuildStep 130 | false 131 | 132 | false 133 | false 134 | false 135 | 136 | 137 | true 138 | Make 139 | 140 | Qt4ProjectManager.MakeStep 141 | 142 | false 143 | 144 | 145 | 146 | 2 147 | 构建 148 | 149 | ProjectExplorer.BuildSteps.Build 150 | 151 | 152 | 153 | true 154 | Make 155 | 156 | Qt4ProjectManager.MakeStep 157 | 158 | true 159 | clean 160 | 161 | 162 | 1 163 | 清理 164 | 165 | ProjectExplorer.BuildSteps.Clean 166 | 167 | 2 168 | false 169 | 170 | Release 171 | 172 | Qt4ProjectManager.Qt4BuildConfiguration 173 | 0 174 | true 175 | 176 | 177 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Desktop_Qt_5_10_1_MSVC2017_64bit-Profile 178 | 179 | 180 | true 181 | qmake 182 | 183 | QtProjectManager.QMakeBuildStep 184 | true 185 | 186 | false 187 | true 188 | false 189 | 190 | 191 | true 192 | Make 193 | 194 | Qt4ProjectManager.MakeStep 195 | 196 | false 197 | 198 | 199 | 200 | 2 201 | 构建 202 | 203 | ProjectExplorer.BuildSteps.Build 204 | 205 | 206 | 207 | true 208 | Make 209 | 210 | Qt4ProjectManager.MakeStep 211 | 212 | true 213 | clean 214 | 215 | 216 | 1 217 | 清理 218 | 219 | ProjectExplorer.BuildSteps.Clean 220 | 221 | 2 222 | false 223 | 224 | Profile 225 | 226 | Qt4ProjectManager.Qt4BuildConfiguration 227 | 0 228 | true 229 | 230 | 3 231 | 232 | 233 | 0 234 | 部署 235 | 236 | ProjectExplorer.BuildSteps.Deploy 237 | 238 | 1 239 | 在本地部署 240 | 241 | ProjectExplorer.DefaultDeployConfiguration 242 | 243 | 1 244 | 245 | 246 | false 247 | false 248 | 1000 249 | 250 | true 251 | 252 | false 253 | false 254 | false 255 | false 256 | true 257 | 0.01 258 | 10 259 | true 260 | 1 261 | 25 262 | 263 | 1 264 | true 265 | false 266 | true 267 | valgrind 268 | 269 | 0 270 | 1 271 | 2 272 | 3 273 | 4 274 | 5 275 | 6 276 | 7 277 | 8 278 | 9 279 | 10 280 | 11 281 | 12 282 | 13 283 | 14 284 | 285 | 2 286 | 287 | CourseDesign 288 | CourseDesign2 289 | Qt4ProjectManager.Qt4RunConfiguration:F:/ko_git_repository/LaneLine-and-Sign-Detection/CourseDesign/CourseDesign.pro 290 | true 291 | 292 | CourseDesign.pro 293 | false 294 | 295 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Desktop_Qt_5_10_1_MSVC2017_64bit-Debug 296 | 3768 297 | false 298 | true 299 | false 300 | false 301 | true 302 | 303 | 1 304 | 305 | 306 | 307 | ProjectExplorer.Project.Target.1 308 | 309 | Qt 5.10.1 for UWP armv7 (MSVC 2017) 310 | Qt 5.10.1 for UWP armv7 (MSVC 2017) 311 | qt.qt5.5101.win64_msvc2017_winrt_armv7_kit 312 | 0 313 | -1 314 | 0 315 | 316 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_armv7_MSVC_2017-Debug 317 | 318 | 319 | true 320 | qmake 321 | 322 | QtProjectManager.QMakeBuildStep 323 | true 324 | 325 | false 326 | false 327 | false 328 | 329 | 330 | true 331 | Make 332 | 333 | Qt4ProjectManager.MakeStep 334 | 335 | false 336 | 337 | 338 | 339 | 2 340 | 构建 341 | 342 | ProjectExplorer.BuildSteps.Build 343 | 344 | 345 | 346 | true 347 | Make 348 | 349 | Qt4ProjectManager.MakeStep 350 | 351 | true 352 | clean 353 | 354 | 355 | 1 356 | 清理 357 | 358 | ProjectExplorer.BuildSteps.Clean 359 | 360 | 2 361 | false 362 | 363 | Debug 364 | 365 | Qt4ProjectManager.Qt4BuildConfiguration 366 | 2 367 | true 368 | 369 | 370 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_armv7_MSVC_2017-Release 371 | 372 | 373 | true 374 | qmake 375 | 376 | QtProjectManager.QMakeBuildStep 377 | false 378 | 379 | false 380 | false 381 | false 382 | 383 | 384 | true 385 | Make 386 | 387 | Qt4ProjectManager.MakeStep 388 | 389 | false 390 | 391 | 392 | 393 | 2 394 | 构建 395 | 396 | ProjectExplorer.BuildSteps.Build 397 | 398 | 399 | 400 | true 401 | Make 402 | 403 | Qt4ProjectManager.MakeStep 404 | 405 | true 406 | clean 407 | 408 | 409 | 1 410 | 清理 411 | 412 | ProjectExplorer.BuildSteps.Clean 413 | 414 | 2 415 | false 416 | 417 | Release 418 | 419 | Qt4ProjectManager.Qt4BuildConfiguration 420 | 0 421 | true 422 | 423 | 424 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_armv7_MSVC_2017-Profile 425 | 426 | 427 | true 428 | qmake 429 | 430 | QtProjectManager.QMakeBuildStep 431 | true 432 | 433 | false 434 | true 435 | false 436 | 437 | 438 | true 439 | Make 440 | 441 | Qt4ProjectManager.MakeStep 442 | 443 | false 444 | 445 | 446 | 447 | 2 448 | 构建 449 | 450 | ProjectExplorer.BuildSteps.Build 451 | 452 | 453 | 454 | true 455 | Make 456 | 457 | Qt4ProjectManager.MakeStep 458 | 459 | true 460 | clean 461 | 462 | 463 | 1 464 | 清理 465 | 466 | ProjectExplorer.BuildSteps.Clean 467 | 468 | 2 469 | false 470 | 471 | Profile 472 | 473 | Qt4ProjectManager.Qt4BuildConfiguration 474 | 0 475 | true 476 | 477 | 3 478 | 0 479 | 480 | 481 | false 482 | false 483 | 1000 484 | 485 | true 486 | 487 | false 488 | false 489 | false 490 | false 491 | true 492 | 0.01 493 | 10 494 | true 495 | 1 496 | 25 497 | 498 | 1 499 | true 500 | false 501 | true 502 | valgrind 503 | 504 | 0 505 | 1 506 | 2 507 | 3 508 | 4 509 | 5 510 | 6 511 | 7 512 | 8 513 | 9 514 | 10 515 | 11 516 | 12 517 | 13 518 | 14 519 | 520 | -1 521 | 522 | 523 | 524 | %{buildDir} 525 | Custom Executable 526 | 527 | ProjectExplorer.CustomExecutableRunConfiguration 528 | 3768 529 | false 530 | true 531 | false 532 | false 533 | true 534 | 535 | 1 536 | 537 | 538 | 539 | ProjectExplorer.Project.Target.2 540 | 541 | Qt 5.10.1 for UWP 64bit (MSVC 2017) 542 | Qt 5.10.1 for UWP 64bit (MSVC 2017) 543 | qt.qt5.5101.win64_msvc2017_winrt_x64_kit 544 | 0 545 | 0 546 | 0 547 | 548 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_64bit_MSVC_2017-Debug 549 | 550 | 551 | true 552 | qmake 553 | 554 | QtProjectManager.QMakeBuildStep 555 | true 556 | 557 | false 558 | false 559 | false 560 | 561 | 562 | true 563 | Make 564 | 565 | Qt4ProjectManager.MakeStep 566 | 567 | false 568 | 569 | 570 | 571 | 2 572 | 构建 573 | 574 | ProjectExplorer.BuildSteps.Build 575 | 576 | 577 | 578 | true 579 | Make 580 | 581 | Qt4ProjectManager.MakeStep 582 | 583 | true 584 | clean 585 | 586 | 587 | 1 588 | 清理 589 | 590 | ProjectExplorer.BuildSteps.Clean 591 | 592 | 2 593 | false 594 | 595 | Debug 596 | 597 | Qt4ProjectManager.Qt4BuildConfiguration 598 | 2 599 | true 600 | 601 | 602 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_64bit_MSVC_2017-Release 603 | 604 | 605 | true 606 | qmake 607 | 608 | QtProjectManager.QMakeBuildStep 609 | false 610 | 611 | false 612 | false 613 | false 614 | 615 | 616 | true 617 | Make 618 | 619 | Qt4ProjectManager.MakeStep 620 | 621 | false 622 | 623 | 624 | 625 | 2 626 | 构建 627 | 628 | ProjectExplorer.BuildSteps.Build 629 | 630 | 631 | 632 | true 633 | Make 634 | 635 | Qt4ProjectManager.MakeStep 636 | 637 | true 638 | clean 639 | 640 | 641 | 1 642 | 清理 643 | 644 | ProjectExplorer.BuildSteps.Clean 645 | 646 | 2 647 | false 648 | 649 | Release 650 | 651 | Qt4ProjectManager.Qt4BuildConfiguration 652 | 0 653 | true 654 | 655 | 656 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_64bit_MSVC_2017-Profile 657 | 658 | 659 | true 660 | qmake 661 | 662 | QtProjectManager.QMakeBuildStep 663 | true 664 | 665 | false 666 | true 667 | false 668 | 669 | 670 | true 671 | Make 672 | 673 | Qt4ProjectManager.MakeStep 674 | 675 | false 676 | 677 | 678 | 679 | 2 680 | 构建 681 | 682 | ProjectExplorer.BuildSteps.Build 683 | 684 | 685 | 686 | true 687 | Make 688 | 689 | Qt4ProjectManager.MakeStep 690 | 691 | true 692 | clean 693 | 694 | 695 | 1 696 | 清理 697 | 698 | ProjectExplorer.BuildSteps.Clean 699 | 700 | 2 701 | false 702 | 703 | Profile 704 | 705 | Qt4ProjectManager.Qt4BuildConfiguration 706 | 0 707 | true 708 | 709 | 3 710 | 711 | 712 | 713 | true 714 | 715 | Run windeployqt 716 | WinRt.BuildStep.Deploy 717 | --qmldir F:\QT_code\LiuWenguo_homework\CourseDesign 718 | 719 | 1 720 | 部署 721 | 722 | ProjectExplorer.BuildSteps.Deploy 723 | 724 | 1 725 | Run windeployqt 726 | 727 | WinRTAppxDeployConfiguration 728 | 729 | 1 730 | 731 | 732 | false 733 | false 734 | 1000 735 | 736 | true 737 | 738 | false 739 | false 740 | false 741 | false 742 | true 743 | 0.01 744 | 10 745 | true 746 | 1 747 | 25 748 | 749 | 1 750 | true 751 | false 752 | true 753 | valgrind 754 | 755 | 0 756 | 1 757 | 2 758 | 3 759 | 4 760 | 5 761 | 6 762 | 7 763 | 8 764 | 9 765 | 10 766 | 11 767 | 12 768 | 13 769 | 14 770 | 771 | -1 772 | 773 | 774 | 775 | %{buildDir} 776 | Custom Executable 777 | 778 | ProjectExplorer.CustomExecutableRunConfiguration 779 | 3768 780 | false 781 | true 782 | false 783 | false 784 | true 785 | 786 | 1 787 | 788 | 789 | 790 | ProjectExplorer.Project.Target.3 791 | 792 | Qt 5.10.1 for UWP 32bit (MSVC 2017) 793 | Qt 5.10.1 for UWP 32bit (MSVC 2017) 794 | qt.qt5.5101.win64_msvc2017_winrt_x86_kit 795 | 0 796 | 0 797 | 0 798 | 799 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_32bit_MSVC_2017-Debug 800 | 801 | 802 | true 803 | qmake 804 | 805 | QtProjectManager.QMakeBuildStep 806 | true 807 | 808 | false 809 | false 810 | false 811 | 812 | 813 | true 814 | Make 815 | 816 | Qt4ProjectManager.MakeStep 817 | 818 | false 819 | 820 | 821 | 822 | 2 823 | 构建 824 | 825 | ProjectExplorer.BuildSteps.Build 826 | 827 | 828 | 829 | true 830 | Make 831 | 832 | Qt4ProjectManager.MakeStep 833 | 834 | true 835 | clean 836 | 837 | 838 | 1 839 | 清理 840 | 841 | ProjectExplorer.BuildSteps.Clean 842 | 843 | 2 844 | false 845 | 846 | Debug 847 | 848 | Qt4ProjectManager.Qt4BuildConfiguration 849 | 2 850 | true 851 | 852 | 853 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_32bit_MSVC_2017-Release 854 | 855 | 856 | true 857 | qmake 858 | 859 | QtProjectManager.QMakeBuildStep 860 | false 861 | 862 | false 863 | false 864 | false 865 | 866 | 867 | true 868 | Make 869 | 870 | Qt4ProjectManager.MakeStep 871 | 872 | false 873 | 874 | 875 | 876 | 2 877 | 构建 878 | 879 | ProjectExplorer.BuildSteps.Build 880 | 881 | 882 | 883 | true 884 | Make 885 | 886 | Qt4ProjectManager.MakeStep 887 | 888 | true 889 | clean 890 | 891 | 892 | 1 893 | 清理 894 | 895 | ProjectExplorer.BuildSteps.Clean 896 | 897 | 2 898 | false 899 | 900 | Release 901 | 902 | Qt4ProjectManager.Qt4BuildConfiguration 903 | 0 904 | true 905 | 906 | 907 | F:/QT_code/LiuWenguo_homework/build-CourseDesign-Qt_5_10_1_for_UWP_32bit_MSVC_2017-Profile 908 | 909 | 910 | true 911 | qmake 912 | 913 | QtProjectManager.QMakeBuildStep 914 | true 915 | 916 | false 917 | true 918 | false 919 | 920 | 921 | true 922 | Make 923 | 924 | Qt4ProjectManager.MakeStep 925 | 926 | false 927 | 928 | 929 | 930 | 2 931 | 构建 932 | 933 | ProjectExplorer.BuildSteps.Build 934 | 935 | 936 | 937 | true 938 | Make 939 | 940 | Qt4ProjectManager.MakeStep 941 | 942 | true 943 | clean 944 | 945 | 946 | 1 947 | 清理 948 | 949 | ProjectExplorer.BuildSteps.Clean 950 | 951 | 2 952 | false 953 | 954 | Profile 955 | 956 | Qt4ProjectManager.Qt4BuildConfiguration 957 | 0 958 | true 959 | 960 | 3 961 | 962 | 963 | 964 | true 965 | 966 | Run windeployqt 967 | WinRt.BuildStep.Deploy 968 | --qmldir F:\QT_code\LiuWenguo_homework\CourseDesign 969 | 970 | 1 971 | 部署 972 | 973 | ProjectExplorer.BuildSteps.Deploy 974 | 975 | 1 976 | Run windeployqt 977 | 978 | WinRTAppxDeployConfiguration 979 | 980 | 1 981 | 982 | 983 | false 984 | false 985 | 1000 986 | 987 | true 988 | 989 | false 990 | false 991 | false 992 | false 993 | true 994 | 0.01 995 | 10 996 | true 997 | 1 998 | 25 999 | 1000 | 1 1001 | true 1002 | false 1003 | true 1004 | valgrind 1005 | 1006 | 0 1007 | 1 1008 | 2 1009 | 3 1010 | 4 1011 | 5 1012 | 6 1013 | 7 1014 | 8 1015 | 9 1016 | 10 1017 | 11 1018 | 12 1019 | 13 1020 | 14 1021 | 1022 | -1 1023 | 1024 | 1025 | 1026 | %{buildDir} 1027 | Custom Executable 1028 | 1029 | ProjectExplorer.CustomExecutableRunConfiguration 1030 | 3768 1031 | false 1032 | true 1033 | false 1034 | false 1035 | true 1036 | 1037 | 1 1038 | 1039 | 1040 | 1041 | ProjectExplorer.Project.TargetCount 1042 | 4 1043 | 1044 | 1045 | ProjectExplorer.Project.Updater.FileVersion 1046 | 18 1047 | 1048 | 1049 | Version 1050 | 18 1051 | 1052 | 1053 | --------------------------------------------------------------------------------