您好,登录后才能下订单哦!
本篇文章给大家分享的是有关opencv中怎么实现车道线检测功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
方法一
main.cpp
#include<cv.h>#include<cxcore.h>#include<highgui.h>#include"mylinedetect.h"#include<cstdio>#include<iostream>using namespace std;int main(){ //声明IplImage指针 IplImage* pFrame = NULL; IplImage* pCutFrame = NULL; IplImage* pCutFrImg = NULL; //声明CvCapture指针 CvCapture* pCapture = 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 = 310; //窗口命名 cvNamedWindow("video", 1); cvNamedWindow("BWmode", 1); //调整窗口初始位置 cvMoveWindow("video", 300, 0); cvMoveWindow("BWmode", 300, 520); //不能打开则退出 if (!(pCapture = cvCaptureFromFile("lane.avi"))){ fprintf(stderr, "Can not open video file\n"); return -2; } //每次读取一桢的视频 while (pFrame = cvQueryFrame(pCapture)){ //设置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 - 5; srcTri[1].y = 0; srcTri[2].x = 0; srcTri[2].y = pCutFrame->height - 1; srcTri[3].x = pCutFrame->width - 1; srcTri[3].y = pCutFrame->height - 1; //改变目标图像大小 dstTri[0].x = 0; dstTri[0].y = 0; dstTri[1].x = pCutFrImg->width - 1; dstTri[1].y = 0; dstTri[2].x = 0; dstTri[2].y = pCutFrImg->height - 1; dstTri[3].x = pCutFrImg->width - 1; dstTri[3].y = pCutFrImg->height - 1; //获得矩阵 cvGetPerspectiveTransform(srcTri, dstTri, warp_mat); //反透视变换 cvWarpPerspective(pCutFrame, pCutFrImg, warp_mat);#endif //前景图转换为灰度图 cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY); //二值化前景图 cvThreshold(pCutFrImg, pCutFrImg, 80, 255.0, CV_THRESH_BINARY); //进行形态学滤波,去掉噪音 cvErode(pCutFrImg, pCutFrImg, 0, 2); cvDilate(pCutFrImg, pCutFrImg, 0, 2); //canny变化 cvCanny(pCutFrImg, pCutFrImg, 50, 120); //sobel变化 //Mat pCutFrMat(pCutFrImg); //Sobel(pCutFrMat, pCutFrMat, pCutFrMat.depth(), 1, 1); //laplacian变化 //Laplacian(pCutFrMat, pCutFrMat, pCutFrMat.depth());#if 1 //0为下面的代码,1为上面的代码 #pragma region Hough直线检测 lines = cvHoughLines2(pCutFrImg, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 100, 15, 15); printf("Lines number: %d\n", lines->total); //画出直线 for (int i = 0; i<lines->total; i++){ CvPoint* line = (CvPoint*)cvGetSeqElem(lines, i); double k = ((line[0].y - line[1].y)*1.0 / (line[0].x - line[1].x)); cout<<"nFrmNum "<<nFrmNum<<" 's k = "<<k<<endl; if(!(abs(k)<0.1))//去掉水平直线 cvLine(pFrame, line[0], line[1], CV_RGB(255, 0, 0), 6, CV_AA); } #pragma endregion#else #pragma region mylinedetect Mat edge(pCutFrImg); vector<struct line> lines = detectLine(edge, 60); Mat pFrameMat(pFrame); drawLines(pFrameMat, lines); namedWindow("mylinedetect", 1); imshow("mylinedetect", pFrameMat); #pragma endregion#endif //恢复ROI区域 cvResetImageROI(pFrame); //写入视频流 writer << pFrame; //显示图像 cvShowImage("video", pFrame); cvShowImage("BWmode", pCutFrImg); //按键事件,空格暂停,其他跳出循环 int temp = cvWaitKey(2); if (temp == 32){ while (cvWaitKey() == -1); } else if (temp >= 0){ break; } } } //销毁窗口 cvDestroyWindow("video"); cvDestroyWindow("BWmode"); //释放图像 cvReleaseImage(&pCutFrImg); cvReleaseImage(&pCutFrame); cvReleaseCapture(&pCapture); return 0;}
mylinedetect.h
#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <iostream>#include <vector>#include <cmath>using namespace cv;using namespace std;const double pi = 3.1415926f;const double RADIAN = 180.0 / pi;struct line{ int theta; int r;};vector<struct line> detectLine(Mat &img, int threshold){ vector<struct line> lines; int diagonal = floor(sqrt(img.rows*img.rows + img.cols*img.cols)); vector< vector<int> >p(360, vector<int>(diagonal)); //统计数量 for (int j = 0; j < img.rows; j++) { for (int i = 0; i < img.cols; i++) { if (img.at<unsigned char>(j, i) > 0){ for (int theta = 0; theta < 360; theta++){ int r = floor(i*cos(theta / RADIAN) + j*sin(theta / RADIAN)); if (r < 0) continue; p[theta][r]++; } } } } //获得最大值 for (int theta = 0; theta < 360; theta++){ for (int r = 0; r < diagonal; r++){ int thetaLeft = max(0, theta - 1); int thetaRight = min(359, theta + 1); int rLeft = max(0, r - 1); int rRight = min(diagonal - 1, r + 1); int tmp = p[theta][r]; if (tmp > threshold && tmp > p[thetaLeft][rLeft] && tmp > p[thetaLeft][r] && tmp > p[thetaLeft][rRight] && tmp > p[theta][rLeft] && tmp > p[theta][rRight] && tmp > p[thetaRight][rLeft] && tmp > p[thetaRight][r] && tmp > p[thetaRight][rRight]){ struct line newline; newline.theta = theta; newline.r = r; lines.push_back(newline); } } } return lines;}void drawLines(Mat &img, const vector<struct line> &lines){ for (int i = 0; i < lines.size(); i++){ vector<Point> points; int theta = lines[i].theta; int r = lines[i].r; double ct = cos(theta / RADIAN); double st = sin(theta / RADIAN); //公式 r = x*ct + y*st //计算左边 int y = int(r / st); if (y >= 0 && y < img.rows){ Point p(0, y); points.push_back(p); } //计算右边 y = int((r - ct*(img.cols - 1)) / st); if (y >= 0 && y < img.rows){ Point p(img.cols - 1, y); points.push_back(p); } //计算上边 int x = int(r / ct); if (x >= 0 && x < img.cols){ Point p(x, 0); points.push_back(p); } //计算下边 x = int((r - st*(img.rows - 1)) / ct); if (x >= 0 && x < img.cols){ Point p(x, img.rows - 1); points.push_back(p); } //画线 cv::line(img, points[0], points[1], Scalar(255, 0, 0), 5, CV_AA); }}
方法二:
#include<cv.h>#include<cxcore.h>#include<highgui.h>#include<cstdio>#include<iostream>using namespace std;int main(){ //声明IplImage指针 IplImage* pFrame = NULL; IplImage* pCutFrame = NULL; IplImage* pCutFrImg = NULL; IplImage* pCutBkImg = NULL; //声明CvMat指针 CvMat* pCutFrameMat = NULL; CvMat* pCutFrMat = NULL; CvMat* pCutBkMat = NULL; //声明CvCapture指针 CvCapture* pCapture = NULL; //声明CvMemStorage和CvSeg指针 CvMemStorage* storage = cvCreateMemStorage(); CvSeq* lines = NULL; //当前帧数 int nFrmNum = 0; //裁剪的天空高度 int CutHeight = 250; //窗口命名 cvNamedWindow("video", 1); //cvNamedWindow("background", 1); cvNamedWindow("foreground", 1); //调整窗口初始位置 cvMoveWindow("video", 300, 30); cvMoveWindow("background", 100, 100); cvMoveWindow("foreground", 300, 370); //不能打开则退出 if (!(pCapture = cvCaptureFromFile("lane.avi"))){ fprintf(stderr, "Can not open video file\n"); return -2; } //每次读取一桢的视频 while (pFrame = cvQueryFrame(pCapture)){ //设置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); pCutBkImg = cvCreateImage(cvSize(pCutFrame->width, pCutFrame->height), IPL_DEPTH_8U, 1); pCutFrImg = cvCreateImage(cvSize(pCutFrame->width, pCutFrame->height), IPL_DEPTH_8U, 1); pCutBkMat = cvCreateMat(pCutFrame->height, pCutFrame->width, CV_32FC1); pCutFrMat = cvCreateMat(pCutFrame->height, pCutFrame->width, CV_32FC1); pCutFrameMat = cvCreateMat(pCutFrame->height, pCutFrame->width, CV_32FC1); //转化成单通道图像再处理 cvCvtColor(pCutFrame, pCutBkImg, CV_BGR2GRAY); cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY); //转换成矩阵 cvConvert(pCutFrImg, pCutFrameMat); cvConvert(pCutFrImg, pCutFrMat); cvConvert(pCutFrImg, pCutBkMat); } else{ //获得剪切图 cvCopy(pFrame, pCutFrame, 0); //前景图转换为灰度图 cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY); cvConvert(pCutFrImg, pCutFrameMat); //高斯滤波先,以平滑图像 cvSmooth(pCutFrameMat, pCutFrameMat, CV_GAUSSIAN, 3, 0, 0.0); //当前帧跟背景图相减 cvAbsDiff(pCutFrameMat, pCutBkMat, pCutFrMat); //二值化前景图 cvThreshold(pCutFrMat, pCutFrImg, 35, 255.0, CV_THRESH_BINARY); //进行形态学滤波,去掉噪音 cvErode(pCutFrImg, pCutFrImg, 0, 1); cvDilate(pCutFrImg, pCutFrImg, 0, 1); //更新背景 cvRunningAvg(pCutFrameMat, pCutBkMat, 0.003, 0); //pCutBkMat = cvCloneMat(pCutFrameMat); //将背景转化为图像格式,用以显示 //cvConvert(pCutBkMat, pCutBkImg); cvCvtColor(pCutFrame, pCutBkImg, CV_BGR2GRAY); //canny变化 cvCanny(pCutFrImg, pCutFrImg, 50, 100); #pragma region Hough检测 lines = cvHoughLines2(pCutFrImg, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 100, 30, 15); printf("Lines number: %d\n", lines->total); //画出直线 for (int i = 0; i<lines->total; i++){ CvPoint* line = (CvPoint* )cvGetSeqElem(lines, i); cvLine(pCutFrame, line[0], line[1], CV_RGB(255, 0, 0), 6, CV_AA); } #pragma endregion //显示图像 cvShowImage("video", pCutFrame); cvShowImage("background", pCutBkImg); cvShowImage("foreground", pCutFrImg); //按键事件,空格暂停,其他跳出循环 int temp = cvWaitKey(2); if (temp == 32){ while (cvWaitKey() == -1); } else if (temp >= 0){ break; } } //恢复ROI区域(多余可去掉) cvResetImageROI(pFrame); } //销毁窗口 cvDestroyWindow("video"); cvDestroyWindow("background"); cvDestroyWindow("foreground"); //释放图像和矩阵 cvReleaseImage(&pCutFrImg); cvReleaseImage(&pCutBkImg); cvReleaseImage(&pCutFrame); cvReleaseMat(&pCutFrameMat); cvReleaseMat(&pCutFrMat); cvReleaseMat(&pCutBkMat); cvReleaseCapture(&pCapture); return 0;}
以上就是opencv中怎么实现车道线检测功能,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。