基于 HoughLinesP函数应用

来源:互联网 发布:大淘营淘宝复制专家 编辑:程序博客网 时间:2024/06/07 08:39

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 <opencv2/opencv.hpp>    #include<iostream>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<Vec4i> 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]<I[3]-90))//the height of two points should more than 90 pixels { line(src,Point(I[0],I[1]),Point(I[2],I[3]),Scalar(0,0,255),1,CV_AA); }        } //vector lines;      //HoughLinesP(canny,lines,1,CV_PI/180,20,200,1000);  //horizontal    //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[3]-I[1];              //double angle = atan2(double(dy),dx) * 180 /CV_PI;               //if (abs(angle) >=5) // reject near horizontal lines               //    continue;                              // if((I[0]>I[2]+90)||(I[0]<I[2]-90))//the height of two points should more than 90 pixels              // {                   //line(src,Point(I[0],I[1]),Point(I[2],I[3]),Scalar(0,0,255),2,CV_AA);               //}         // }imshow("src",src);   waitKey(0);return 0;  }  
  

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

2.车道检测

1.车道线检测
#include "stdafx.h"#include <opencv2/opencv.hpp>    #include<iostream>#include<time.h>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<Vec4i> 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]<I[3]-90)) { line(srcROI,Point(I[0],I[1]),Point(I[2],I[3]),Scalar(0,0,255),3,CV_AA);line(gray,Point(I[0],I[1]),Point(I[2],I[3]),Scalar(0,0,255),3,CV_AA); }        }imshow("frame",frame);imshow("gray",gray);/*stop=clock();cout<<"fps : "<<1.0/(((double)(stop-start))/ CLOCKS_PER_SEC)<<endl;*/        if(waitKey(10) == 27) //wait for 'esc' key press for 10 ms. If 'esc' key is pressed, break loop        {            cout<<"video paused!, press q to quit, any other key to continue"<<endl;            if(waitKey(0) == 'q')            {                cout << "terminated by user" << endl;                break;            }        }    }      return 0;  }  

整体来说检测到效果一般。

2.可简单的区分左右车道,并左右车道各保留一条车道线(2017.05.31改)。

// hough_fitline.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <opencv2/opencv.hpp>    #include<iostream>#include<time.h>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="<<frame.rows<<endl<<"srcROI.cols"<<frame.cols<<endl;circle(frame,Point(300,260),3,Scalar(255,0,0),3);    Canny(gray,canny,50,100);    //blur(gray,gray,Size(3,3));    //imshow("gray",gray);    imshow("canny",canny);    cout<<"Fnumber:"<<Fnumber<<endl;    vector<Vec4i> lines;    HoughLinesP(canny,lines,1,CV_PI/180,20,10,50);    //select approprivate lines acoording to the slopeint 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]<I[3]-90))//selecting the length of lane{if(I[0]<260||I[2]<260)//how to optimize the left and right lane{    j++;if(j==1) {    cout<<"left_Point(I[0],I[1])="<<Point(I[0],I[1])<<endl<<"left_Point(I[2],I[3])="<<Point(I[2],I[3])<<endl;    line(srcROI,Point(I[0],I[1]),Point(I[2],I[3]),Scalar(0,0,255),2,CV_AA);} }else{k++;if(k==1) {                    line(srcROI,Point(I[0],I[1]),Point(I[2],I[3]),Scalar(255,0,255),2,CV_AA);cout<<"right_Point(I[0],I[1])="<<Point(I[0],I[1])<<endl<<"right_Point(I[2],I[3])="<<Point(I[2],I[3])<<endl;}   } }        }imshow("frame",frame);if(Fnumber==30)imwrite("D://vvoo3//image.jpg",frame);//imshow("gray",gray);        if(waitKey(10) == 27) //wait for 'esc' key press for 10 ms. If 'esc' key is pressed, break loop        {            cout<<"video paused!, press q to quit, any other key to continue"<<endl;            if(waitKey(0) == 'q')            {                cout << "terminated by user" << endl;                break;            }        }    }      return 0;  }  



效果不好。


3.IplImage 格式

#include "stdafx.h"  #include<opencv2/opencv.hpp>  #include<cstdio>  #include<iostream>  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="<<warp_mat<<endl;              CvMat*inverse=cvCreateMat(3, 3, CV_32FC1);              cvInvert(warp_mat,inverse,CV_SVD);              //反透视变换              cvWarpPerspective(pCutFrame, pCutFrame, warp_mat);                            //cvShowImage("video2", pFrame);    #endif              //前景图转换为灰度图              cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);                         cvCanny(pCutFrImg, pCutFrImg, 50, 120);                       lines = cvHoughLines2(pCutFrImg,storage,CV_HOUGH_PROBABILISTIC,1,CV_PI/180,50,90,50);              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(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  );       }  }









0 0
原创粉丝点击