MATLAB车道线识别系统

MATLAB车道线识别系统

function imgout = lanemarker(img)

    global top bot

    persistent tform

    if isempty(tform)

        movingPoints = [203 720; 585 460; 695 460 ; 1127 720];

        fixedPoints = [320 720; 320 0; 960 0; 960 720];

        tform = fitgeotrans(movingPoints,fixedPoints,'projective');

        top = 220;

        bot = 12;

    end

    topview = view2top(img,tform);

    [flanel,flaner] = lanefinder(topview);

    hpic = size(topview,1);

    y = 1:hpic;

    y = y';

    xl = polyval(flanel,y);

    xr = polyval(flaner,y);

    dim = size(topview);

    dim = [dim,3];

    imref = imref2d(size(topview));

    lanel = reshape([xl';y'],1,[]);

    laner = [xr';y'];

    laner = fliplr(laner);

    laner = reshape(laner,1,[]);

    xpic = zeros(dim,'uint8');

    xpic = insertShape(xpic,'FilledPolygon',[lanel,laner],'Color',[0,255,0],'Opacity',0.3);

    xpic = imwarp(xpic,tform.invert,'OutputView',imref);

    img = imlincomb(1,img,1,xpic);

    xpic = zeros(dim,'uint8');

    xpic = insertShape(xpic,'Line',lanel,'LineWidth',20,'Color',[255,0,0],'Opacity',1);

    xpic = insertShape(xpic,'Line',laner,'LineWidth',20,'Color',[255,0,0],'Opacity',1);

    xpic = imwarp(xpic,tform.invert,'OutputView',imref);

    imgout = imlincomb(1,img,1,xpic);

end

上面是主程序view2top函数是将图转换为俯视图的函数,就是由左图变成右边的图。view2top函数由很多函数来完成工作,下面做一些必要说明。

function topview = view2top(img,tform)

    global top bot

    th_sobelx = [35, 100];

    th_sobely= [30, 255];

    th_mag = [30, 255];

    th_dir =  [0.7, 1.3];

    th_h = [10, 100];

    th_s = [85, 255];

    th_l = [0, 60];

    gradient_comb = gradient_combine(img, th_sobelx, th_sobely, th_mag, th_dir);

    hsl_comb = hsl_combine(img, th_h, th_s, th_l);

    dim = size(img);

    combined_result = zeros(dim(1:2));

    combined_result = uint8(combined_result);

    combined_result(top:end-bot,:,:) = comb_result(gradient_comb, hsl_comb);

    % figure(1)

    % imshow(combined_result)

    imref = imref2d(size(combined_result));

    topview = imwarp(combined_result,tform,'OutputView',imref);

%     topview = topview(top:end-bot,:,:);

end

上面的函数实现了由道路图像变成车道线俯视图的过程,该函数首先将图片中的车辆线提出出来,gradient_combine和hsl_combine通过图像梯度和hsl色彩模式来提出可能的车道线comb_result来进一步优化结果。

function gradient_comb = gradient_combine(img, th_x, th_y, th_mag, th_dir)

    global top bot

    R = img(top:end-bot,:,:);

    R = R(:,:,1);

    dim = size(R);

    sobelx = sobel_xy(R, 'x', th_x);

    sobely = sobel_xy(R, 'y', th_y);

    mag_img = mag_thresh(R, th_mag);

    dir_img = dir_thresh(R, th_dir);

    gradient_comb = zeros(dim,'uint8');

    gradient_comb(((sobelx > 0) & (mag_img > 0) & (dir_img > 0)) ...

        | ((sobelx > 0) & (sobely > 0))) = uint8(255);

end

上述函数实现了梯度阈值的过程,sobelx 给出水平阈值后的结果,sobely求出垂直梯度

阈值后的结果,mag_thresh给出梯度阈值后的结果,dir_img给出梯度方向阈值后的结果。下面给出了其中的各个结果。注意上面的阈值过程只作用于红色通道。

function hsl_comb = hsl_combine(img, th_h, th_s, th_l)

    global top bot

    hsl = img(top:end-bot,:,:);

    hsl = rgb2hsl(hsl);

    h = hsl(:,:,1);

    s = hsl(:,:,2);

    l = hsl(:,:,3);

    dim = size(h);

    h_th = ch_thresh(h, th_h);

    s_th = ch_thresh(s, th_s);

    l_th = ch_thresh(l, th_l);

    hsl_comb = zeros(dim,'uint8');

    hsl_comb(((s_th > 0) & (l_th == 0)) ...

        | ((s_th == 0) & (h_th > 0) & (l_th >0))) = uint8(255);

end

上面一段函数实现了hsl色彩通道阈值提取的过程,其结果如下图所示。色彩空间中的HSL、HSV、HSB有什么区别?提到了什么是hsl色彩空间,matlab只提供了转hsv的方法没有提供rgb转hsl色彩空间的方法,该函数在下方已经提供。

hsl阈值提出的结果

function result = comb_result(grad, hsl)

    dim = size(grad);

    result = zeros(dim,'uint8');

    result(grad>0) = uint8(100);

    result(hsl>0) = uint8(255);

end

上面的函数将两种结果进行整合,得出下面的结果。最后将下图做透视变形就得出最初提到的俯视图。

得到俯视图就可以利用滑窗拟合得到左右车道线的两次多项式表示结果。

function [flanel,flaner] = lanefinder(topview)

    persistent imgcounter avelanel avelaner flag

    hpic = size(topview,1);

    wpic = size(topview,2);

    if isempty(imgcounter)

        imgcounter = 0;

        flag = 0;

        avelanel = zeros(hpic,10);

        avelaner = zeros(hpic,10);

    end

    hist = sum(topview);

    midx = floor(wpic/2);

    [~,leftx] = max(hist(1:midx));

    [~,rightx] = max(hist(midx+1:end));

    rightx = rightx+midx;

    num = 9;

    hwin = floor(hpic/num);

    wwinhalf = 56;

    minpix = 50;

       

    [rowy,colx] = find(topview);

    leftlane = [];

    rightlane = [];

    for i = num:-1:1

        win_high = hwin*i;

        win_low = hwin*(i-1);

        vcount = rowy <= win_high & rowy > win_low;

        lcount = vcount & (colx <= leftx+wwinhalf & colx > leftx-wwinhalf);

        lpix = sum(lcount);

        rcount = vcount & (colx <= rightx+wwinhalf & colx > rightx-wwinhalf);

        rpix = sum(rcount);

        if lpix > minpix

            leftx = mean(colx(lcount));

            leftx = round(leftx);

        end

        if rpix > minpix

            rightx = mean(colx(rcount));

            rightx = round(rightx);

        end

        leftlane = [leftlane; colx(lcount),rowy(lcount)];

        rightlane = [rightlane; colx(rcount),rowy(rcount)];

    end

    

    flanel = polyfit(leftlane(:,2),leftlane(:,1),2);

    flaner = polyfit(rightlane(:,2),rightlane(:,1),2);

    t = 1:hpic;

    t = t';

    if flag == 0      

        imgcounter = imgcounter+1;

        avelanel(:,imgcounter) = polyval(flanel,t);

        avelaner(:,imgcounter) = polyval(flaner,t);

        if imgcounter == 10

            flag = 1;

        end

    else

        avelanel = [avelanel(:,2:end),polyval(flanel,t)];

        avelaner = [avelaner(:,2:end),polyval(flaner,t)];

        

        flanel = polyfit(t,mean(avelanel,2),2);

        flaner = polyfit(t,mean(avelaner,2),2);

    end

    % y = 1:hpic;

    % xl = flanel(y);

    % xr = flaner(y);

    % imshow(topview)

    % hold on

    % plot(xl,y);

    % plot(xr,y);

    % hold off

end

上面的函数完成了二次多项式拟合的结果,其主要用于视频的处理,所以不仅仅利用一张图片来得到车道线的结果,而是利用了十帧图像的平均结果。下图是得出的左右车道线结果。

再将车辆线从俯视图反透视变形和原始图像叠加如下,最后给出一个视频结果。

function hsl = rgb2hsl(rgb)

    dim = size(rgb);

    drgb = reshape(double(rgb)/255,[],3);%change range to 0-1

    mx = max(drgb,[],2);%max of the 3 colors

    mn = min(drgb,[],2);%min of the 3 colors

    L = (mx+mn)/2;%luminance is half of max value + min value

    S = zeros(size(L));

    % this set of matrix operations can probably be done as an addition...

    zeroidx = (mx==mn);

    S(zeroidx) = 0;

    lowlidx=L <= 0.5;

    calc = (mx-mn)./(mx+mn);

    idx = lowlidx & (~ zeroidx);

    S(idx) = calc(idx);

    hilidx = L > 0.5;

    calc = (mx-mn)./(2-(mx+mn));

    idx = hilidx & (~ zeroidx);

    S(idx) = calc(idx);

    hsv = rgb2hsv(rgb);

    hsv = reshape(hsv,[],3);

    H = hsv(:,1);

    hsl = reshape([H, S, L],dim);

    hsl = uint8(hsl*255);

end

% Sobel算子在Matlab默认为 $\left\lbrack \begin{array}{ccc}1 & 2 & 1\\0 & 0 & 0\\-1  

% & -2 & -1\end{array}\right\rbrack$,强调水平方向的边缘

function binary_output = sobel_xy(img, orient, thresh)

    h = fspecial('sobel'); % 垂直方向sobel算子,强调水平边

    dim = size(img);

    timg = double(img);

    if orient == 'x'

        abs_sobel = abs(imfilter(timg,fliplr(h')));

    else

        abs_sobel = abs(imfilter(timg,h));

    end

    scale_factor = max(abs_sobel(:)) / 255;

    timg = reshape(abs_sobel(:) / scale_factor,dim);

    scaled_sobel = uint8(timg);

    binary_output = zeros(dim,'uint8');

    binary_output((scaled_sobel > thresh(1)) & (scaled_sobel <= thresh(2))) = uint8(255);

end

function binary_output = mag_thresh(img, thresh)

    timg = double(img);

    dim = size(img);

    h = fspecial('sobel');

    sobelx = imfilter(timg,fliplr(h'));

    sobely = imfilter(timg,h);

    gradmag = sqrt(sobelx.^2 + sobely.^2);

    scale_factor = max(gradmag(:)) / 255;

    scaled_mag = reshape(gradmag(:) / scale_factor,dim);

    binary_output = zeros(dim,'uint8');

    binary_output((scaled_mag > thresh(1)) & (scaled_mag <= thresh(2))) = uint8(255);

end

function kernel = sobel_kernel(dim)

    half = floor(dim/2);

    t = [half:1:dim-2, dim-1, dim-2:-1:half];

    sobel = zeros(dim);

    for i = 1:half

        sobel(i,:) = t-i+1;

    end

    kernel = sobel-flipud(sobel);

end

function binary_output = dir_thresh(img, thresh)

    timg = double(img);

    dim = size(img);

  

    h = sobel_kernel(15);

    

    sobelx = imfilter(timg,h');

    sobely = imfilter(timg,h);

    absgraddir = atan(abs(sobely) ./ abs(sobelx));

    binary_output = zeros(dim,'uint8');

    binary_output((absgraddir > thresh(1)) & (absgraddir <= thresh(2))) = uint8(255);

end

function binary_output = ch_thresh(ch, thresh)

    dim = size(ch);

    binary_output = zeros(dim,'uint8');

    binary_output((ch > thresh(1)) & (ch <= thresh(2))) = uint8(255);

end

function result = comb_result(grad, hsl)

    dim = size(grad);

    result = zeros(dim,'uint8');

    result(grad>0) = uint8(100);

    result(hsl>0) = uint8(255);

end

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值