您的位置:首页 > 其它

车道检测源码分析系列(三)

2015-05-17 11:01 441 查看
下面看一个出自国外某教授的基于OpenCVSharp的车辆视觉框架,虽然包含车道检测和车辆识别,但源程序仅100行左右,非常精巧。

算法描述

检测部分的步骤很经典,是比较通用的步骤:

将图像上半部分无关内容截掉,设定ROI

转为灰度图

Canny算子提取边缘

Hough检测直线

通过直线角度位置信息筛选出车道线,标记到图上

效果如下图:



源程序

有博客将其中车道检测部分转为了OpenCV2,以下的源码转自该博客。原文链接

另外,国外有基于此程序进行扩展的,后续会介绍。

OpenCVSharp版本

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

using OpenCvSharp;

namespace LaneDetection
{
class Program
{
[STAThread]
static void Main()
{
CvCapture cap = CvCapture.FromFile("test1.mp4");
CvWindow w = new CvWindow("Lane Detection");
CvWindow canny = new CvWindow("Canny");
IplImage src, gray, dstCanny, halfFrame, smallImg;
CvMemStorage storage = new CvMemStorage();
CvSeq lines;

while (CvWindow.WaitKey(10) < 0)
{
src = cap.QueryFrame();
halfFrame = new IplImage(new CvSize(src.Size.Width / 2, src.Size.Height / 2), BitDepth.U8, 3);
Cv.PyrDown(src, halfFrame, CvFilter.Gaussian5x5);

gray = new IplImage(src.Size, BitDepth.U8, 1);
dstCanny = new IplImage(src.Size, BitDepth.U8, 1);
storage.Clear();

// Crop off top half of image since we're only interested in the lower portion of the video
int halfWidth = src.Width / 2;
int halfHeight = src.Height / 2;
int startX = halfWidth - (halfWidth / 2);
src.SetROI(new CvRect(0, halfHeight - 0, src.Width - 1, src.Height - 1));

gray.SetROI(src.GetROI());
dstCanny.SetROI(src.GetROI());

src.CvtColor(gray, ColorConversion.BgrToGray);
Cv.Smooth(gray, gray, SmoothType.Gaussian, 5, 5);
Cv.Canny(gray, dstCanny, 50, 200, ApertureSize.Size3);
canny.Image = dstCanny;
storage.Clear();
lines = dstCanny.HoughLines2(storage, HoughLinesMethod.Probabilistic, 1, Math.PI / 180, 50, 50, 100);

for (int i = 0; i < lines.Total; i++)
{
CvLineSegmentPoint elem = lines.GetSeqElem<CvLineSegmentPoint>(i).Value;

int dx = elem.P2.X - elem.P1.X;
int dy = elem.P2.Y - elem.P1.Y;
double angle = Math.Atan2(dy, dx) * 180 / Math.PI;

if (Math.Abs(angle) <= 10)
continue;

if (elem.P1.Y > elem.P2.Y + 50  || elem.P1.Y < elem.P2.Y -50 )
{
src.Line(elem.P1, elem.P2, CvColor.Red, 2, LineType.AntiAlias, 0);
}
}
src.ResetROI();
storage.Clear();
w.Image = src;
}
}
}
}


OpenCV2版本

#include "stdafx.h"
#include <highgui.h>
#include <cv.h>
#include <math.h>

using namespace cv;
using namespace std;

#define INF 99999999
CvCapture* g_capture = NULL;

int g_slider_pos = 0 ;
int frame_count = 0;
CvSeq* lines;

int main(int argc,char* argv[])
{
cvNamedWindow( "show");
g_capture=cvCreateFileCapture( "D:\\road.avi");
IplImage* frame;
while(1)
{
CvMemStorage* storage = cvCreateMemStorage();
frame=cvQueryFrame(g_capture);

//set the ROI of the original image
int x = 0,y = frame->height/2;
int width = frame->width,height = frame->height/2;

if(!frame)
break;

cvSetImageROI(frame,cvRect(x,y,width,height));
IplImage* gray = cvCreateImage(cvGetSize(frame),8,1);
cvCvtColor(frame,gray,CV_BGR2GRAY);

cvCanny(gray,gray,50,100);
cvShowImage("canny",gray);
cvSmooth(gray,gray,CV_GAUSSIAN,3,1,0);

//Hough
lines = cvHoughLines2(gray,storage,CV_HOUGH_PROBABILISTIC,1,CV_PI/180,50,90,50);

//select approprivate lines acoording to the slope
for (int i = 0;i < lines->total;i ++)
{
double k =INF;
CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
int dx = line[1].x - line[0].x;
int dy = line[1].x - line[0].y;
double angle = atan2(dy,dx) * 180 /CV_PI;
if (abs(angle) <= 10)
continue;
if (line[0].y > line[1].y + 50 || line[0].y < line[1].y - 50)
{
cvLine(frame,line[0],line[1],CV_RGB(255,0,0),2,CV_AA);
}
}
cvResetImageROI(frame);
cvShowImage( "show",frame);
char c = cvWaitKey(33);
if(c==27)
break;
}
cvReleaseCapture(&g_capture);
cvDestroyWindow( "show");
return 0;
}


参考资料

国外教授的博客-OpenCVSharp版本中文翻译

国内某博客-改写OpenCV2版本
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息