基于 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); } } //vectorlines; //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
- 基于 HoughLinesP函数应用
- opencv houghlinesp函数详解
- HoughLinesP函数用法示例
- opencv的HoughLinesP( )函数
- HoughLinesP( )函数详解
- OpenCV---HoughLinesP函数的使用
- OpenCV 霍夫圆变换 HoughLinesP( )函数
- HoughLinesP函数(概率检测直线)
- opencv3累计概率霍夫变换-HoughLinesP函数
- OpenCV3.0 Examples学习笔记(12)-houghlines.cpp-通过HoughLinesP函数实现直线检测
- opencv中霍夫变换cv::HoughLinesP函数的使用方法和形参说明
- HoughLinesP opencv for java
- 霍夫找線(HoughLines、HoughLinesP)
- 基于视图的应用开发--关键函数的实现
- OpenCV Tutorial: 霍夫找線(HoughLines、HoughLinesP)
- opencv使用-HoughLinesP and HoughLines
- Opencv2.4.9源码分析——HoughLinesP
- Opencv2.4.9源码分析——HoughLinesP
- 简单练习—字符串反转
- 第二届山东ACM省赛 Crack Mathmen
- 欢迎使用CSDN-markdown编辑器
- Weex 中别具匠心的 JS Framework
- js获取url参数
- 基于 HoughLinesP函数应用
- 缩小浏览器窗口右边出现空白
- WPFSample示例分析
- CXF webService客户端调用方法
- 应用部署weblogic 报错Unsupported major.minor version 51.0的解决过程
- 电子表格控件Aspose.Cells V17.4.0发布 | 新增重要功能
- 深入理解sdram之基本特性的理解
- java实现二叉树的建立,前中后序遍历,层次遍历,深度,节点个数等
- HashMap与ConcurrentHashMap的区别