//---------------------车道线检测-------------------------//
/*可以处理摄像头,也可以处理视频文件*/
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
#include <string>
#include <cv.h>
#include <math.h>
using namespace cv;
using namespace std;
CvCapture* g_capture = NULL;
IplImage* PreProcessImg = NULL;
CvPoint point1, point2, point3, pointend, pointtemp;
CvPoint pointmeet;//相交点
vector<CvPoint> points;
vector<CvPoint> pointsleft;
vector<CvPoint> pointsright;
//结构体1,左侧的线,右侧的线
struct line
{
CvPoint pointbottom;
CvPoint pointtop;
}lineleft, lineright;
//结构体2
struct greycount
{
uchar grey;
int count;
};
//大津阈值,车道从背景中分离出来
void ImproveOTSU(IplImage* image, IplImage* image2)
{
//int lc = cvRound((image->height / 2) + 1);
//cvSetImageROI(image, cvRect(0, lc, image->width, image->height));
//如果只对下半幅图像做大津阈值,效果不好
//cvThreshold(image, image, 80, 255, CV_THRESH_BINARY);//速度慢,与OSTU差100ms
//cvThreshold(image, image2, 180, 235, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);//BINARY能检测出视频3-2
cvThreshold(image, image2, 0, 255, CV_THRESH_OTSU);//改变阈值没效果
//cvResetImageROI(image);
//cvCopy(image, image2);
}
//改进的hough变换检测车道
int Hough(IplImage* image, float* tabSin, float *tabCos, int *accum, int numrho, int &predistance1, int &preangle1, int &predistance2, int &preangle2)
{
int r, angle1 = 1, angle2 = 1, distance1 = 0, distance2 = 0, n = 0;
long j;
int angelstart1 = 40;
int angleend1 = 70;
int anglestart2 = 110;
int angleend2 = 160;
if (preangle1 != 0)
{
angelstart1 = preangle1 - 5;
angleend1 = preangle1 + 5;
}
if (preangle2 != 0)
{
anglestart2 = preangle2 - 5;
angleend2 = preangle2 + 5;
}
int step = image->widthStep / sizeof(uchar);
uchar *data0 = (uchar *)image->imageData;
for (int i = image->height / 2; i < image->height; i++)
{
for (j = 0; j < image->width; j++)
{
if (data0[i*step + j] == 255)//??
{
for (n = angelstart1; n < angleend1; n++)//40--70
{
r = cvRound(j * tabCos[n] + i * tabSin[n]);
r += (numrho - 1) / 2;
accum[(n + 1) * (numrho + 2) + r + 1]++;
}
for (n = anglestart2; n < angleend2; n++)//110--160
{
r = cvRound(j * tabCos[n] + i * tabSin[n]);
r += (numrho - 1) / 2;
accum[(n + 1) * (numrho + 2) + r + 1]++;
}
}
}
}
//printf("preangle1,preangle2:%d %d\n ",preangle1,preangle2);
//找出数值最大的小格
int numbermax1 = 30, numbermax2 = 30;
for (r = 0; r < numrho; r++)//angle1\angle2 ????
{
for (n = 40; n < 70; n++)
{
int base = (n + 1) * (numrho + 2) + r + 1;
if (accum[base] > numbermax1)
{
numbermax1 = accum[base];
angle1 = n;
distance1 = cvRound(r - (numrho - 1)*0.5f);
}
}
for (n = 110; n<160; n++)
{
int base = (n + 1) * (numrho + 2) + r + 1;
if (accum[base] > numbermax2)
{
numbermax2 = accum[base];
angle2 = n;
distance2 = cvRound(r - (numrho - 1)*0.5f);
}
}
}
//printf("angle1,angle2, distance1,distance2:%d %d %d %d\n",angle1, angle2,distance1,distance2);
//if( distance1 || distance2 )
//{
if (angle1 == 0)
{
lineleft.pointbottom.x = 0;
lineleft.pointbottom.y = 0;
lineleft.pointtop.x = 0;
lineleft.pointtop.y = 0;
}
if (angle2 == 0)
{
lineright.pointbottom.x = 0;
lineright.pointbottom.y = 0;
lineright.pointtop.x = 0;
lineright.pointtop.y = 0;
}
//???????
if (angle1 < 90)
{
if ((lineleft.pointbottom.y = (int)(distance1 / tabSin[angle1])) > image->height)//此处分母tabSin[angle1]为零
{
lineleft.pointbottom.x = (int)((distance1 - image->height * tabSin[angle1]) / tabCos[angle1]);
lineleft.pointbottom.y = image->height;
}
else
lineleft.pointbottom.x = 0;
if ((lineleft.pointtop.x = (int)(distance1 / tabCos[angle1])) > image->width)
{
lineleft.pointtop.x = image->width;
lineleft.pointtop.y = (int)((distance1 - image->width*tabCos[angle1]) / tabSin[angle1]);
}
else
lineleft.pointtop.y = 0;
}
if (angle2 > 90 /* && angle2 < 180*/)
{
if ((lineright.pointtop.y = int(distance2 / tabSin[angle2])) < 0)
{
lineright.pointtop.y = 0;
lineright.pointtop.x = int(distance2 / tabCos[angle2]);
}
else
lineright.pointtop.x = 0;
if (((lineright.pointbottom.x = (int)((distance2 - image->height *tabSin[angle2]) / tabCos[angle2])) > image->width))
{
lineright.pointbottom.x = image->width;
lineright.pointbottom.y = int((distance2 - image->width*tabCos[angle2]) / tabSin[angle2]);
}
else
lineright.pointbottom.y = image->height;
}
predistance1 = distance1;
preangle1 = angle1;
predistance2 = distance2;
preangle2 = angle2;
return angle1;
//}
}
//找出直线的相交点
CvPoint findmeetpoint(IplImage* image, float* tabSin, float *tabCos, int angleleft, int angleright)
{
//float tanA = tabCos[angleleft] / tabSin[angleleft];
//float tanB = tabCos[angleright] / tabSin[angleright] ;
float tanA = -tabCos[angleleft] / tabSin[angleleft];//分母为零,赋值为1也不行
float tanB = -tabCos[angleright] / tabSin[angleright];
CvPoint pointmeet;
pointmeet.x = (lineright.pointbottom.y - lineleft.pointbottom.y + lineleft.pointbottom.x*tanA - lineright.pointbottom.x*tanB) / (tanA - tanB);
pointmeet.y = (pointmeet.x - lineleft.pointbottom.x)*tanA + lineleft.pointbottom.y;
return pointmeet;
}
//判断出弯曲的方向,0代表没有弯曲,1代表左弯,2代表右弯
int finddirection(IplImage* image, float* tabSin, float *tabCos, int angleleft, int angleright)
{
int i = 0, j = 0;
int i1 = 0, j1 = 0;
int step = image->widthStep / sizeof(uchar); //imagestep为排列的图像行大小
uchar *data0 = (uchar *)image->imageData; //指向排列的图像数据
uchar *data1 = (uchar *)image->imageData;
int numwhite = 0, numblack = 0;
int num = 0;
//float tanA = tabCos[angleleft] / tabSin[angleleft];
//float tanB = tabCos[angleright] / tabSin[angleright] ;
float tanA = -tabCos[angleleft] / tabSin[angleleft];
float tanB = -tabCos[angleright] / tabSin[angleright];
pointmeet.x = 0;
pointmeet.y = 0;
pointmeet = findmeetpoint(image, tabSin, tabCos, angleleft, angleright);
//找出直线与曲线的交点
//左车道
//偏离点的确定。
for (i = lineleft.pointbottom.y; i > pointmeet.y; i--)
{
j = float((i - lineleft.pointbottom.y)) / tanA + lineleft.pointbottom.x;//什么公式??
if (data0[i*step + j] == 255)//????
{
//printf( "pointmeet1:%f\n", (float)pointmeet.y );
pointtemp.x = j;
pointtemp.y = i;
numwhite++;
}
if (data0[i*step + j] != 255 && numwhite > 20)
{
pointsleft.push_back(pointtemp);
numblack++;
break;
}
if (numblack>3)
pointsleft.push_back(pointtemp);
}
numwhite = 0;
for (i = lineright.pointbottom.y; i > pointmeet.y; i--)
{
j = float((i - lineright.pointbottom.y)) / tanB + lineright.pointbottom.x;
//printf("%f", data1[i*step]);
if (data1[i*step + j] > 200) //200改大或改小都不行,>改成==
{
//printf("pointmeet2:%f\n", (int)pointmeet.y );
pointtemp.x = j;
pointtemp.y = i;
numwhite++;
}
if (data1[i*step + j] != 255 && numwhite>20)
{
pointsright.push_back(pointtemp);
numblack++;
break;
}
if (numblack>3)
pointsright.push_back(pointtemp);
}
///////////////////////////////////////////////
if (pointsleft.size() == 0 || pointsright.size() == 0)
{
pointtemp.y = 0;
pointtemp.x = 0;
pointsright.clear();
pointsleft.clear();
pointsright.push_back(pointtemp);
pointsleft.push_back(pointtemp);
return 0;
}
////////////////////////////////////////////////////
//结合左右车道进行直线与曲线切点的校正
int tempy = (pointsleft.back().y<pointsright.back().y) ? pointsleft.back().y : pointsright.back().y;
for (i = tempy; i<pointsleft.back().y; i++)
{
j = float((i - lineleft.point
- 1
- 2
前往页