/*车道线检测,思路:
首先 ,对图像进行平滑处理,然后Canny边缘检测,使用Hough画直线
郭洪成
2015.3.31
*/
#include<cv.h>
#include<highgui.h>
#include<math.h>
#include<vector>
#include<string.h>
#include <atlstr.h>
#include <io.h>
//自定义LINE结构体
//由pt0,pt1两个点连接成一段线段
struct LINE
{
CvPoint pt0;
CvPoint pt1;
LINE( CvPoint pta, CvPoint ptb )
{
pt0 = pta;
pt1 = ptb;
} //带参构造函数LINE( ),用于构造一个LINE
LINE()
{
pt0.x = pt0.y = 0;
pt1.x = pt1.y = 0;
} //无参构造函数,原点(0,0)
};
// 得到两条平行线之间的距离
double GetDisOfParallelLines( LINE line0, LINE line1 )
{
CvPoint midPoint = cvPoint( (line0.pt0.x + line0.pt1.x)/2, (line0.pt0.y + line0.pt1.y)/2 ); // 中点
double x_dis = line1.pt0.x - line1.pt1.x;
if ( x_dis == 0.0 ) return fabs((double)(midPoint.x - line0.pt1.x)); // 如果line1 垂直x轴
double a = (line1.pt0.y - line1.pt1.y) / x_dis;
double b = line1.pt0.y - (line1.pt0.x * a);
return fabs(a * midPoint.x - midPoint.y + b) / sqrt(a * a + 1);
}
//得到一条直线的tan率,也就是对边/邻边
double GetTanOfLine( LINE line )
{
double x_dis = line.pt0.x - line.pt1.x;
if ( x_dis == 0.0 ) return 10e9;
return (line.pt0.y - line.pt1.y) / x_dis;
}
//判断两条直线是否是平行线,通过球每条直线的tan率来比较
bool IsParallelLines( LINE line0, LINE line1 )
{
#define LIMIT (1.1547 / 3) //近似平行线的斜率之差的范围
double angleTan0 = GetTanOfLine( line0 );
double angleTan1 = GetTanOfLine( line1 );
if ( fabs(angleTan0 - angleTan1) < (double)LIMIT )
{
return 1;
}
return 0;
}
//遍历文件夹文件的辅助函数
bool GetPicDirSetInFolder(CString strFindPath, std::vector<CString> &vecPathSet)
{
WIN32_FIND_DATA wfd;
HANDLE hf = FindFirstFileA(strFindPath, &wfd);
if (INVALID_HANDLE_VALUE != hf)
{
vecPathSet.push_back(wfd.cFileName);
while (FindNextFileA(hf, &wfd))
{
vecPathSet.push_back(wfd.cFileName);
}
FindClose(hf);
}
return true;
}
//计算一根线段的长度
double fGetLen(LINE fLine )
{
return sqrt( (fLine.pt0.x - fLine.pt1.x) * (fLine.pt0.x - fLine.pt1.x) +
( fLine.pt0.y - fLine.pt1.y) *( fLine.pt0.y - fLine.pt1.y) ) ;
}
//获取所输入直线最长的一根
LINE fGetMaxLine(LINE fLine1 , LINE fLine2)
{
double fDisOfL1 = sqrt( (fLine1.pt0.x - fLine1.pt1.x) * (fLine1.pt0.x - fLine1.pt1.x) +
( fLine1.pt0.y - fLine1.pt1.y) *( fLine1.pt0.y - fLine1.pt1.y) );
double fDisOfL2 = sqrt( (fLine2.pt0.x - fLine2.pt1.x) * (fLine2.pt0.x - fLine2.pt1.x) +
( fLine2.pt0.y - fLine2.pt1.y) *( fLine2.pt0.y - fLine2.pt1.y) );
if ( fDisOfL1 > fDisOfL2 )
return fLine1;
else return fLine2;
}
//主函数,里面的whiteVec和yellowVec是可以使用的
int main()
{
IplImage* fSrcImage ;
IplImage *fTempImage = NULL ;
IplImage *fTempImage1 = NULL ;
CvSize fcvSize ; //图片大小,包含width , heigth
double fScale = 0.5 ; //设置图片的缩放倍数
//遍历文件夹所有图片
std::vector<CString> vecPathSet;
CString findPath = "D:\\DEMO\\photoAlex\\rightwindow\\*.jpg";
CString folder = "D:\\DEMO\\photoAlex\\rightwindow\\";
CString procFolder = "D:\\DEMO\\photo\\result\\";
CString procFolder1 = "D:\\DEMO\\photo\\result1\\";
GetPicDirSetInFolder(findPath, vecPathSet);
for (int iPic = 0; iPic < vecPathSet.size(); iPic ++)
{
CString path = folder;
// load_img_path 存储的是打开文件夹
path.Append(vecPathSet[iPic]);
CString save_path_result = procFolder;
CString save_path_result1 = procFolder1;
//save_img_path存储的是保存文件夹
save_path_result.Append(vecPathSet[iPic]);
save_path_result1.Append(vecPathSet[iPic]);
//save_path_result.Append(a);
// ProcessImage(path, save_img_path); // 进行图像处理
fSrcImage= cvLoadImage(path , 0) ; // 载入文件夹下的所有图片
IplImage *fSrcImage1= cvLoadImage(path , 1) ;
IplImage *fSrcImage2= cvLoadImage(path , 1) ;//彩图
IplImage* fDstImage=cvCreateImage(cvGetSize(fSrcImage) , 8 , 1) ;
IplImage* fColorImage=cvCreateImage(cvGetSize(fSrcImage) , 8 , 3) ;
//分配空间,默认64KB
CvMemStorage* storage=cvCreateMemStorage(0) ;
CvSeq* fLine1=0 ; // 指向所检测到的线的序列的第一条...
//cvThreshold(fSrcImage, fSrcImage, 80, 255.0, CV_THRESH_BINARY);
//进行形态学滤波,膨胀腐蚀,去掉噪音
cvErode(fSrcImage, fSrcImage, 0, 2);
cvDilate(fSrcImage, fSrcImage, 0, 2);
/*cvErode(fSrcImage2, fSrcImage2, 0, 2);
cvDilate(fSrcImage2, fSrcImage2, 0, 2);*/
//WashOffTheColor(fSrcImage2);
/*cvErode(fSrcImage2, fSrcImage2, 0, 3);
cvDilate(fSrcImage2, fSrcImage2, 0, 3);*/
//首先对源图像进行边缘检测 , 结果以灰度图显示,
cvCanny(fSrcImage , fDstImage , 20 , 150 , 3) ;
//cvSobel(fSrcImage,fDstImage,0,1,5);
cvCvtColor(fDstImage , fColorImage , CV_GRAY2BGR) ;
cvNamedWindow("Canny" , 1) ;
cvShowImage("Canny" , fDstImage) ;
//通过Hough直线检测返回给fLine1
//Hough直线返回的不是一条直线,而是一条直线上面的两个点,起点和终点
fLine1=cvHoughLines2(//返回一个指向CvSeq序列结构的的指针,
fDstImage , //要进行霍夫检测的图像,必须是8位的,
storage , //保存结果位置的指针,
CV_HOUGH_PROBABILISTIC ,
1 , //这两个参数都是用来设置直线的分辨率的
CV_PI/180 ,
100, //一个阈值
20 ,
15 //表示支持所返回的直线的点的数量
) ;
int fIndex ; //fIndex为直线的索引
std::vector<LINE> fVector1;
std::vector<LINE> fVector2;
std::vector<LINE> fVector3;//存储连接之后的线段
std::vector<LINE> fVector4;//存放的是左边1/4的线段
std::vector<LINE> whiteVec;
std::vector<LINE> yellowVec;
for(fIndex=0 ; fIndex<fLine1->total ; fIndex++) // ← 遍历每一条霍夫直线
{
//↓ ↓ ↓ ↓ 获得第fIndex条霍夫直线
CvPoint* line=(CvPoint*)cvGetSeqElem(fLine1 , fIndex) ;
//↓ ↓ ↓ ↓ 对每条霍夫直线的两个端点画线段
cvLine(fSrcImage1 , line[0] , line[1] , CV_RGB(21 , 168 , 146) , 1 , CV_AA) ;
//↓ ↓ ↓ ↓ 对每条画好的直线,存储到vector里面
fVector1.push_back(LINE(line[0] , line[1]));
//LINE fLine2 = LINE(line[0] , line[1]);
}
//↓ ↓ ↓ ↓ 遍历vector里面的所有线段,使用双重循环,一条线段和其他所有的线段比较
//↓ ↓ ↓ ↓ 判断是否是相距为零的平行线,是的话,就连接两条直线
for(int i =0; i<fVector1.size() ;i++ )
{
/*if(sqrt( (fVector1[i].pt0.x - fVector1[i].pt1.x) * (fVector1[i].pt0.x-fVector1[i].pt1.x) +
(fVector1[i].pt0.y - fVector1[i].pt1.y) * (fVector1[i].pt0.y - fVector1[i].pt1.y) ) < 200 )
continue;*/
if( sqrt( (fVector1[i].pt0.x - fVector1[i].pt1.x) * (fVector1[i].pt0.x-fVector1[i].pt1.x) +
(fVector1[i].pt0.y - fVector1[i].pt1.y) * (fVector1[i].pt0.y - fVector1[i].pt1.y) ) < 150 ||
fabs(GetTanOfLine(fVector1[i]) ) <= 1.7 || fabs(GetTanOfLine(fVector1[i]) )>11 ) //← 对所有的直线判断,角度小于60°就舍弃
continue;
for(int j = i+1 ; j<fVector1.size() ;j++)
{
//if(GetDisOfParallelLines(fVector1[i] , fVector1[j]) == 0 )
if( IsParallelLines(fVector1[i] , fVector1[j]) == true && GetDisOfParallelLines(fVector1[i] , fVector1[j]) < 2 )
{
cvLine(fSrcImage1 , fVector1[i].pt0 , fVector1[j].pt1 , CV_RGB(168 , 21 , 43) , 3 , 8) ;
fVector2.push_back(LINE (fVector1[i].pt0 , fVector1[j].pt1) );//将连接后的直线放进fVector2里面
}
}
}
//筛选连接之后的线
for (int i = 0 ; i<fVector2.size() ; i++)
{
//int max = 0 ;
if(fabs(GetTanOfLine(fVector2[i]) ) <=2.1)//倾斜角度过小,则排除,
continue;
for(int j = i; j<fVector2.size() ;j++) {
if( IsParallelLines(fVector2[i] , fVector2[j]) == true
&& GetDisOfParallelLines(fVector2[i] , fVector2[j]) <2 )
{
LINE fLine3 = fGetMaxLine(fVector2[i] , fVector2[j]);
fVector3.push_back(fLine3);//fVector3里面存放的是比较之后的线段
cvLine(fSrcImage1 , fLine3.pt0 , fLine3.pt1 , CV_RGB(255 , 0, 0) , 6 , CV_AA) ;
}
}
}
//筛选连接之后的线
double max = 0 ;
int flag = 1;
for( int i = 0 ; i<fVector2.size() ; i++)
{
double max = fGetLen(fVector2[i]) ;
for(int j = i ; j<fVector2.size(); j++)
if( fabs(GetTanOfLine(fVector2[i]) )>2.1
&& IsParallelLines(fVector2[i] , fVector2[j]) == true
&& GetDisOfParallelLines(fVector2[i] , fVector2[j]) <2
&& fGetLen(fVector2[j]) > max
)
{
flag = j ;
max = fGetLen(fVector2[j]) ;
}
fVector3.push_back( fVector2[flag] );
cvLine( fSrcImage1 , fVector3[flag].pt0 , fVector3[flag].pt1 ,CV_RGB(225,0,0) , 6 , CV_AA );
}
int width = (fSrcImage1->width)/4 ;
//int height = fSrcImage1->height;
LINE fLine4;
int max = 0 , max1 = 0;
int flag = -1 , flag1 = -1;
//检测白线最长
for(int i = 0 ; i < fVector3.size() ; i++)//遍历fVec4里面的所有线段
{
if(fVector3[i].pt0.x > width
|| fVector3[i].pt1.x > width
|| GetTanOfLine( fVector3[i] ) > 0
)
continue;
if ( fGetLen(fVector3[i]) > max )
{
max = fGetLen(fVector3[i]);
flag = i;
}
}
if(flag > -1)
{
cvLine(fSrcImage1 , fVector3[flag].pt0 , fVector3[flag].pt1 , CV_RGB( 240 , 240 , 240 ) , 6 , CV_AA);
whiteVec.push_back(fVector3[flag]);
}
///检测白线第二长//
for(int i = 0 ; i < fVector3.size() ; i++)//遍历fVec4里面的所有线段
{
if( fVector3[i].pt0.x > width || fVector3[i].pt1.x >width
|| i==flag
||GetDisOfParallelLines(fVector3[i] , fVector3[flag]) <3
|| GetTanOfLine( fVector3[i] ) > 0
/*||GetDisOfParallelLines(fVector3[i] , fVector3[flag]) >11*/
)
continue;
if ( fGetLen(fVector3[i]) > max1 )
{
max1 = fGetLen(fVector3[i]);
flag1 = i;
}
}
if(flag1 > -1)
{
cvLine(fSrcImage1 , fVector3[flag1].pt0 , fVector3[flag1].pt1 , CV_RGB( 240 , 240 , 240 ) , 6 , CV_AA);
whiteVec.push_back(fVector3[flag1]);
}
/检测黄线最长
int ywidth =( fSrcImage1->width )/ 2;
int yflag = -1 , yflag1 =-1;
int ymax = 0 , ymax1 =0;
for(int i = 0 ; i < fVector3.size() ; i++)//遍历fVec4里面的所有线段
{
if(fVector3[i].pt0.x < ywidth
|| fVector3[i].pt1.x < ywidth
|| GetTanOfLine( fVector3[i] ) < 0
)
continue;
if ( fGetLen(fVector3[i]) > ymax )
{
ymax = fGetLen(fVector3[i]);
yflag = i;
}
}
if(yflag > -1)
{
cvLine(fSrcImage1 , fVector3[yflag].pt0 , fVector3[yflag].pt1 , CV_RGB( 255 , 255 , 0 ) , 6 , CV_AA);
yellowVec.push_back(fVector3[yflag]);
}
///检测黄线第二长//
for(int i = 0 ; i < fVector3.size() ; i++)//遍历fVec4里面的所有线段
{
if( fVector3[i].pt0.x < ywidth
|| fVector3[i].pt1.x < ywidth
|| i==yflag
||GetDisOfParallelLines(fVector3[i] , fVector3[yflag]) <3
|| GetTanOfLine( fVector3[i] ) < 0
/*||GetDisOfParallelLines(fVector3[i] , fVector3[yflag]) >11*/
)
continue;
if ( fGetLen(fVector3[i]) > ymax1 )
{
ymax1 = fGetLen(fVector3[i]);
yflag1 = i;
}
}
if(yflag1 > -1)
{
cvLine(fSrcImage1 , fVector3[yflag1].pt0 , fVector3[yflag1].pt1 , CV_RGB( 255 , 255 , 0 ) , 6 , CV_AA);
yellowVec.push_back(fVector3[yflag1]);
}
//设置图片缩放倍数
fcvSize.width = fColorImage->width * fScale ;
fcvSize.height = fColorImage->height * fScale ;
fTempImage = cvCreateImage(fcvSize , fColorImage->depth , fColorImage->nChannels) ;
fTempImage1 = cvCreateImage(fcvSize , fSrcImage->depth , fSrcImage->nChannels) ;
IplImage *fTempImage2 = cvCreateImage(fcvSize , fDstImage->depth , fDstImage->nChannels) ;
cvResize(fColorImage , fTempImage , CV_INTER_AREA) ;
cvResize(fSrcImage , fTempImage1 , CV_INTER_AREA) ;
cvResize(fDstImage , fTempImage2 , CV_INTER_AREA) ;
/*cvNamedWindow("fColorImage" , 1) ;
cvShowImage("fColorImage" , fColorImage) ; */
/*cvNamedWindow("fSrcImage" , 1) ;
cvShowImage("fSrcImage" , fTempImage1) ;
cvNamedWindow("HOUGH" , 1) ;
cvShowImage("HOUGH" , fTempImage) ;
cvNamedWindow("Canny" , 1) ;
cvShowImage("Canny" , fTempImage2) ;*/
//fLoad1.Append(fLoad3);
// cvSaveImage(save_path_result, fSrcImage1);
cvSaveImage(save_path_result1, fSrcImage1);
//cvSaveImage(save_path_result1, fSrcImage2);
cvReleaseImage(&fSrcImage2);
cvReleaseImage(&fSrcImage1);
cvReleaseImage(&fSrcImage);
cvWaitKey(0) ;
}
return 0 ;
}
首先 ,对图像进行平滑处理,然后Canny边缘检测,使用Hough画直线
郭洪成
2015.3.31
*/
#include<cv.h>
#include<highgui.h>
#include<math.h>
#include<vector>
#include<string.h>
#include <atlstr.h>
#include <io.h>
//自定义LINE结构体
//由pt0,pt1两个点连接成一段线段
struct LINE
{
CvPoint pt0;
CvPoint pt1;
LINE( CvPoint pta, CvPoint ptb )
{
pt0 = pta;
pt1 = ptb;
} //带参构造函数LINE( ),用于构造一个LINE
LINE()
{
pt0.x = pt0.y = 0;
pt1.x = pt1.y = 0;
} //无参构造函数,原点(0,0)
};
// 得到两条平行线之间的距离
double GetDisOfParallelLines( LINE line0, LINE line1 )
{
CvPoint midPoint = cvPoint( (line0.pt0.x + line0.pt1.x)/2, (line0.pt0.y + line0.pt1.y)/2 ); // 中点
double x_dis = line1.pt0.x - line1.pt1.x;
if ( x_dis == 0.0 ) return fabs((double)(midPoint.x - line0.pt1.x)); // 如果line1 垂直x轴
double a = (line1.pt0.y - line1.pt1.y) / x_dis;
double b = line1.pt0.y - (line1.pt0.x * a);
return fabs(a * midPoint.x - midPoint.y + b) / sqrt(a * a + 1);
}
//得到一条直线的tan率,也就是对边/邻边
double GetTanOfLine( LINE line )
{
double x_dis = line.pt0.x - line.pt1.x;
if ( x_dis == 0.0 ) return 10e9;
return (line.pt0.y - line.pt1.y) / x_dis;
}
//判断两条直线是否是平行线,通过球每条直线的tan率来比较
bool IsParallelLines( LINE line0, LINE line1 )
{
#define LIMIT (1.1547 / 3) //近似平行线的斜率之差的范围
double angleTan0 = GetTanOfLine( line0 );
double angleTan1 = GetTanOfLine( line1 );
if ( fabs(angleTan0 - angleTan1) < (double)LIMIT )
{
return 1;
}
return 0;
}
//遍历文件夹文件的辅助函数
bool GetPicDirSetInFolder(CString strFindPath, std::vector<CString> &vecPathSet)
{
WIN32_FIND_DATA wfd;
HANDLE hf = FindFirstFileA(strFindPath, &wfd);
if (INVALID_HANDLE_VALUE != hf)
{
vecPathSet.push_back(wfd.cFileName);
while (FindNextFileA(hf, &wfd))
{
vecPathSet.push_back(wfd.cFileName);
}
FindClose(hf);
}
return true;
}
//计算一根线段的长度
double fGetLen(LINE fLine )
{
return sqrt( (fLine.pt0.x - fLine.pt1.x) * (fLine.pt0.x - fLine.pt1.x) +
( fLine.pt0.y - fLine.pt1.y) *( fLine.pt0.y - fLine.pt1.y) ) ;
}
//获取所输入直线最长的一根
LINE fGetMaxLine(LINE fLine1 , LINE fLine2)
{
double fDisOfL1 = sqrt( (fLine1.pt0.x - fLine1.pt1.x) * (fLine1.pt0.x - fLine1.pt1.x) +
( fLine1.pt0.y - fLine1.pt1.y) *( fLine1.pt0.y - fLine1.pt1.y) );
double fDisOfL2 = sqrt( (fLine2.pt0.x - fLine2.pt1.x) * (fLine2.pt0.x - fLine2.pt1.x) +
( fLine2.pt0.y - fLine2.pt1.y) *( fLine2.pt0.y - fLine2.pt1.y) );
if ( fDisOfL1 > fDisOfL2 )
return fLine1;
else return fLine2;
}
//主函数,里面的whiteVec和yellowVec是可以使用的
int main()
{
IplImage* fSrcImage ;
IplImage *fTempImage = NULL ;
IplImage *fTempImage1 = NULL ;
CvSize fcvSize ; //图片大小,包含width , heigth
double fScale = 0.5 ; //设置图片的缩放倍数
//遍历文件夹所有图片
std::vector<CString> vecPathSet;
CString findPath = "D:\\DEMO\\photoAlex\\rightwindow\\*.jpg";
CString folder = "D:\\DEMO\\photoAlex\\rightwindow\\";
CString procFolder = "D:\\DEMO\\photo\\result\\";
CString procFolder1 = "D:\\DEMO\\photo\\result1\\";
GetPicDirSetInFolder(findPath, vecPathSet);
for (int iPic = 0; iPic < vecPathSet.size(); iPic ++)
{
CString path = folder;
// load_img_path 存储的是打开文件夹
path.Append(vecPathSet[iPic]);
CString save_path_result = procFolder;
CString save_path_result1 = procFolder1;
//save_img_path存储的是保存文件夹
save_path_result.Append(vecPathSet[iPic]);
save_path_result1.Append(vecPathSet[iPic]);
//save_path_result.Append(a);
// ProcessImage(path, save_img_path); // 进行图像处理
fSrcImage= cvLoadImage(path , 0) ; // 载入文件夹下的所有图片
IplImage *fSrcImage1= cvLoadImage(path , 1) ;
IplImage *fSrcImage2= cvLoadImage(path , 1) ;//彩图
IplImage* fDstImage=cvCreateImage(cvGetSize(fSrcImage) , 8 , 1) ;
IplImage* fColorImage=cvCreateImage(cvGetSize(fSrcImage) , 8 , 3) ;
//分配空间,默认64KB
CvMemStorage* storage=cvCreateMemStorage(0) ;
CvSeq* fLine1=0 ; // 指向所检测到的线的序列的第一条...
//cvThreshold(fSrcImage, fSrcImage, 80, 255.0, CV_THRESH_BINARY);
//进行形态学滤波,膨胀腐蚀,去掉噪音
cvErode(fSrcImage, fSrcImage, 0, 2);
cvDilate(fSrcImage, fSrcImage, 0, 2);
/*cvErode(fSrcImage2, fSrcImage2, 0, 2);
cvDilate(fSrcImage2, fSrcImage2, 0, 2);*/
//WashOffTheColor(fSrcImage2);
/*cvErode(fSrcImage2, fSrcImage2, 0, 3);
cvDilate(fSrcImage2, fSrcImage2, 0, 3);*/
//首先对源图像进行边缘检测 , 结果以灰度图显示,
cvCanny(fSrcImage , fDstImage , 20 , 150 , 3) ;
//cvSobel(fSrcImage,fDstImage,0,1,5);
cvCvtColor(fDstImage , fColorImage , CV_GRAY2BGR) ;
cvNamedWindow("Canny" , 1) ;
cvShowImage("Canny" , fDstImage) ;
//通过Hough直线检测返回给fLine1
//Hough直线返回的不是一条直线,而是一条直线上面的两个点,起点和终点
fLine1=cvHoughLines2(//返回一个指向CvSeq序列结构的的指针,
fDstImage , //要进行霍夫检测的图像,必须是8位的,
storage , //保存结果位置的指针,
CV_HOUGH_PROBABILISTIC ,
1 , //这两个参数都是用来设置直线的分辨率的
CV_PI/180 ,
100, //一个阈值
20 ,
15 //表示支持所返回的直线的点的数量
) ;
int fIndex ; //fIndex为直线的索引
std::vector<LINE> fVector1;
std::vector<LINE> fVector2;
std::vector<LINE> fVector3;//存储连接之后的线段
std::vector<LINE> fVector4;//存放的是左边1/4的线段
std::vector<LINE> whiteVec;
std::vector<LINE> yellowVec;
for(fIndex=0 ; fIndex<fLine1->total ; fIndex++) // ← 遍历每一条霍夫直线
{
//↓ ↓ ↓ ↓ 获得第fIndex条霍夫直线
CvPoint* line=(CvPoint*)cvGetSeqElem(fLine1 , fIndex) ;
//↓ ↓ ↓ ↓ 对每条霍夫直线的两个端点画线段
cvLine(fSrcImage1 , line[0] , line[1] , CV_RGB(21 , 168 , 146) , 1 , CV_AA) ;
//↓ ↓ ↓ ↓ 对每条画好的直线,存储到vector里面
fVector1.push_back(LINE(line[0] , line[1]));
//LINE fLine2 = LINE(line[0] , line[1]);
}
//↓ ↓ ↓ ↓ 遍历vector里面的所有线段,使用双重循环,一条线段和其他所有的线段比较
//↓ ↓ ↓ ↓ 判断是否是相距为零的平行线,是的话,就连接两条直线
for(int i =0; i<fVector1.size() ;i++ )
{
/*if(sqrt( (fVector1[i].pt0.x - fVector1[i].pt1.x) * (fVector1[i].pt0.x-fVector1[i].pt1.x) +
(fVector1[i].pt0.y - fVector1[i].pt1.y) * (fVector1[i].pt0.y - fVector1[i].pt1.y) ) < 200 )
continue;*/
if( sqrt( (fVector1[i].pt0.x - fVector1[i].pt1.x) * (fVector1[i].pt0.x-fVector1[i].pt1.x) +
(fVector1[i].pt0.y - fVector1[i].pt1.y) * (fVector1[i].pt0.y - fVector1[i].pt1.y) ) < 150 ||
fabs(GetTanOfLine(fVector1[i]) ) <= 1.7 || fabs(GetTanOfLine(fVector1[i]) )>11 ) //← 对所有的直线判断,角度小于60°就舍弃
continue;
for(int j = i+1 ; j<fVector1.size() ;j++)
{
//if(GetDisOfParallelLines(fVector1[i] , fVector1[j]) == 0 )
if( IsParallelLines(fVector1[i] , fVector1[j]) == true && GetDisOfParallelLines(fVector1[i] , fVector1[j]) < 2 )
{
cvLine(fSrcImage1 , fVector1[i].pt0 , fVector1[j].pt1 , CV_RGB(168 , 21 , 43) , 3 , 8) ;
fVector2.push_back(LINE (fVector1[i].pt0 , fVector1[j].pt1) );//将连接后的直线放进fVector2里面
}
}
}
//筛选连接之后的线
for (int i = 0 ; i<fVector2.size() ; i++)
{
//int max = 0 ;
if(fabs(GetTanOfLine(fVector2[i]) ) <=2.1)//倾斜角度过小,则排除,
continue;
for(int j = i; j<fVector2.size() ;j++) {
if( IsParallelLines(fVector2[i] , fVector2[j]) == true
&& GetDisOfParallelLines(fVector2[i] , fVector2[j]) <2 )
{
LINE fLine3 = fGetMaxLine(fVector2[i] , fVector2[j]);
fVector3.push_back(fLine3);//fVector3里面存放的是比较之后的线段
cvLine(fSrcImage1 , fLine3.pt0 , fLine3.pt1 , CV_RGB(255 , 0, 0) , 6 , CV_AA) ;
}
}
}
//筛选连接之后的线
double max = 0 ;
int flag = 1;
for( int i = 0 ; i<fVector2.size() ; i++)
{
double max = fGetLen(fVector2[i]) ;
for(int j = i ; j<fVector2.size(); j++)
if( fabs(GetTanOfLine(fVector2[i]) )>2.1
&& IsParallelLines(fVector2[i] , fVector2[j]) == true
&& GetDisOfParallelLines(fVector2[i] , fVector2[j]) <2
&& fGetLen(fVector2[j]) > max
)
{
flag = j ;
max = fGetLen(fVector2[j]) ;
}
fVector3.push_back( fVector2[flag] );
cvLine( fSrcImage1 , fVector3[flag].pt0 , fVector3[flag].pt1 ,CV_RGB(225,0,0) , 6 , CV_AA );
}
int width = (fSrcImage1->width)/4 ;
//int height = fSrcImage1->height;
LINE fLine4;
int max = 0 , max1 = 0;
int flag = -1 , flag1 = -1;
//检测白线最长
for(int i = 0 ; i < fVector3.size() ; i++)//遍历fVec4里面的所有线段
{
if(fVector3[i].pt0.x > width
|| fVector3[i].pt1.x > width
|| GetTanOfLine( fVector3[i] ) > 0
)
continue;
if ( fGetLen(fVector3[i]) > max )
{
max = fGetLen(fVector3[i]);
flag = i;
}
}
if(flag > -1)
{
cvLine(fSrcImage1 , fVector3[flag].pt0 , fVector3[flag].pt1 , CV_RGB( 240 , 240 , 240 ) , 6 , CV_AA);
whiteVec.push_back(fVector3[flag]);
}
///检测白线第二长//
for(int i = 0 ; i < fVector3.size() ; i++)//遍历fVec4里面的所有线段
{
if( fVector3[i].pt0.x > width || fVector3[i].pt1.x >width
|| i==flag
||GetDisOfParallelLines(fVector3[i] , fVector3[flag]) <3
|| GetTanOfLine( fVector3[i] ) > 0
/*||GetDisOfParallelLines(fVector3[i] , fVector3[flag]) >11*/
)
continue;
if ( fGetLen(fVector3[i]) > max1 )
{
max1 = fGetLen(fVector3[i]);
flag1 = i;
}
}
if(flag1 > -1)
{
cvLine(fSrcImage1 , fVector3[flag1].pt0 , fVector3[flag1].pt1 , CV_RGB( 240 , 240 , 240 ) , 6 , CV_AA);
whiteVec.push_back(fVector3[flag1]);
}
/检测黄线最长
int ywidth =( fSrcImage1->width )/ 2;
int yflag = -1 , yflag1 =-1;
int ymax = 0 , ymax1 =0;
for(int i = 0 ; i < fVector3.size() ; i++)//遍历fVec4里面的所有线段
{
if(fVector3[i].pt0.x < ywidth
|| fVector3[i].pt1.x < ywidth
|| GetTanOfLine( fVector3[i] ) < 0
)
continue;
if ( fGetLen(fVector3[i]) > ymax )
{
ymax = fGetLen(fVector3[i]);
yflag = i;
}
}
if(yflag > -1)
{
cvLine(fSrcImage1 , fVector3[yflag].pt0 , fVector3[yflag].pt1 , CV_RGB( 255 , 255 , 0 ) , 6 , CV_AA);
yellowVec.push_back(fVector3[yflag]);
}
///检测黄线第二长//
for(int i = 0 ; i < fVector3.size() ; i++)//遍历fVec4里面的所有线段
{
if( fVector3[i].pt0.x < ywidth
|| fVector3[i].pt1.x < ywidth
|| i==yflag
||GetDisOfParallelLines(fVector3[i] , fVector3[yflag]) <3
|| GetTanOfLine( fVector3[i] ) < 0
/*||GetDisOfParallelLines(fVector3[i] , fVector3[yflag]) >11*/
)
continue;
if ( fGetLen(fVector3[i]) > ymax1 )
{
ymax1 = fGetLen(fVector3[i]);
yflag1 = i;
}
}
if(yflag1 > -1)
{
cvLine(fSrcImage1 , fVector3[yflag1].pt0 , fVector3[yflag1].pt1 , CV_RGB( 255 , 255 , 0 ) , 6 , CV_AA);
yellowVec.push_back(fVector3[yflag1]);
}
//设置图片缩放倍数
fcvSize.width = fColorImage->width * fScale ;
fcvSize.height = fColorImage->height * fScale ;
fTempImage = cvCreateImage(fcvSize , fColorImage->depth , fColorImage->nChannels) ;
fTempImage1 = cvCreateImage(fcvSize , fSrcImage->depth , fSrcImage->nChannels) ;
IplImage *fTempImage2 = cvCreateImage(fcvSize , fDstImage->depth , fDstImage->nChannels) ;
cvResize(fColorImage , fTempImage , CV_INTER_AREA) ;
cvResize(fSrcImage , fTempImage1 , CV_INTER_AREA) ;
cvResize(fDstImage , fTempImage2 , CV_INTER_AREA) ;
/*cvNamedWindow("fColorImage" , 1) ;
cvShowImage("fColorImage" , fColorImage) ; */
/*cvNamedWindow("fSrcImage" , 1) ;
cvShowImage("fSrcImage" , fTempImage1) ;
cvNamedWindow("HOUGH" , 1) ;
cvShowImage("HOUGH" , fTempImage) ;
cvNamedWindow("Canny" , 1) ;
cvShowImage("Canny" , fTempImage2) ;*/
//fLoad1.Append(fLoad3);
// cvSaveImage(save_path_result, fSrcImage1);
cvSaveImage(save_path_result1, fSrcImage1);
//cvSaveImage(save_path_result1, fSrcImage2);
cvReleaseImage(&fSrcImage2);
cvReleaseImage(&fSrcImage1);
cvReleaseImage(&fSrcImage);
cvWaitKey(0) ;
}
return 0 ;
}