HoughLinesP能够检测出线端,即能够检测出图像中直线的两个端点,确切地定位图像中的直线。
void HoughLinesP(InputArray image,
OutputArray lines,
double rho,
double theta,
int threshold,
double minLineLength=0,
double maxLineGap=0 )
image为输入图像,要求是8位单通道图像
lines为输出的直线向量,每条线用4个元素表示,即直线的两个端点的4个坐标值
rho和theta分别为距离和角度的分辨率
threshold为阈值,即步骤3中的阈值
minLineLength为最小直线长度,在步骤5中要用到,即如果小于该值,则不被认为是一条直线
maxLineGap为最大直线间隙,在步骤4中要用到,即如果有两条线段是在一条直线上,但它们之间因为有间隙,所以被认为是两个线段,如果这个间隙大于该值,则被认为是两条线段,否则是一条。
首先来检测棋盘的竖直线段:
#include "stdafx.h"
#include
#include
using namespace cv;
using namespace std;
int main()
{
Mat src=imread("D://vvoo//qipan.jpg");
Mat gray,canny;
cvtColor(src,gray,CV_RGB2GRAY);
Canny(gray,canny,50,100);
//imshow("canny",canny);
vector lines;
HoughLinesP(canny,lines,1,CV_PI/180,20,20,600);
//select approprivate lines acoording to the slope
for (int i = 0;i < lines.size();i ++)
{
Vec4i I=lines[i];
int dx=I[2]-I[0];
int dy=I[2]-I[1];
double angle = atan2(double(dy),dx) * 180 /CV_PI;
if (abs(angle) <= 20) // reject near horizontal lines
continue;
if((I[1]>I[3]+90)||(I[1]=5) // reject near horizontal lines
// continue;
// if((I[0]>I[2]+90)||(I[0]
函数atan2()是求两点之间的角度(弧度),根据弧度转换角度公式:弧度变角度 180/π×弧度,最后就是斜率。
#include "stdafx.h"
#include
#include
#include
using namespace cv;
using namespace std;
clock_t start,stop;
int main()
{
Mat frame,gray,canny;
bool stop = false;
VideoCapture cap("D:\\vvoo1\\32.avi");//打开视频文件
double fps = cap.get(CV_CAP_PROP_FPS);
cout << "Input video's Frame per seconds : " << fps << endl;
if (!cap.isOpened())
{
cout << "读取视频有误" << endl;
return -1;
}
while (!stop)
{
start=clock();
cap >> frame;
Mat srcROI =frame(Range(250,frame.rows),Range(50,frame.cols-120));
cvtColor(srcROI,gray,CV_RGB2GRAY);
Canny(gray,canny,50,100);
//blur(gray,gray,Size(3,3));
//imshow("gray",gray);
imshow("canny",canny);
vector lines;
HoughLinesP(canny,lines,1,CV_PI/180,20,10,50);
//select approprivate lines acoording to the slope
for (int i = 0;i < lines.size();i ++)
{
Vec4i I=lines[i];
int dx=I[2]-I[0];
int dy=I[2]-I[1];
double angle = atan2(double(dy),dx) * 180 /CV_PI;
if (abs(angle) <= 20)
continue;
if((I[1]>I[3]+90)||(I[1]
2.可简单的区分左右车道,并左右车道各保留一条车道线(2017.05.31改)。
// hough_fitline.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include
#include
#include
using namespace cv;
using namespace std;
int main()
{
int Fnumber=0;
Mat frame,gray,canny;
bool stop = false;
VideoCapture cap("D:\\vvoo1\\32.avi");//打开视频文件
double fps = cap.get(CV_CAP_PROP_FPS);
cout << "Input video's Frame per seconds : " << fps << endl;
if (!cap.isOpened())
{
cout << "读取视频有误" << endl;
return -1;
}
while (!stop)
{
cap >> frame;
Fnumber++;
Mat srcROI =frame(Range(250,frame.rows),Range(50,frame.cols-120));
cvtColor(srcROI,gray,CV_RGB2GRAY);
//cout<<"srcROI.rows="< lines;
HoughLinesP(canny,lines,1,CV_PI/180,20,10,50);
//select approprivate lines acoording to the slope
int j=0,k=0;
for (int i = 0;i < lines.size();i ++)
{
Vec4i I=lines[i];
int dx=I[2]-I[0];
int dy=I[2]-I[1];
double angle = atan2(double(dy),dx) * 180 /CV_PI;
if (abs(angle) <= 20)
continue;
if((I[1]>I[3]+90)||(I[1]
效果不好。
#include "stdafx.h"
#include
#include
#include
using namespace std;
using namespace cv;
int cur_frame = 0; //用于指示g_capture的当前帧
int g_slider_position = 0;
void onTrackbarSlide(int pos);
CvCapture* pCapture = NULL;
int main()
{
IplImage* pFrame = NULL;
IplImage* pCutFrame = NULL;
IplImage* pCutFrImg = NULL;
//声明CvMemStorage和CvSeg指针
CvMemStorage* storage = cvCreateMemStorage();
CvSeq* lines = NULL;
//生成视频的结构
VideoWriter writer("result.avi", CV_FOURCC('M', 'J', 'P', 'G'), 25.0, Size(856, 480));
int nFrmNum = 0;
int CutHeight = 240;
cvNamedWindow("video", 1);
cvNamedWindow("BWmode", 1);
cvMoveWindow("video", 300, 0);
cvMoveWindow("BWmode", 300, 520);
if (!(pCapture = cvCaptureFromFile("D:\\vvoo1\\32.avi"))){
fprintf(stderr, "Can not open video file\n");
return -2;
}
//每次读取一桢的视频
while (pFrame = cvQueryFrame(pCapture))
{
int frames = (int)cvGetCaptureProperty(pCapture, CV_CAP_PROP_FRAME_COUNT); //以帧数来设置读入位置
if(frames != 0)
{
cvCreateTrackbar("Frames", //进度条名称
"video", //让进度条显示在最终结果的窗口
&g_slider_position,
frames,
onTrackbarSlide ); //调用一次onTrackbarSlide
}
//设置ROI裁剪图像
cvSetImageROI(pFrame, cvRect(0, CutHeight, pFrame->width, pFrame->height - CutHeight));
nFrmNum++;
//第一次要申请内存p
if (nFrmNum == 1){
pCutFrame = cvCreateImage(cvSize(pFrame->width, pFrame->height - CutHeight), pFrame->depth, pFrame->nChannels);
cvCopy(pFrame, pCutFrame, 0);
pCutFrImg = cvCreateImage(cvSize(pCutFrame->width, pCutFrame->height), IPL_DEPTH_8U, 1);
//转化成单通道图像再处理
cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
}
else{
//获得剪切图
cvCopy(pFrame, pCutFrame, 0);
#if 0 //反透视变换
//二维坐标下的点,类型为浮点
CvPoint2D32f srcTri[4], dstTri[4];
CvMat* warp_mat = cvCreateMat(3, 3, CV_32FC1);
//计算矩阵反射变换
srcTri[0].x = 10;
srcTri[0].y = 20;
srcTri[1].x = pCutFrame->width - 50;
srcTri[1].y = 0;
srcTri[2].x = 0;
srcTri[2].y = pCutFrame->height - 50;
srcTri[3].x = pCutFrame->width - 50;
srcTri[3].y = pCutFrame->height - 1;
//改变目标图像大小
dstTri[0].x = 0;
dstTri[0].y = 0;
dstTri[1].x = pCutFrame->width - 1;
dstTri[1].y = 0;
dstTri[2].x = 0;
dstTri[2].y = pCutFrame->height - 1;
dstTri[3].x = pCutFrame->width - 1;
dstTri[3].y = pCutFrame->height - 1;
//获得矩阵
cvGetPerspectiveTransform(srcTri, dstTri, warp_mat);
cout<<"warp_mat="<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(double(dy),dx) * 180 /CV_PI;
if (abs(angle) <= 10)
continue;
if (line[0].y > line[1].y + 90 || line[0].y < line[1].y - 90)
{
//if(line[0].x<260||line[1].x<260)
cvLine(pFrame,line[0],line[1],CV_RGB(255,0,0),2,CV_AA);
/*else
cvLine(pFrame,line[0],line[1],CV_RGB(255,0,255),2,CV_AA); */
}
}
//cvWarpPerspective(pCutFrame,pFrame,inverse);
//恢复ROI区域
cvResetImageROI(pFrame);
//写入视频流
writer << pFrame;
//显示图像
cvShowImage("video", pFrame);
//cvShowImage("BWmode", pCutFrImg);
//cvShowImage("video1", pCutFrame);
int temp = cvWaitKey(2);
if (temp == 32){
while (cvWaitKey() == -1);
}
else if (temp >= 0){
break;
}
}
}
//让进度条随着视频播放滚动
cur_frame = (int)cvGetCaptureProperty(pCapture,CV_CAP_PROP_POS_FRAMES);//提取当前帧
cvSetTrackbarPos("Frames","video",cur_frame);//设置进度条位置
//销毁窗口
cvDestroyWindow("video");
//cvDestroyWindow("BWmode");
//释放图像
cvReleaseImage(&pCutFrImg);
cvReleaseImage(&pCutFrame);
cvReleaseCapture(&pCapture);
return 0;
}
void onTrackbarSlide(int pos)
{
if (pos!=cur_frame)
{
//如果回调函数onTrackbarSlide(int pos)中当前的函数参数pos与全局变量相等,
//说明是滚动条自动移动造成的调用,不必重新设置g_capture的当前帧
cvSetCaptureProperty(
pCapture,
CV_CAP_PROP_POS_FRAMES, pos );
}
}