亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

opencv車道線檢測的實現方法

2020-01-26 13:25:43
字體:
來源:轉載
供稿:網友

車道線檢測,需要完成以下功能:

  • 圖像裁剪:通過設定圖像ROI區域,拷貝圖像獲得裁剪圖像
  • 反透視變換:用的是室外采集到的視頻,沒有對應的變換矩陣。所以建立二維坐標,通過四點映射的方法計算矩陣,進行反透視變化。后因ROI區域的設置易造成變換矩陣獲取困難和插值得到的透視圖效果不理想,故沒應用
  • 二值化:先變化為灰度圖,然后設定閾值直接變成二值化圖像。
  • 形態學濾波:對二值化圖像進行腐蝕,去除噪點,然后對圖像進行膨脹,彌補對車道線的腐蝕。
  • 邊緣檢測:canny變化、sobel變化和laplacian變化中選擇了效果比較好的canny變化,三者在代碼中均可以使用,canny變化效果稍微好一點。
  • 直線檢測:實現了兩種方法 1>使用opencv庫封裝好的霍夫直線檢測函數,在原圖對應區域用紅線描出車道線 2>自己寫一種直線檢測,在頭文件中,遍歷ROI區域進行特定角度范圍的直線檢測。兩種方法均可在視頻中體現,第一種方法運行效率較快。
  • 按鍵控制:空格暫停,其余鍵退出,方便調試和截圖。

實現的效果

 

在亮度良好道路條件良好的情況下,檢測車前區域的車道線實現比較成功,排除掉高速護欄的影響,而且原圖像還能完整體現。

 

車子行駛在高速公路大型彎道上,可以在一定角度范圍內認定車道線仍是直線,檢測出為直線。

 

車子切換過程中只有一根車道線被識別,但是穩定回變換車道后,實現效果良好。減速線為黃色,二值化是也被過濾,沒造成影響。

 

 

剛進入隧道時,攝像機光源基本處于高光狀態,拍攝亮度基本不變,二值化圖像時情況良好,噪聲比較多但是沒產生多大線狀影響;當攝像頭自動調節亮度,圖像亮度變低,二值化時同一閾值把車道線給過濾掉,造成無法識別車道線的現象。

 

在道路損壞的情況下,由于閾值一定,基本上檢測不出車道線。

結論

實現的功能:實現了車道線檢測的基本功能,反透視變換矩陣實現了但效果不太理想,使用自己寫的直線檢測部分,車道線識別抗干擾能力較強。

缺點:整個識別系統都是固定的參數,只能在特定的環境產生良好的效果。

改進空間:提取全部關鍵參數,每次對ROI圖像進行快速掃描更新參數,否則使用默認參數。例如,可以選擇每次5間隔取點,以像素最高點的85%作為該次二值化的閾值。從而做到動態車道線識別。

完整代碼

方法一

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

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美一级大片视频| 欧美天堂在线观看| 亚洲丝袜一区在线| 欧美裸体xxxx极品少妇软件| 久久久亚洲网站| 国产一区二区三区在线免费观看| 91精品视频免费观看| 亚洲国产精品国自产拍av秋霞| 在线日韩日本国产亚洲| 成人a级免费视频| 久久久噜噜噜久噜久久| 日韩电视剧在线观看免费网站| 97视频在线播放| 日韩av黄色在线观看| 国产精品扒开腿爽爽爽视频| 亚洲精品视频二区| 欧美大片在线免费观看| xvideos亚洲人网站| 欧美第一黄网免费网站| 九色成人免费视频| 黑人巨大精品欧美一区免费视频| 亚洲国产一区自拍| 欧美午夜激情小视频| 久久天堂av综合合色| 日韩电影在线观看免费| 成人福利网站在线观看| 色婷婷亚洲mv天堂mv在影片| 日韩av片永久免费网站| 97国产精品视频人人做人人爱| 色播久久人人爽人人爽人人片视av| 亚洲精品mp4| 精品亚洲aⅴ在线观看| 日本sm极度另类视频| 亚洲老板91色精品久久| 欧美尤物巨大精品爽| 亚洲区在线播放| 亚州欧美日韩中文视频| 在线免费观看羞羞视频一区二区| 日韩激情视频在线播放| 欧美高跟鞋交xxxxhd| 日韩在线播放av| 亚洲在线观看视频| 久久天天躁狠狠躁夜夜躁2014| 538国产精品一区二区免费视频| 国产精品香蕉av| 中文字幕日韩视频| 国产一区二区三区直播精品电影| 日本最新高清不卡中文字幕| 九九热这里只有精品免费看| 日韩av综合网| 亚洲天堂成人在线| 欧美裸体xxxx极品少妇| 久久全球大尺度高清视频| 久久免费视频这里只有精品| 亚洲女成人图区| 热99精品里视频精品| 色综合视频一区中文字幕| 亚洲欧美另类在线观看| 亚洲激情 国产| 亚洲精品国产综合久久| 中文字幕欧美日韩在线| 久久噜噜噜精品国产亚洲综合| 91精品国产综合久久香蕉| 最近2019中文字幕第三页视频| 精品性高朝久久久久久久| 国产精品igao视频| 精品自拍视频在线观看| 亚洲色图欧美制服丝袜另类第一页| 久久久久久91香蕉国产| 精品久久久久久久大神国产| 成年人精品视频| 欧美亚洲在线视频| 69av视频在线播放| 日韩在线观看av| 亚洲欧美日本另类| 国产成人精品国内自产拍免费看| 久久99热这里只有精品国产| 美女精品视频一区| 一区二区三区在线播放欧美| 国产精品青青在线观看爽香蕉| 91产国在线观看动作片喷水| 岛国av在线不卡| 88xx成人精品| 69视频在线免费观看| 国精产品一区一区三区有限在线| 欧美日韩在线看| 91午夜在线播放| 久久中文字幕视频| 欧美电影免费播放| 欧美性猛交xxxx| 欧美精品一本久久男人的天堂| 色999日韩欧美国产| 欧美尺度大的性做爰视频| 国产欧美最新羞羞视频在线观看| 亚洲精选中文字幕| 国产成人涩涩涩视频在线观看| 欧美成人免费全部| 欧美黑人xxxx| 色无极影院亚洲| 亚洲图片欧美午夜| 91高清视频在线免费观看| 亚洲人线精品午夜| 日韩视频在线观看免费| 久久免费福利视频| 欧美成人免费在线视频| 91欧美日韩一区| 免费99精品国产自在在线| 久久亚洲一区二区三区四区五区高| 亚洲福利视频网站| 神马久久久久久| 午夜精品久久久久久久白皮肤| 国模精品系列视频| 欧美激情高清视频| 91国在线精品国内播放| 久久久久久久国产| 国产香蕉一区二区三区在线视频| 国内外成人免费激情在线视频网站| 欧美自拍视频在线| 欧美日韩国产中字| 91在线无精精品一区二区| 7m精品福利视频导航| 26uuu久久噜噜噜噜| 91精品啪aⅴ在线观看国产| 亚洲第一网站免费视频| 日韩av网址在线| 国产a∨精品一区二区三区不卡| 亚洲999一在线观看www| 26uuu国产精品视频| 亚洲电影免费观看高清完整版在线| 日韩av综合网| 亚洲精品午夜精品| 国产精品热视频| 精品国产欧美一区二区五十路| 欧美午夜女人视频在线| 97涩涩爰在线观看亚洲| 日韩高清中文字幕| 国产亚洲成精品久久| 久久成人免费视频| 国产亚洲精品久久久久久777| 欧美极品少妇与黑人| 国产日韩欧美电影在线观看| 夜夜嗨av一区二区三区免费区| 国产成人亚洲综合| 国产精品第七十二页| 欧美视频13p| 91综合免费在线| 亚洲欧美日本伦理| 日韩免费看的电影电视剧大全| 日韩在线视频免费观看高清中文| 久久久久成人精品| 欧美激情精品久久久久久蜜臀| 成人欧美一区二区三区黑人孕妇| 热草久综合在线| 亚洲一区二区三区毛片| 久久手机精品视频| 在线午夜精品自拍| 久久免费视频网站| 亚洲区中文字幕| 欧美与欧洲交xxxx免费观看| 欧美wwwxxxx| 亚洲精品mp4| 在线精品91av| 国产精品极品美女在线观看免费| 久久91亚洲精品中文字幕|