標籤:

MATLAB 車道線識別

MATLAB 車道線識別

5 人贊了文章

merbar/CarND-Vehicle-Detection提供的方案是python的,我想用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 offend

上面的函數完成了二次多項式擬合的結果,其主要用於視頻的處理,所以不僅僅利用一張圖片來得到車道線的結果,而是利用了十幀圖像的平均結果。下圖是得出的左右車道線結果。

再將車輛線從俯視圖反透視變形和原始圖像疊加如下,最後給出一個視頻結果。

https://www.zhihu.com/video/975512591259381760

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默認為 $leftlbrack egin{array}{ccc}1 & 2 & 1\0 & 0 & 0\-1 % & -2 & -1end{array}
ight
brack$,強調水平方向的邊緣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);endfunction 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);endfunction 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);endfunction 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);endfunction binary_output = ch_thresh(ch, thresh) dim = size(ch); binary_output = zeros(dim,uint8); binary_output((ch > thresh(1)) & (ch <= thresh(2))) = uint8(255);endfunction result = comb_result(grad, hsl) dim = size(grad); result = zeros(dim,uint8); result(grad>0) = uint8(100); result(hsl>0) = uint8(255);end

順帶贊一下matab最新打code report真心漂亮,m和c對照,看著很清楚。


推薦閱讀:

顏色矩特徵提取Matlab源碼
【Matlab基礎】04. 自定義函數
MATLAB做圖像處理到社會上實用嗎?
用於數學建模 安裝matlab 2014 需要安裝哪些組件?
MATLAB學習筆記1:如何快速創建多個僅有數字變化變數名?

TAG:MATLAB |