基于 HoughLinesP函数应用

1.概率霍夫变换

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]
基于 HoughLinesP函数应用_第1张图片   基于 HoughLinesP函数应用_第2张图片

函数atan2()是求两点之间的角度(弧度),根据弧度转换角度公式:弧度变角度 180/π×弧度,最后就是斜率。

2.车道检测

1.车道线检测
#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]
基于 HoughLinesP函数应用_第3张图片
整体来说检测到效果一般。

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]


基于 HoughLinesP函数应用_第4张图片

效果不好。


3.IplImage 格式

#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  );  
     }  
}


基于 HoughLinesP函数应用_第5张图片






你可能感兴趣的:(Opencv常用函数介绍)