opencv车道线检测的实现方法

车道线检测,需要完成以下功能:

  • 图像裁剪:通过设定图像ROI区域,拷贝图像获得裁剪图像
  • 反透视变换:用的是室外采集到的视频,没有对应的变换矩阵。所以建立二维坐标,通过四点映射的方法计算矩阵,进行反透视变化。后因ROI区域的设置易造成变换矩阵获取困难和插值得到的透视图效果不理想,故没应用
  • 二值化:先变化为灰度图,然后设定阈值直接变成二值化图像。
  • 形态学滤波:对二值化图像进行腐蚀,去除噪点,然后对图像进行膨胀,弥补对车道线的腐蚀。
  • 边缘检测:canny变化、sobel变化和laplacian变化中选择了效果比较好的canny变化,三者在代码中均可以使用,canny变化效果稍微好一点。
  • 直线检测:实现了两种方法 1>使用opencv库封装好的霍夫直线检测函数,在原图对应区域用红线描出车道线 2>自己写一种直线检测,在头文件中,遍历ROI区域进行特定角度范围的直线检测。两种方法均可在视频中体现,第一种方法运行效率较快。
  • 按键控制:空格暂停,其余键退出,方便调试和截图。

实现的效果

在亮度良好道路条件良好的情况下,检测车前区域的车道线实现比较成功,排除掉高速护栏的影响,而且原图像还能完整体现。

车子行驶在高速公路大型弯道上,可以在一定角度范围内认定车道线仍是直线,检测出为直线。

车子切换过程中只有一根车道线被识别,但是稳定回变换车道后,实现效果良好。减速线为黄色,二值化是也被过滤,没造成影响。

刚进入隧道时,摄像机光源基本处于高光状态,拍摄亮度基本不变,二值化图像时情况良好,噪声比较多但是没产生多大线状影响;当摄像头自动调节亮度,图像亮度变低,二值化时同一阈值把车道线给过滤掉,造成无法识别车道线的现象。

在道路损坏的情况下,由于阈值一定,基本上检测不出车道线。

结论

实现的功能:实现了车道线检测的基本功能,反透视变换矩阵实现了但效果不太理想,使用自己写的直线检测部分,车道线识别抗干扰能力较强。

缺点:整个识别系统都是固定的参数,只能在特定的环境产生良好的效果。

改进空间:提取全部关键参数,每次对ROI图像进行快速扫描更新参数,否则使用默认参数。例如,可以选择每次5间隔取点,以像素最高点的85%作为该次二值化的阈值。从而做到动态车道线识别。

完整代码

方法一

main.cpp

#include<cv.h>
#include<cxcore.h>
#include<highgui.h>
#include"mylinedetect.h"

#include<cstdio>
#include<iostream>
using namespace std;

int main(){
  //声明IplImage指针
  IplImage* pFrame = NULL;
  IplImage* pCutFrame = NULL;
  IplImage* pCutFrImg = NULL;
  //声明CvCapture指针
  CvCapture* pCapture = NULL;
  //声明CvMemStorage和CvSeg指针
  CvMemStorage* storage = cvCreateMemStorage();
  CvSeq* lines = NULL;
  //生成视频的结构
  VideoWriter writer("result.avi", CV_FOURCC('M', 'J', 'P', 'G'), 25.0, Size(856, 480));
  //当前帧数
  int nFrmNum = 0;
  //裁剪的天空高度
  int CutHeight = 310;
  //窗口命名
  cvNamedWindow("video", 1);
  cvNamedWindow("BWmode", 1);
  //调整窗口初始位置
  cvMoveWindow("video", 300, 0);
  cvMoveWindow("BWmode", 300, 520);
  //不能打开则退出
  if (!(pCapture = cvCaptureFromFile("lane.avi"))){
    fprintf(stderr, "Can not open video file\n");
    return -2;
  }
  //每次读取一桢的视频
  while (pFrame = cvQueryFrame(pCapture)){
    //设置ROI裁剪图像
    cvSetImageROI(pFrame, cvRect(0, CutHeight, pFrame->width, pFrame->height - CutHeight));
    nFrmNum++;
    //第一次要申请内存p
    if (nFrmNum == 1){
      pCutFrame = cvCreateImage(cvSize(pFrame->width, pFrame->height - CutHeight), pFrame->depth, pFrame->nChannels);
      cvCopy(pFrame, pCutFrame, 0);
      pCutFrImg = cvCreateImage(cvSize(pCutFrame->width, pCutFrame->height), IPL_DEPTH_8U, 1);
      //转化成单通道图像再处理
      cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
    }
    else{
      //获得剪切图
      cvCopy(pFrame, pCutFrame, 0);
#if 0    //反透视变换
      //二维坐标下的点,类型为浮点
      CvPoint2D32f srcTri[4], dstTri[4];
      CvMat* warp_mat = cvCreateMat(3, 3, CV_32FC1);
      //计算矩阵反射变换
      srcTri[0].x = 10;
      srcTri[0].y = 20;
      srcTri[1].x = pCutFrame->width - 5;
      srcTri[1].y = 0;
      srcTri[2].x = 0;
      srcTri[2].y = pCutFrame->height - 1;
      srcTri[3].x = pCutFrame->width - 1;
      srcTri[3].y = pCutFrame->height - 1;
      //改变目标图像大小
      dstTri[0].x = 0;
      dstTri[0].y = 0;
      dstTri[1].x = pCutFrImg->width - 1;
      dstTri[1].y = 0;
      dstTri[2].x = 0;
      dstTri[2].y = pCutFrImg->height - 1;
      dstTri[3].x = pCutFrImg->width - 1;
      dstTri[3].y = pCutFrImg->height - 1;
      //获得矩阵
      cvGetPerspectiveTransform(srcTri, dstTri, warp_mat);
      //反透视变换
      cvWarpPerspective(pCutFrame, pCutFrImg, warp_mat);
#endif
      //前景图转换为灰度图
      cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
      //二值化前景图
      cvThreshold(pCutFrImg, pCutFrImg, 80, 255.0, CV_THRESH_BINARY);
      //进行形态学滤波,去掉噪音
      cvErode(pCutFrImg, pCutFrImg, 0, 2);
      cvDilate(pCutFrImg, pCutFrImg, 0, 2);
      //canny变化
      cvCanny(pCutFrImg, pCutFrImg, 50, 120);
      //sobel变化
      //Mat pCutFrMat(pCutFrImg);
      //Sobel(pCutFrMat, pCutFrMat, pCutFrMat.depth(), 1, 1);
      //laplacian变化
      //Laplacian(pCutFrMat, pCutFrMat, pCutFrMat.depth());
#if 1    //0为下面的代码,1为上面的代码
  #pragma region Hough直线检测
      lines = cvHoughLines2(pCutFrImg, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 100, 15, 15);
      printf("Lines number: %d\n", lines->total);
      //画出直线
      for (int i = 0; i<lines->total; i++){
        CvPoint* line = (CvPoint*)cvGetSeqElem(lines, i);
        double k = ((line[0].y - line[1].y)*1.0 / (line[0].x - line[1].x));
        cout<<"nFrmNum "<<nFrmNum<<" 's k = "<<k<<endl;
        if(!(abs(k)<0.1))//去掉水平直线
          cvLine(pFrame, line[0], line[1], CV_RGB(255, 0, 0), 6, CV_AA);
      }
  #pragma endregion
#else
  #pragma region mylinedetect
      Mat edge(pCutFrImg);
      vector<struct line> lines = detectLine(edge, 60);
      Mat pFrameMat(pFrame);
      drawLines(pFrameMat, lines);
      namedWindow("mylinedetect", 1);
      imshow("mylinedetect", pFrameMat);
  #pragma endregion
#endif
      //恢复ROI区域
      cvResetImageROI(pFrame);
      //写入视频流
      writer << pFrame;
      //显示图像
      cvShowImage("video", pFrame);
      cvShowImage("BWmode", pCutFrImg);
      //按键事件,空格暂停,其他跳出循环
      int temp = cvWaitKey(2);
      if (temp == 32){
        while (cvWaitKey() == -1);
      }
      else if (temp >= 0){
        break;
      }
    }
  }
  //销毁窗口
  cvDestroyWindow("video");
  cvDestroyWindow("BWmode");
  //释放图像
  cvReleaseImage(&pCutFrImg);
  cvReleaseImage(&pCutFrame);
  cvReleaseCapture(&pCapture);

  return 0;
}

mylinedetect.h

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <vector>
#include <cmath>
using namespace cv;
using namespace std;

const double pi = 3.1415926f;
const double RADIAN = 180.0 / pi;

struct line{
  int theta;
  int r;
};

vector<struct line> detectLine(Mat &img, int threshold){
  vector<struct line> lines;
  int diagonal = floor(sqrt(img.rows*img.rows + img.cols*img.cols));
  vector< vector<int> >p(360, vector<int>(diagonal));
  //统计数量
  for (int j = 0; j < img.rows; j++) {
    for (int i = 0; i < img.cols; i++) {
      if (img.at<unsigned char>(j, i) > 0){
        for (int theta = 0; theta < 360; theta++){
          int r = floor(i*cos(theta / RADIAN) + j*sin(theta / RADIAN));
          if (r < 0)
            continue;
          p[theta][r]++;
        }
      }
    }
  }
  //获得最大值
  for (int theta = 0; theta < 360; theta++){
    for (int r = 0; r < diagonal; r++){
      int thetaLeft = max(0, theta - 1);
      int thetaRight = min(359, theta + 1);
      int rLeft = max(0, r - 1);
      int rRight = min(diagonal - 1, r + 1);
      int tmp = p[theta][r];
      if (tmp > threshold
        && tmp > p[thetaLeft][rLeft] && tmp > p[thetaLeft][r] && tmp > p[thetaLeft][rRight]
        && tmp > p[theta][rLeft] && tmp > p[theta][rRight]
        && tmp > p[thetaRight][rLeft] && tmp > p[thetaRight][r] && tmp > p[thetaRight][rRight]){
        struct line newline;
        newline.theta = theta;
        newline.r = r;
        lines.push_back(newline);
      }
    }
  }
  return lines;
}

void drawLines(Mat &img, const vector<struct line> &lines){
  for (int i = 0; i < lines.size(); i++){
    vector<Point> points;
    int theta = lines[i].theta;
    int r = lines[i].r;

    double ct = cos(theta / RADIAN);
    double st = sin(theta / RADIAN);

    //公式 r = x*ct + y*st
    //计算左边
    int y = int(r / st);
    if (y >= 0 && y < img.rows){
      Point p(0, y);
      points.push_back(p);
    }
    //计算右边
    y = int((r - ct*(img.cols - 1)) / st);
    if (y >= 0 && y < img.rows){
      Point p(img.cols - 1, y);
      points.push_back(p);
    }
    //计算上边
    int x = int(r / ct);
    if (x >= 0 && x < img.cols){
      Point p(x, 0);
      points.push_back(p);
    }
    //计算下边
    x = int((r - st*(img.rows - 1)) / ct);
    if (x >= 0 && x < img.cols){
      Point p(x, img.rows - 1);
      points.push_back(p);
    }
    //画线
    cv::line(img, points[0], points[1], Scalar(255, 0, 0), 5, CV_AA);
  }
}

方法二:

#include<cv.h>
#include<cxcore.h>
#include<highgui.h>

#include<cstdio>
#include<iostream>
using namespace std;

int main(){
  //声明IplImage指针
  IplImage* pFrame = NULL;
  IplImage* pCutFrame = NULL;
  IplImage* pCutFrImg = NULL;
  IplImage* pCutBkImg = NULL;
  //声明CvMat指针
  CvMat* pCutFrameMat = NULL;
  CvMat* pCutFrMat = NULL;
  CvMat* pCutBkMat = NULL;
  //声明CvCapture指针
  CvCapture* pCapture = NULL;
  //声明CvMemStorage和CvSeg指针
  CvMemStorage* storage = cvCreateMemStorage();
  CvSeq* lines = NULL;
  //当前帧数
  int nFrmNum = 0;
  //裁剪的天空高度
  int CutHeight = 250;
  //窗口命名
  cvNamedWindow("video", 1);
  //cvNamedWindow("background", 1);
  cvNamedWindow("foreground", 1);
  //调整窗口初始位置
  cvMoveWindow("video", 300, 30);
  cvMoveWindow("background", 100, 100);
  cvMoveWindow("foreground", 300, 370);
  //不能打开则退出
  if (!(pCapture = cvCaptureFromFile("lane.avi"))){
    fprintf(stderr, "Can not open video file\n");
    return -2;
  }
  //每次读取一桢的视频
  while (pFrame = cvQueryFrame(pCapture)){
    //设置ROI裁剪图像
    cvSetImageROI(pFrame, cvRect(0, CutHeight, pFrame->width, pFrame->height - CutHeight));
    nFrmNum++;
    //第一次要申请内存p
    if (nFrmNum == 1){
      pCutFrame = cvCreateImage(cvSize(pFrame->width, pFrame->height - CutHeight), pFrame->depth, pFrame->nChannels);
      cvCopy(pFrame, pCutFrame, 0);
      pCutBkImg = cvCreateImage(cvSize(pCutFrame->width, pCutFrame->height), IPL_DEPTH_8U, 1);
      pCutFrImg = cvCreateImage(cvSize(pCutFrame->width, pCutFrame->height), IPL_DEPTH_8U, 1);

      pCutBkMat = cvCreateMat(pCutFrame->height, pCutFrame->width, CV_32FC1);
      pCutFrMat = cvCreateMat(pCutFrame->height, pCutFrame->width, CV_32FC1);
      pCutFrameMat = cvCreateMat(pCutFrame->height, pCutFrame->width, CV_32FC1);
      //转化成单通道图像再处理
      cvCvtColor(pCutFrame, pCutBkImg, CV_BGR2GRAY);
      cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
      //转换成矩阵
      cvConvert(pCutFrImg, pCutFrameMat);
      cvConvert(pCutFrImg, pCutFrMat);
      cvConvert(pCutFrImg, pCutBkMat);
    }
    else{
      //获得剪切图
      cvCopy(pFrame, pCutFrame, 0);
      //前景图转换为灰度图
      cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
      cvConvert(pCutFrImg, pCutFrameMat);
      //高斯滤波先,以平滑图像
      cvSmooth(pCutFrameMat, pCutFrameMat, CV_GAUSSIAN, 3, 0, 0.0);
      //当前帧跟背景图相减
      cvAbsDiff(pCutFrameMat, pCutBkMat, pCutFrMat);
      //二值化前景图
      cvThreshold(pCutFrMat, pCutFrImg, 35, 255.0, CV_THRESH_BINARY);
      //进行形态学滤波,去掉噪音
      cvErode(pCutFrImg, pCutFrImg, 0, 1);
      cvDilate(pCutFrImg, pCutFrImg, 0, 1);
      //更新背景
      cvRunningAvg(pCutFrameMat, pCutBkMat, 0.003, 0);
      //pCutBkMat = cvCloneMat(pCutFrameMat);
      //将背景转化为图像格式,用以显示
      //cvConvert(pCutBkMat, pCutBkImg);
      cvCvtColor(pCutFrame, pCutBkImg, CV_BGR2GRAY);
      //canny变化
      cvCanny(pCutFrImg, pCutFrImg, 50, 100);
      #pragma region Hough检测
      lines = cvHoughLines2(pCutFrImg, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 100, 30, 15);
      printf("Lines number: %d\n", lines->total);
      //画出直线
      for (int i = 0; i<lines->total; i++){
        CvPoint* line = (CvPoint* )cvGetSeqElem(lines, i);
        cvLine(pCutFrame, line[0], line[1], CV_RGB(255, 0, 0), 6, CV_AA);
      }
      #pragma endregion
      //显示图像
      cvShowImage("video", pCutFrame);
      cvShowImage("background", pCutBkImg);
      cvShowImage("foreground", pCutFrImg);
      //按键事件,空格暂停,其他跳出循环
      int temp = cvWaitKey(2);
      if (temp == 32){
        while (cvWaitKey() == -1);
      }
      else if (temp >= 0){
        break;
      }
    }
    //恢复ROI区域(多余可去掉)
    cvResetImageROI(pFrame);
  }
  //销毁窗口
  cvDestroyWindow("video");
  cvDestroyWindow("background");
  cvDestroyWindow("foreground");
  //释放图像和矩阵
  cvReleaseImage(&pCutFrImg);
  cvReleaseImage(&pCutBkImg);
  cvReleaseImage(&pCutFrame);
  cvReleaseMat(&pCutFrameMat);
  cvReleaseMat(&pCutFrMat);
  cvReleaseMat(&pCutBkMat);
  cvReleaseCapture(&pCapture);

  return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 使用OpenCV实现检测和追踪车辆

    本文实例为大家分享了OpenCV实现检测和追踪车辆的具体代码,供大家参考,具体内容如下 完整源码GitHub 使用高斯混合模型(BackgroundSubtractorMOG2)对背景建模,提取出前景 使用中值滤波去掉椒盐噪声,再闭运算和开运算填充空洞 使用cvBlob库追踪车辆,我稍微修改了cvBlob源码来通过编译 由于要对背景建模,这个方法要求背景是静止的 另外不同车辆白色区域不能连通,否则会认为是同一物体 void processVideo(char* videoFilename) {

  • python结合opencv实现人脸检测与跟踪

    模式识别课上老师留了个实验,在VC++环境下利用OpenCV库编程实现人脸检测与跟踪. 然后就开始下载opencv和vs2012,再然后,配置了好几次还是配置不成功,这里不得不吐槽下微软,软件做这么大,这么难用真的好吗? 于是就尝试了一下使用python完成实验任务,大概过程就是这样子的: 首先,配置运行环境: 下载opencv和python的比较新的版本,推荐opencv2.4.X和python2.7.X. 直接去官网下载就ok了,python安装时一路next就行,下载的opencv.exe

  • opencv实现图片与视频中人脸检测功能

    本文实例为大家分享了opencv实现人脸检测功能的具体代码,供大家参考,具体内容如下 第一章:反思与总结 上一篇博客我相信自己将人脸检测中的AdaBoost算法解释的非常清晰了,以及如何训练人脸检测的强分类器:人脸检测中AdaBoost算法详解.事后,自我感觉对这个人脸检测还是不够具体,所以自己抽了一下午的时间用opencv实现图片与视频中的人脸检测,下面是我用vs2013加opencv4.9来实现的.做一下声明,我的代码是参考OpenCV实现人脸检测的一个博客写的,非常感谢这位博主,我学到了很

  • python opencv检测目标颜色的实例讲解

    实例如下所示: # -*- coding:utf-8 -*- __author__ = 'kingking' __version__ = '1.0' __date__ = '14/07/2017' import cv2 import numpy as np import time if __name__ == '__main__': Img = cv2.imread('example.png')#读入一幅图像 kernel_2 = np.ones((2,2),np.uint8)#2x2的卷积核

  • Python+OpenCV人脸检测原理及示例详解

    关于opencv OpenCV 是 Intel 开源计算机视觉库 (Computer Version) .它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法. OpenCV 拥有包括 300 多个 C 函数的跨平台的中.高层 API .它不依赖于其它的外部库 -- 尽管也可以使用某些外部库. OpenCV 对非商业应用和商业应用都是免费 的.同时 OpenCV 提供了对硬件的访问,可以直接访问摄像头,并且 opencv 还提供了一个简单的 GUI(graph

  • Java+opencv3.2.0实现人脸检测功能

    说到人脸检测,首先要了解Haar特征分类器.Haar特征分类器说白了就是一个个的xml文件,不同的xml里面描述人体各个部位的特征值,比如人脸.眼睛等等.OpenCV3.2.0中提供了如下特征文件: haarcascade_eye.xml haarcascade_eye_tree_eyeglasses.xml haarcascade_frontalcatface.xml haarcascade_frontalcatface_extended.xml haarcascade_frontalface

  • python+opencv实现霍夫变换检测直线

    本文实例为大家分享了python+opencv实现霍夫变换检测直线的具体代码,供大家参考,具体内容如下 python+opencv实现高斯平滑滤波 python+opencv实现阈值分割 功能: 创建一个滑动条来控制检测直线的长度阈值,即大于该阈值的检测出来,小于该阈值的忽略 注意:这里用的函数是HoughLinesP而不是HoughLines,因为HoughLinesP直接给出了直线的断点,在画出线段的时候可以偷懒 代码: # -*- coding: utf-8 -*- import cv2

  • 利用Opencv中Houghline方法实现直线检测

    利用Opencv中的Houghline方法进行直线检测-python语言 这是给Python部落翻译的文章,请在这里看原文. 在图像处理中,霍夫变换用来检测任意能够用数学公式表达的形状,即使这个形状被破坏或者有点扭曲. 下面我们将看到利用HoughLine算法来阐述霍夫变化进行直线检测的原理,把此算法应用到特点图像的边缘检测是可取的.边缘检测方法请参考这篇文章–边缘检测. Houghline算法基础 直线可以表示为y=mx+c,或者以极坐标形式表示为r=xcosθ+ysinθ,其中r是原点到直线

  • OpenCV-Python实现轮廓检测实例分析

    相比C++而言,Python适合做原型.本系列的文章介绍如何在Python中用OpenCV图形库,以及与C++调用相应OpenCV函数的不同之处.这篇文章介绍在Python中使用OpenCV检测并绘制轮廓. 提示: 转载请详细注明原作者及出处,谢谢! 本文介绍在OpenCV-Python中检测并绘制轮廓的方法. 本文不介详细的理论知识,读者可从其他资料中获取相应的背景知识.笔者推荐清华大学出版社的<图像处理与计算机视觉算法及应用(第2版)>. 轮廓检测 轮廓检测也是图像处理中经常用到的.Ope

  • opencv车道线检测的实现方法

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

  • 基于OpenCV实现车道线检测(自动驾驶 机器视觉)

    目录 0 前言 1 车道线检测 2 目标 3 检测思路 4 代码实现 4.1 视频图像加载 4.2 车道线区域 4.3 区域 4.4 canny 边缘检测 4.5 霍夫变换(Hough transform) 4.6 HoughLinesP 检测原理 0 前言 无人驾驶技术是机器学习为主的一门前沿领域,在无人驾驶领域中机器学习的各种算法随处可见,今天学长给大家介绍无人驾驶技术中的车道线检测. 1 车道线检测 在无人驾驶领域每一个任务都是相当复杂,看上去无从下手.那么面对这样极其复杂问题,我们解决问

  • python+opencv实现车道线检测

    python+opencv车道线检测(简易实现),供大家参考,具体内容如下 技术栈:python+opencv 实现思路: 1.canny边缘检测获取图中的边缘信息: 2.霍夫变换寻找图中直线: 3.绘制梯形感兴趣区域获得车前范围: 4.得到并绘制车道线: 效果展示: 代码实现: import cv2 import numpy as np def canny(): gray = cv2.cvtColor(lane_image, cv2.COLOR_RGB2GRAY) #高斯滤波 blur = c

  • 使用opencv实现车道线检测实战代码

    效果 void lane_detection(cv::Mat &src, cv::Mat &dst) { dst = cv::Mat::zeros(src.size(),src.type()); cv::Mat grid =cv::Mat::zeros(src.size(),src.type()); int iStep = 25; int iNUmsX = src.cols / iStep; int inUmsY = src.rows / iStep; for(int i = 1; i &

  • 基于opencv实现车道线检测

    基于opencv的车道线检测,供大家参考,具体内容如下 原理: 算法基本思想说明: 传统的车道线检测,多数是基于霍夫直线检测,其实这个里面有个很大的误区,霍夫直线拟合容易受到各种噪声干扰,直接运用有时候效果不好,更多的时候通过霍夫直线检测进行初步的筛选,然后再有针对性的进行直线拟合,根据拟合的直线四个点坐标,绘制出车道线,这种方式可以有效避免霍夫直线拟合不良后果,是一种更加稳定的车道线检测方法,在实际项目中,可以选择两种方法并行,在计算出结果后进行叠加或者对比提取,今天分享的案例主要是绕开了霍夫

  • Python道路车道线检测的实现

    车道线检测是自动驾驶汽车以及一般计算机视觉的关键组件.这个概念用于描述自动驾驶汽车的路径并避免进入另一条车道的风险. 在本文中,我们将构建一个机器学习项目来实时检测车道线.我们将使用 OpenCV 库使用计算机视觉的概念来做到这一点.为了检测车道,我们必须检测车道两侧的白色标记. 使用 Python 和 OpenCV 进行道路车道线检测 使用 Python 中的计算机视觉技术,我们将识别自动驾驶汽车必须行驶的道路车道线.这将是自动驾驶汽车的关键部分,因为自动驾驶汽车不应该越过它的车道,也不应该进

  • C++ opencv实现车道线识别

    本文实例为大家分享了C++ opencv实现车道线识别的具体代码,供大家参考,具体内容如下 先上图 1. 2. (一)目前国内外广泛使用的车道线检测方法主要分为两大类: (1) 基于道路特征的车道线检测: (2) 基于道路模型的车道线检测. 基于道路特征的车道线检测作为主流检测方法之一,主要是利用车道线与道路环境的物理特征差异进行后续图像的分割与处理,从而突出车道线特征,以实现车道线的检测.该方法复杂度较低,实时性较高,但容易受到道路环境干扰. 基于道路模型的车道线检测主要是基于不同的二维或三维

  • python opencv角点检测连线功能的实现代码

    原始图 角点检测 points = cv2.goodFeaturesToTrack(gray, 100, 0.01, 10) points = np.int0(points).reshape(-1,2) for point in points: x, y = point.ravel() cv2.circle(img, (x, y), 10, (0, 255, 0), -1) 连线 cv2.line(img, (0, y1), (1000, y1), (0, 255, 0), thickness=

  • opencv实现机器视觉检测和计数的方法

    引言 在机器视觉中,有时需要对产品进行检测和计数.其难点无非是对于产品的图像分割. 由于之前网购的维生素片,有时候忘了今天有没有吃过,就想对瓶子里的药片计数...在学习opencv以后,希望实现对于维生素片分割计数算法.本次实战在基于形态学的基础上又衍生出基于距离变换的分水岭算法,使其实现的效果更具普遍性. 基于形态学的维生素片检测和计数 整体思路: 读取图片 形态学处理(在二值化前进行适度形态学处理,效果俱佳) 二值化 提取轮廓(进行药片分割) 获取轮廓索引,并筛选所需要的轮廓 画出轮廓,显示

  • OpenCV实现特征检测和特征匹配方法汇总

    目录 1.SURF 2.SIFT 3.ORB 4.FAST 5.Harris角点 一幅图像中总存在着其独特的像素点,这些点我们可以认为就是这幅图像的特征,成为特征点.计算机视觉领域中的很重要的图像特征匹配就是一特征点为基础而进行的,所以,如何定义和找出一幅图像中的特征点就非常重要.这篇文章我总结了视觉领域最常用的几种特征点以及特征匹配的方法. 在计算机视觉领域,兴趣点(也称关键点或特征点)的概念已经得到了广泛的应用, 包括目标识别. 图像配准. 视觉跟踪. 三维重建等. 这个概念的原理是, 从图

随机推荐