图像处理车道线识别_图像识别 车辆在哪个车道 - CSDN
精华内容
参与话题
  • 图像处理车道线检测

    千次阅读 2017-05-28 12:07:30
    看过几篇车道线检测的文章,有原理比较简单的,比如基于模板、霍夫变换,复杂的还有基于深度学习的,有检测直道、弯道的。推荐几篇文章。根据实际需求,我只是想能够比较粗略地得到视频流中的车道线信息,不需要特别...

    看过几篇车道线检测的文章,有原理比较简单的,比如基于模板、霍夫变换,复杂的还有基于深度学习的,有检测直道、弯道的。推荐几篇文章。根据实际需求,我只是想能够比较粗略地得到视频流中的车道线信息,不需要特别精确,所以本人是基于OpenCV,通过霍夫变换实现的车道线检测。
    直接看代码和结果吧:
    代码部分:

    /*
    -功能:车道线检测
    -输入:
            IplImage * curImage      //图像
    -返回:
            //本文中保存车道线起点和终点的参数是全局变量
    */
    void getRoad(IplImage * curImage)
    {
        IplImage *temp = cvCreateImage(cvGetSize(curImage), IPL_DEPTH_8U, 1);
        //cvCvtColor(curImage, temp, CV_BGR2GRAY);
        cvThreshold(curImage, temp, 90, 255.0, CV_THRESH_BINARY);       //200
        cvErode(temp, temp, NULL, 1);
        cvDilate(temp, temp, NULL, 1);
        cvCanny(temp, temp, 50, 120);
        //霍夫变换
        CvSeq *lines = NULL;
    
        CvMemStorage *storage = cvCreateMemStorage(0);
        lines = cvHoughLines2(
            temp, 
            storage, 
            CV_HOUGH_PROBABILISTIC,         //method            概率
            1.0,                            //rho
            CV_PI / 180,                    //theta
            40,                             //threshold     像素点个数阈值
            20,                             //param1        最小线段长度
            10);                            //param2        线段的最大间隔
        int length = lines->total;
        vector<CvPoint*> lRoadV, rRoadV;//候选车道线线段
        for (size_t i = 0; i < length; i++)
        {
            CvPoint *points = (CvPoint*)cvGetSeqElem(lines, i);
            double k = (points[0].y - points[1].y)*1.0 / (points[0].x - points[1].x);
            if (k > -1.5&&k < -0.5)             //左车道
            {
                lRoadV.push_back(points);
            }
            else if (k > 0.5 && k < 1.5)        //右车道
            {
                rRoadV.push_back(points);
            }   
        }
            selectRoad(lRoadV, rRoadV);//进一步筛选车道线
    }
    

    效果如下
    这里写图片描述

    展开全文
  • 车道线识别

    2020-07-30 23:32:19
    基于huogh变换的车道线检测改进算法,实现车道线识别
  • 目标:实际公路的车道线检测 素材中车道保持不变,车道线清晰明确,易于检测,是车道检测的基础版本,网上也有很多针对复杂场景的高级实现,感兴趣的朋友可以自行了解。 如果我们手动把这部分ROI区域抠出来,就会...

    目标:实际公路的车道线检测

    道路图像
    素材中车道保持不变,车道线清晰明确,易于检测,是车道检测的基础版本,网上也有很多针对复杂场景的高级实现,感兴趣的朋友可以自行了解。
    车道线位置基本固定在虚线框内
    如果我们手动把这部分ROI区域抠出来,就会排除掉大部分干扰。接下来检测直线肯定是用霍夫变换,但ROI区域内的边缘直线信息还是很多,考虑到只有左右两条车道线,一条斜率为正,一条为负,可将所有的线分为两组,每组再通过均值或最小二乘法拟合的方式确定唯一一条线就可以完成检测。总体步骤如下:
    1. 灰度化
    2. 高斯模糊
    3. Canny边缘检测
    4. 不规则ROI区域截取
    5. 霍夫直线检测
    6. 车道计算
    7. 对于视频来说,只要一幅图能检查出来,合成下就可以了,问题不大。

    图像预处理

    灰度化和滤波操作是大部分图像处理的必要步骤。灰度化不必多说,因为不是基于色彩信息识别的任务,所以没有必要用彩色图,可以大大减少计算量。而滤波会削弱图像噪点,排除干扰信息。另外,根据前面学习的知识,边缘提取是基于图像梯度的,梯度对噪声很敏感,所以平滑滤波操作必不可少。
    原图 vs 灰度滤波图
    这次的代码我们分模块来写,规范一点。其中process_an_image()是主要的图像处理流程:

    import cv2 as cv
    import numpy as np
    
    # 高斯滤波核大小
    blur_ksize = 5
    # Canny边缘检测高低阈值
    canny_lth = 50
    canny_hth = 150
    
    def process_an_image(img):
        # 1. 灰度化、滤波和Canny
        gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
        blur_gray = cv.GaussianBlur(gray, (blur_ksize, blur_ksize), 1)
        edges = cv.Canny(blur_gray, canny_lth, canny_hth)
    
    if __name__ == "__main__":
        img = cv.imread('test_pictures/lane.jpg')
        result = process_an_image(img)
        cv.imshow("lane", np.hstack((img, result)))
        cv.waitKey(0)
    

    边缘检测结果图

    ROI获取

    按照前面描述的方案,只需保留边缘图中的红线部分区域用于后续的霍夫直线检测,其余都是无用的信息:
    过滤掉红框以外的信息
    如何实现呢?我们可以创建一个梯形的mask掩膜,然后与边缘检测结果图混合运算,掩膜中白色的部分保留,黑色的部分舍弃。梯形的四个坐标需要手动标记:
    掩膜mask

    def process_an_image(img):
        # 1. 灰度化、滤波和Canny
    
        # 2. 标记四个坐标点用于ROI截取
        rows, cols = edges.shape
        points = np.array([[(0, rows), (460, 325), (520, 325), (cols, rows)]])
        # [[[0 540], [460 325], [520 325], [960 540]]]
        roi_edges = roi_mask(edges, points)
        
    def roi_mask(img, corner_points):
        # 创建掩膜
        mask = np.zeros_like(img)
        cv.fillPoly(mask, corner_points, 255)
    
        masked_img = cv.bitwise_and(img, mask)
        return masked_img
    

    这样,结果图”roi_edges”应该是:
    只保留关键区域的边缘检测图

    霍夫直线提取

    为了方便后续计算直线的斜率,我们使用统计概率霍夫直线变换(因为它能直接得到直线的起点和终点坐标)。霍夫变换的参数比较多,可以放在代码开头,便于修改:

    # 霍夫变换参数
    rho = 1
    theta = np.pi / 180
    threshold = 15
    min_line_len = 40
    max_line_gap = 20
    
    def process_an_image(img):
        # 1. 灰度化、滤波和Canny
    
        # 2. 标记四个坐标点用于ROI截取
    
        # 3. 霍夫直线提取
        drawing, lines = hough_lines(roi_edges, rho, theta, threshold, min_line_len, max_line_gap)
    
    def hough_lines(img, rho, theta, threshold, min_line_len, max_line_gap):
        # 统计概率霍夫直线变换
        lines = cv.HoughLinesP(img, rho, theta, threshold, minLineLength=min_line_len, maxLineGap=max_line_gap)
    
        # 新建一副空白画布
        drawing = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
        # draw_lines(drawing, lines)     # 画出直线检测结果
    
        return drawing, lines
    
    def draw_lines(img, lines, color=[0, 0, 255], thickness=1):
        for line in lines:
            for x1, y1, x2, y2 in line:
                cv.line(img, (x1, y1), (x2, y2), color, thickness)
    

    draw_lines()是用来画直线检测的结果,后面我们会接着处理直线,所以这里注释掉了,可以取消注释看下效果:
    霍夫直线检测结果图
    对本例的这张测试图来说,如果打印出直线的条数print(len(lines)),应该是有15条。

    车道计算

    这部分应该算是本实验的核心内容了:前面通过霍夫变换得到了多条直线的起点和终点,我们的目的是通过某种算法只得到左右两条车道线。
    第一步:根据斜率正负划分某条线是左车道还是右车道。
    斜率计算公式
    再次强调,斜率计算是在图像坐标系下,所以斜率正负/左右跟平面坐标有区别。
    第二步、迭代计算各直线斜率与斜率均值的差,排除掉差值过大的异常数据。

    注意这里迭代的含义,意思是第一次计算完斜率均值并排除掉异常值后,再在剩余的斜率中取均值,继续排除……这样迭代下去。

    第三步、最小二乘法拟合左右车道线。

    经过第二步的筛选,就只剩下可能的左右车道线了,这样只需从多条直线中拟合出一条就行。拟合方法有很多种,最常用的便是最小二乘法,它通过最小化误差的平方和来寻找数据的最佳匹配函数。

    具体来说,假设目前可能的左车道线有6条,也就是12个坐标点,包括12个x和12个y,我们的目的是拟合出这样一条直线:
    直线公式
    使得误差平方和最小:
    误差平方和公式
    Python中可以直接使用np.polyfit()进行最小二乘法拟合。

    def process_an_image(img):
        # 1. 灰度化、滤波和Canny
    
        # 2. 标记四个坐标点用于ROI截取
    
        # 3. 霍夫直线提取
    
        # 4. 车道拟合计算
        draw_lanes(drawing, lines)
    
        # 5. 最终将结果合在原图上
        result = cv.addWeighted(img, 0.9, drawing, 0.2, 0)
    
        return result
    
    def draw_lanes(img, lines, color=[255, 0, 0], thickness=8):
        # a. 划分左右车道
        left_lines, right_lines = [], []
        for line in lines:
            for x1, y1, x2, y2 in line:
                k = (y2 - y1) / (x2 - x1)
                if k < 0:
                    left_lines.append(line)
                else:
                    right_lines.append(line)
    
        if (len(left_lines) <= 0 or len(right_lines) <= 0):
            return
    
        # b. 清理异常数据
        clean_lines(left_lines, 0.1)
        clean_lines(right_lines, 0.1)
    
        # c. 得到左右车道线点的集合,拟合直线
        left_points = [(x1, y1) for line in left_lines for x1, y1, x2, y2 in line]
        left_points = left_points + [(x2, y2) for line in left_lines for x1, y1, x2, y2 in line]
        right_points = [(x1, y1) for line in right_lines for x1, y1, x2, y2 in line]
        right_points = right_points + [(x2, y2) for line in right_lines for x1, y1, x2, y2 in line]
    
        left_results = least_squares_fit(left_points, 325, img.shape[0])
        right_results = least_squares_fit(right_points, 325, img.shape[0])
    
        # 注意这里点的顺序,从左下角开始按照顺序构造梯形
        vtxs = np.array([[left_results[1], left_results[0], right_results[0], right_results[1]]])
        # d. 填充车道区域
        cv.fillPoly(img, vtxs, (0, 255, 0))
    
        # 或者只画车道线
        # cv.line(img, left_results[0], left_results[1], (0, 255, 0), thickness)
        # cv.line(img, right_results[0], right_results[1], (0, 255, 0), thickness)
        
    def clean_lines(lines, threshold):
        # 迭代计算斜率均值,排除掉与差值差异较大的数据
        slope = [(y2 - y1) / (x2 - x1) for line in lines for x1, y1, x2, y2 in line]
        while len(lines) > 0:
            mean = np.mean(slope)
            diff = [abs(s - mean) for s in slope]
            idx = np.argmax(diff)
            if diff[idx] > threshold:
                slope.pop(idx)
                lines.pop(idx)
            else:
                break
                
    def least_squares_fit(point_list, ymin, ymax):
        # 最小二乘法拟合
        x = [p[0] for p in point_list]
        y = [p[1] for p in point_list]
    
        # polyfit第三个参数为拟合多项式的阶数,所以1代表线性
        fit = np.polyfit(y, x, 1)
        fit_fn = np.poly1d(fit)  # 获取拟合的结果
    
        xmin = int(fit_fn(ymin))
        xmax = int(fit_fn(ymax))
    
        return [(xmin, ymin), (xmax, ymax)]
    

    这段代码比较多,请每个步骤单独来看。最后得到的是左右两条车道线的起点和终点坐标,可以选择画出车道线,这里我直接填充了整个区域:
    填充车道线结果
    搞定了一张图,视频也就没什么问题了,关键就是视频帧的提取和合成,为此,我们要用到Python的视频编辑包moviepy:
    pip install moviepy
    另外还需要ffmpeg,首次运行moviepy时会自动下载,也可手动下载。

    只需在开头导入moviepy,然后将主函数改掉就可以了,其余代码不需要更改:

    # 开头导入moviepy
    from moviepy.editor import VideoFileClip
    
    # 主函数更改为:
    if __name__ == "__main__":
        output = 'test_videos/output.mp4'
        clip = VideoFileClip("test_videos/cv2_white_lane.mp4")
        out_clip = clip.fl_image(process_an_image)
        out_clip.write_videofile(output, audio=False)
    

    本文实现了车道检测的基础版本,如果你感兴趣的话,可以自行搜索了解更多。

    实现功能完整代码

    import cv2 as cv
    import numpy as np
    
    # 高斯滤波核大小
    blur_ksize = 5
    
    # Canny边缘检测高低阈值
    canny_lth = 50
    canny_hth = 150
    
    # 霍夫变换参数
    rho = 1
    theta = np.pi / 180
    threshold = 15
    min_line_len = 40
    max_line_gap = 20
    
    
    def process_an_image(img):
        # 1. 灰度化、滤波和Canny
        gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
        blur_gray = cv.GaussianBlur(gray, (blur_ksize, blur_ksize), 1)
        edges = cv.Canny(blur_gray, canny_lth, canny_hth)
    
        # 2. 标记四个坐标点用于ROI截取
        rows, cols = edges.shape
        points = np.array([[(0, rows), (460, 325), (520, 325), (cols, rows)]])
        # [[[0 540], [460 325], [520 325], [960 540]]]
        roi_edges = roi_mask(edges, points)
    
        # 3. 霍夫直线提取
        drawing, lines = hough_lines(roi_edges, rho, theta,
                                     threshold, min_line_len, max_line_gap)
    
        # 4. 车道拟合计算
        draw_lanes(drawing, lines)
    
        # 5. 最终将结果合在原图上
        result = cv.addWeighted(img, 0.9, drawing, 0.2, 0)
    
        return result
    
    
    def roi_mask(img, corner_points):
        # 创建掩膜
        mask = np.zeros_like(img)
        cv.fillPoly(mask, corner_points, 255)
    
        masked_img = cv.bitwise_and(img, mask)
        return masked_img
    
    
    def hough_lines(img, rho, theta, threshold, min_line_len, max_line_gap):
        # 统计概率霍夫直线变换
        lines = cv.HoughLinesP(img, rho, theta, threshold,
                                minLineLength=min_line_len, maxLineGap=max_line_gap)
    
        # 新建一副空白画布
        drawing = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
        # 画出直线检测结果
        # draw_lines(drawing, lines)
        # print(len(lines))
    
        return drawing, lines
    
    
    def draw_lines(img, lines, color=[0, 0, 255], thickness=1):
        for line in lines:
            for x1, y1, x2, y2 in line:
                cv.line(img, (x1, y1), (x2, y2), color, thickness)
    
    
    def draw_lanes(img, lines, color=[255, 0, 0], thickness=8):
        # a. 划分左右车道
        left_lines, right_lines = [], []
        for line in lines:
            for x1, y1, x2, y2 in line:
                k = (y2 - y1) / (x2 - x1)
                if k < 0:
                    left_lines.append(line)
                else:
                    right_lines.append(line)
    
        if (len(left_lines) <= 0 or len(right_lines) <= 0):
            return
    
        # b. 清理异常数据
        clean_lines(left_lines, 0.1)
        clean_lines(right_lines, 0.1)
    
        # c. 得到左右车道线点的集合,拟合直线
        left_points = [(x1, y1) for line in left_lines for x1, y1, x2, y2 in line]
        left_points = left_points + [(x2, y2)
                                     for line in left_lines for x1, y1, x2, y2 in line]
    
        right_points = [(x1, y1)
                        for line in right_lines for x1, y1, x2, y2 in line]
        right_points = right_points + \
            [(x2, y2) for line in right_lines for x1, y1, x2, y2 in line]
    
        left_results = least_squares_fit(left_points, 325, img.shape[0])
        right_results = least_squares_fit(right_points, 325, img.shape[0])
    
        # 注意这里点的顺序
        vtxs = np.array(
            [[left_results[1], left_results[0], right_results[0], right_results[1]]])
        # d.填充车道区域
        cv.fillPoly(img, vtxs, (0, 255, 0))
    
        # 或者只画车道线
        # cv.line(img, left_results[0], left_results[1], (0, 255, 0), thickness)
        # cv.line(img, right_results[0], right_results[1], (0, 255, 0), thickness)
    
    
    def clean_lines(lines, threshold):
        # 迭代计算斜率均值,排除掉与差值差异较大的数据
        slope = [(y2 - y1) / (x2 - x1)
                 for line in lines for x1, y1, x2, y2 in line]
        while len(lines) > 0:
            mean = np.mean(slope)
            diff = [abs(s - mean) for s in slope]
            idx = np.argmax(diff)
            if diff[idx] > threshold:
                slope.pop(idx)
                lines.pop(idx)
            else:
                break
    
    
    def least_squares_fit(point_list, ymin, ymax):
        # 最小二乘法拟合
        x = [p[0] for p in point_list]
        y = [p[1] for p in point_list]
    
        # polyfit第三个参数为拟合多项式的阶数,所以1代表线性
        fit = np.polyfit(y, x, 1)
        fit_fn = np.poly1d(fit)  # 获取拟合的结果
    
        xmin = int(fit_fn(ymin))
        xmax = int(fit_fn(ymax))
    
        return [(xmin, ymin), (xmax, ymax)]
    
    
    if __name__ == "__main__":
        img = cv.imread('test_pictures/lane2.jpg')
        result = process_an_image(img)
        cv.imshow("lane", np.hstack((img, result)))
        cv.waitKey(0)
    

    左图:原图;右图:车道检测结果

    展开全文
  • 图像分割--车道线识别

    千次阅读 2018-09-24 11:29:41
    一、背景  无人驾驶技术近年来发展迅速。无人车若想实现自动驾驶,从视觉的角度上讲其要先学会观察道路,具体来说,就是... 本车道线识别的算法流程图如图1所示,本部分后面将对其各部分原理进行简要说明。  ...

    一、背景

           无人驾驶技术近年来发展迅速。无人车若想实现自动驾驶,从视觉的角度上讲其要先学会观察道路,具体来说,就是检测车道线。包括识别车道线与车的位置关系,是实线还是虚线等。本文将简单介绍车道线检测的基本技术,将在python平台上使用opencv库进行测试。

    二、车道线识别主要原理

           本车道线识别的算法流程图如图1所示,本部分后面将对其各部分原理进行简要说明。

                                                                                    

                                                                                   图1

    1)彩色图像转化为灰度图像

           通常的彩色图像是三通道的,为处理简便,将彩色图像转化为单通道的灰度图像。转化的经验公式如下。该公式是根据人眼对RGB三种不同颜色的感光强度进行分配的。

                                              Gray =0.299∙R+0.587∙G+0.114∙B

    2)图像平滑

           图像中噪声太严重将会影响对目标的分割提取,所以前期需要对图像进行平滑滤波,降低图像噪声和减小细节的同时,还能保留边界。图像平滑滤波算法有许多种,如中值滤波、高斯滤波等。本项目选用高斯滤波算法对图像进行去噪,其原理是重新计算图像中每个点的值,计算的时候将该点与周围点进行加权平均,权重符合高斯分布。一般将权重按对应位置组成矩阵形式,称为高斯核,其中本项目将用到的是大小为5的高斯核,如下所示:

                                                                

    3)边缘提取

           车道线的一个主要特征是他的边缘比较明显,因此可以使用边缘检测算法将之从原图像中提取出来。边缘检测的结果就是标识出数字图像中亮度值变化明显的点。边缘检测的实质是计算图片中每个点的梯度(像素值的变化情况),变化值越大表明是边缘的可能性越高。本文使用canny算法进行图像边缘提取,其计算梯度时使用了卷积,计算方向[0、45、90、135]度间的梯度值。

           计算出每个像素点的梯度值后,接下来需要筛选可疑边缘点。方法是将每个像素点的梯度值与梯度方向上的俩个点进行比较,当且仅当这个点的梯度值最大时才保留,否则舍弃。例如,梯度方向是0度,那么将当前梯度值与左右两边的梯度值进行比较,当且仅当当前梯度值最大才保留。

           从前一步筛选出的点只是可疑边缘点,会存在部分误标记的点,这些标记的点可能是由噪声或则颜色的变化造成的。解决思路是设置俩个阈值low_threshold、high_threshold,当像素点梯度值小于low_threshold时,说明该像素点是误标记点,将其丢弃;当像素点梯度值大于high _threshold时,说明该像素点不是误标记点,将其保留;当像素点梯度值介于俩阈值之间时,当且仅当存在其相连点的梯度值大于high _threshold时才保留为边缘点。

    4ROI区域选择

           通过Canny算法进行边缘检测获得边缘图像后,边缘图像不仅包括所需要的车道线边缘,同时包括不需要的其他车道以及周围围栏的边缘。去掉这些边缘的办法是确定一个多边形的可视域,只保留可视域部分的边缘信息。其依据是camera相对车是固定的,车相对于车道的相对位置也基本固定,所以车道在camera中基本保持在一个固定区域内。所以可以保留边缘图像中的可视域部分,去除其他无关信息对图像处理的干扰。

    5)霍夫线变换

           霍夫变换是一种特征提取技术,检测具有特定形状的物体,通常是直线、圆、椭圆等。其原理是将原空间映射到参数空间,在参数空间进行投票获得所需的图像。

           霍夫线变换是一种用来寻找直线的方法。一条直线在图像二维空间中由俩个变量表示,一种方法是在笛卡尔坐标系中用(m,b)斜率和截距表示;另一种方法是在极坐标系中用(r,θ)极径和极角表示。

           对于霍夫变换,我们将用极坐标系来表示直线。因此,直线的表达式可表示为:y=(-\cos \theta /\sin \theta )x+(r/\sin \theta ),化简得:r=x\cos \theta +y\sin \theta。一般来说,对于点(x_{0},y_{0}),我们可以将通过这个点的一族直线统一定义为:y_{\theta }=x_{0}\cos \theta +y_{0}\sin \theta。这意味着每一对(r_{\theta },\theta )代表一条通过点(x_{0},y_{0})的直线。如果对于一个给定的点(x_{0},y_{0}),我们在极坐标系对极径极角平面绘出所有通过它的直线,将得到一条正弦曲线。若对图像中所有点进行上述操作,如果俩个不同点进行上述操作后得到的曲线在平面极径极角平面相交,这就意味着它们通过同一条直线。霍夫线变换要做的就是追踪图像中每个点对应曲线的交点。如果交于一点的曲线的数量超过了阈值,那么可以认为这个交点所代表的参数对(r_{\theta },\theta )在原图像中为一条直线。最后在根据这个参数对在原图像中绘制出车道线。

    三、实现代码以及运行效果分析

    1)源代码及注释:

    import numpy as np
    import cv2
    import matplotlib.pyplot as plt
    import matplotlib.image as mpimg
    
    '''根据极角极径参数在原图像中画线'''
    def draw_lines(img, lines, color=[255, 0, 0], thickness=6):
        for line in lines:
            for x1,y1,x2,y2 in line:
                # 在图像中设置俩条水平线,只有当直线于其相交,才绘制该直线,用于筛选直线
                top_horizon_line = ([0, img.shape[0]*0.6], [img.shape[1], img.shape[0]*0.7])
                bottom_horizon_line = ([0, img.shape[0]], [img.shape[1], img.shape[0]])
                line_intersection_top = line_intersection(top_horizon_line, ([x1, y1], [x2, y2]))
                line_intersection_bottom = line_intersection(bottom_horizon_line, ([x1, y1], [x2, y2]))
                if line_intersection_top == None or line_intersection_bottom == None:
                    return
                # 绘制直线
                cv2.line(img, line_intersection_top, line_intersection_bottom, color, thickness)
    
    '''判断俩条线段是否相交'''
    def line_intersection(line1, line2):
        xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
        ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
    
        def det(a, b):
            return a[0] * b[1] - a[1] * b[0]
        div = det(xdiff, ydiff)
    
        if div == 0:
           return None
    
        d = (det(*line1), det(*line2))
        x = det(d, xdiff) / div
        y = det(d, ydiff) / div
        return int(x), int(y)
    
    
    image = mpimg.imread("./test_images/lane.jpg")      # 读取源图像
    showImg = True
    image = np.array(image)
    grayscale_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)   # 转为灰度图
    kernel_size = 5
    # 高斯平滑,大小为5的高斯核
    gaussian_blur_image = cv2.GaussianBlur(grayscale_image, (kernel_size, kernel_size), 0)
    # 设置阈值,进行canny边缘提取
    canny_low_threshold = 10
    canny_high_threshold = 20
    edge_image = cv2.Canny(gaussian_blur_image, canny_low_threshold, canny_high_threshold)
    # ROI可视区域选择,本程序选取左测公路区域
    image_shape = edge_image.shape
    x_offset = 200
    y_offset = 90
    v1 = (0,  image_shape[0] - y_offset / 2)
    v2 = (int(image_shape[1]/4 + x_offset), int(image_shape[0]/2+y_offset))
    v3 = (int(image_shape[1]/2 - x_offset), int(image_shape[0]/2+y_offset))
    v4 = (image_shape[1] / 2 + x_offset, image_shape[0] - y_offset / 2)
    vert = np.array([[v1, v2, v3, v4]], dtype=np.int32)
    mask = np.zeros_like(edge_image)
    if len(edge_image.shape) > 2:
        channel_count = edge_image.shape[2]
        ignore_mask_color = (255,) * channel_count
    else:
        ignore_mask_color = 255
    # ROI可视区填充,在用mask与灰度图进行与运算,即在灰度图中得可视区
    cv2.fillPoly(mask, vert, ignore_mask_color)
    masked_edge_image = cv2.bitwise_and(edge_image, mask)
    # 显示可视区的边缘提取二值图像
    cv2.imshow("edge", masked_edge_image)
    print(np.array([[v1, v2, v3, v4]], dtype=np.int32))
    # 霍夫线变换
    rho = 2                 # 设置极径分辨率
    theta = (np.pi)/180     # 设置极角分辨率
    threshold = 100         # 设置检测一条直线所需最少的交点
    min_line_len = 300      # 设置线段最小长度
    max_line_gap = 20       # 设置线段最近俩点的距离
    lines = cv2.HoughLinesP(masked_edge_image, rho, theta, threshold, np.array([]), minLineLength=min_line_len, maxLineGap=max_line_gap)
    hough_line_image = np.zeros((masked_edge_image.shape[0], masked_edge_image.shape[1], 3), dtype=np.uint8)
    # 绘制检测到的直线
    draw_lines(hough_line_image, lines)
    # 将直线与原图像合成为一幅图像
    sync_image = cv2.addWeighted(image, 0.8, hough_line_image, 1, 0)
    # 显示图像
    if showImg:
        plt.imshow(sync_image)
        plt.show()
        cv2.imshow("lane", sync_image)
        cv2.waitKey(0)
    

    2)运行结果

                                                           

                                                                              图2 ROI边缘提取二值图像

                                                         

                                                                               图3 车道线识别图像

           从图2、图3可以看出,本车道线识别算法能较好的识别出车道线,而且识别速度块。不足的地方在于对较为模糊的车道线不能很好的将其检测出来,比如图3中左边公路中的中间车道线没有检测出来。从图2的ROI边缘提取二值图像中可以看出,这是canny边缘提取的时候中间车道线的边缘断断续续,而且周边较多干扰。

    四、总结

           车道识别是无人驾驶中的重要技术,虽然本设计用的算法较为简单,而且识别效果也没有达到很好,但这却是学习其他高深复杂算法的基础和过渡。虽然以前就用过canny算法,但之前却没有很好的理解它。通过本本项目的学习,让我对canny算法和霍夫变换有了更深刻的理解。

     

    展开全文
  • 这个一个python实现的车道线识别程序,基于opencv库。压缩包内还附了测试用的图像和视频,适合进行python和图像处理学习。
  • opencv车道线检测

    万次阅读 多人点赞 2016-03-28 16:51:36
    车道线检测,需要完成以下功能: 图像裁剪:通过设定图像ROI区域,拷贝图像获得裁剪图像 反透视变换:用的是室外采集到的视频,没有对应的变换矩阵。所以建立二维坐标,通过四点映射的方法计算矩阵,进行反透视变化...

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

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

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

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

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

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

    这里写图片描述
    在道路损坏的情况下,由于阈值一定,基本上检测不出车道线。

    结论

       实现的功能:实现了车道线检测的基本功能,反透视变换矩阵实现了但效果不太理想,使用自己写的直线检测部分,车道线识别抗干扰能力较强。
    
       缺点:整个识别系统都是固定的参数,只能在特定的环境产生良好的效果。
    
       改进空间:提取全部关键参数,每次对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;
    }
    展开全文
  • C++ opencv车道线识别

    万次阅读 多人点赞 2018-11-23 11:44:51
    基于道路特征的车道线检测作为主流检测方法之一,主要是利用车道线与道路环境的物理特征差异进行后续图像的分割与处理,从而突出车道线特征,以实现车道线的检测。该方法复杂度较低,实时性较高,但容易受到道路环境...
  • 车道线识别/Opencv/传统方法

    千次阅读 2019-01-06 20:23:59
    车道检测(Advanced Lane Finding Project) 实现步骤: 使用提供的一组棋盘格图片计算相机校正矩阵...使用梯度阈值(gradient threshold),颜色阈值(color threshold)等处理图片得到清晰捕捉车道线的二进制图(binar...
  • 本课所讲的车道线检测来自于一个实际的项目,因为场景比较单一,而且硬件比较受限制,所以采用传统的图像处理方法来识别它们。 源图像 需求:要求识别出 黄色线道里外两条线, 一共有两根黄色车道线。 挑战性:...
  • Opencv-Python处理车道线检测

    千次阅读 2020-03-04 12:14:52
    去年对Opencv系统学习了一段时间,后面没有继续更新博客,但自己也有继续学习啦,哈哈,最近做了一个小项目,利用图像处理算法解决车道线检测。但目前自己深知这只是个基础的初级状态,还有很多不足的地方,后面会...
  • 一、效果展示 对车辆所在车道的车道线检测效果: 二、基本思路 ...在主函数中,我们需要读取视频,对每一帧都进行车道线检测处理。 int main() { VideoCapture cap("road.mp4"); int height ..
  • 车道线检测学习总结

    万次阅读 多人点赞 2018-09-14 11:31:38
    之前学习了一个非常酷炫的车道线检测项目:Advanced Lane Finding Project  现在写一个学习笔记,备注一下,方便以后复习:  项目总体流程如下: 第一步,采用棋盘对相机进行校正: 第二步,对图像进行...
  • 其中第一种方法是根据车道线与周围环境的物理特征差异进行图像处理,从而检测到车道线,该方法复杂度较低,实时性较高,但易受到道路环境的干扰,而且Hough变换的直线检测特质导致了该方法在道路曲率较大时的检测...
  • 传统的车道线识别大致的思路是在感兴趣区域中找到边缘像素然后用霍夫变换找到直线,直线可能有很多根因此用斜率过滤一些,之后将找到的直线分为左右两边的车道线,然后用多项式拟合直线的像素点。 传统车道线检测...
  • 高级车道线检测

    千次阅读 2018-10-05 21:35:39
    基于图像处理相关技术的高级车道线检测(可适用于弯道,车道线颜色不固定,路面阴影,亮光) pipeline: 1.校准摄像头的畸变,使拍摄照片能够较完整的反映3D世界的情况 2.对每一帧图片做透视转换(perspective ...
  • 车道线检测,就是在汽车行驶时通过汽车前方的摄像头捕捉到地面的图像(视频),通过Opencv对图片(视频)进行一系列处理后,可以在图片(视频)中标注出车道线,然后以此作为汽车自动驾驶时的安全行驶范围。...
  • 对摄像头拍摄的车道线视频进行提取,利用相应的图像处理知识进行视频的处理,提取相应的信息
  • (Python)识别和定位车道线

    千次阅读 2018-07-06 10:23:56
    一幅幅图片中去识别和定位车道线的位置 车道线有一个与柏油马路相比很明显的特征,那就是它是白色的 #importing some useful packages import matplotlib.pyplot as plt import matplotlib.image as mpimg ...
  • 基于python的车道线检测

    万次阅读 多人点赞 2018-07-12 21:48:10
    最近在开源社区下载了一份使用opencv在python环境中实现车道线检测的代码,研究了一下,终于有点儿看懂了,寻思着写下来,免得以后忘记了。 这个车道线检测项目原本是优达学城里无人驾驶课程中的第一个上手的项目,...
  • 车道线检测网络-LaneNet(论文简述)

    千次阅读 2019-03-27 14:08:13
    无论是辅助驾驶还是自动驾驶,车道线识别都是非常重要的。以前的算法需要很多人工的操作或者无法很好的适应不同的车道线场景。本文主要是使用semantic segmentation的方式来对车道线进行划分,可以适应变化的车道...
1 2 3 4 5 ... 20
收藏数 1,743
精华内容 697
关键字:

图像处理车道线识别