欧美大屁股bbbbxxxx,狼人大香伊蕉国产www亚洲,男ji大巴进入女人的视频小说,男人把ji大巴放进女人免费视频,免费情侣作爱视频

歡迎來到入門教程網(wǎng)!

C語言

當(dāng)前位置:主頁 > 軟件編程 > C語言 >

opencv車道線檢測(cè)的實(shí)現(xiàn)方法

來源:本站原創(chuàng)|時(shí)間:2020-01-10|欄目:C語言|點(diǎn)擊: 次

車道線檢測(cè),需要完成以下功能:

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

實(shí)現(xiàn)的效果

 

在亮度良好道路條件良好的情況下,檢測(cè)車前區(qū)域的車道線實(shí)現(xiàn)比較成功,排除掉高速護(hù)欄的影響,而且原圖像還能完整體現(xiàn)。

 

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

 

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

 

 

剛進(jìn)入隧道時(shí),攝像機(jī)光源基本處于高光狀態(tài),拍攝亮度基本不變,二值化圖像時(shí)情況良好,噪聲比較多但是沒產(chǎn)生多大線狀影響;當(dāng)攝像頭自動(dòng)調(diào)節(jié)亮度,圖像亮度變低,二值化時(shí)同一閾值把車道線給過濾掉,造成無法識(shí)別車道線的現(xiàn)象。

 

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

結(jié)論

實(shí)現(xiàn)的功能:實(shí)現(xiàn)了車道線檢測(cè)的基本功能,反透視變換矩陣實(shí)現(xiàn)了但效果不太理想,使用自己寫的直線檢測(cè)部分,車道線識(shí)別抗干擾能力較強(qiáng)。

缺點(diǎn):整個(gè)識(shí)別系統(tǒng)都是固定的參數(shù),只能在特定的環(huán)境產(chǎn)生良好的效果。

改進(jìn)空間:提取全部關(guān)鍵參數(shù),每次對(duì)ROI圖像進(jìn)行快速掃描更新參數(shù),否則使用默認(rèn)參數(shù)。例如,可以選擇每次5間隔取點(diǎn),以像素最高點(diǎn)的85%作為該次二值化的閾值。從而做到動(dòng)態(tài)車道線識(shí)別。

完整代碼

方法一

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;
  //生成視頻的結(jié)構(gòu)
  VideoWriter writer("result.avi", CV_FOURCC('M', 'J', 'P', 'G'), 25.0, Size(856, 480));
  //當(dāng)前幀數(shù)
  int nFrmNum = 0;
  //裁剪的天空高度
  int CutHeight = 310;
  //窗口命名
  cvNamedWindow("video", 1);
  cvNamedWindow("BWmode", 1);
  //調(diào)整窗口初始位置
  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)){
    //設(shè)置ROI裁剪圖像
    cvSetImageROI(pFrame, cvRect(0, CutHeight, pFrame->width, pFrame->height - CutHeight));
    nFrmNum++;
    //第一次要申請(qǐng)內(nèi)存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);
      //轉(zhuǎn)化成單通道圖像再處理
      cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
    }
    else{
      //獲得剪切圖
      cvCopy(pFrame, pCutFrame, 0);
#if 0    //反透視變換
      //二維坐標(biāo)下的點(diǎn),類型為浮點(diǎn)
      CvPoint2D32f srcTri[4], dstTri[4];
      CvMat* warp_mat = cvCreateMat(3, 3, CV_32FC1);
      //計(jì)算矩陣反射變換
      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;
      //改變目標(biāo)圖像大小
      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
      //前景圖轉(zhuǎn)換為灰度圖
      cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
      //二值化前景圖
      cvThreshold(pCutFrImg, pCutFrImg, 80, 255.0, CV_THRESH_BINARY);
      //進(jìn)行形態(tài)學(xué)濾波,去掉噪音
      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直線檢測(cè)
      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
      //恢復(fù)ROI區(qū)域
      cvResetImageROI(pFrame);
      //寫入視頻流
      writer << pFrame;
      //顯示圖像
      cvShowImage("video", pFrame);
      cvShowImage("BWmode", pCutFrImg);
      //按鍵事件,空格暫停,其他跳出循環(huán)
      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));
  //統(tǒng)計(jì)數(shù)量
  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
    //計(jì)算左邊
    int y = int(r / st);
    if (y >= 0 && y < img.rows){
      Point p(0, y);
      points.push_back(p);
    }
    //計(jì)算右邊
    y = int((r - ct*(img.cols - 1)) / st);
    if (y >= 0 && y < img.rows){
      Point p(img.cols - 1, y);
      points.push_back(p);
    }
    //計(jì)算上邊
    int x = int(r / ct);
    if (x >= 0 && x < img.cols){
      Point p(x, 0);
      points.push_back(p);
    }
    //計(jì)算下邊
    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;
  //當(dāng)前幀數(shù)
  int nFrmNum = 0;
  //裁剪的天空高度
  int CutHeight = 250;
  //窗口命名
  cvNamedWindow("video", 1);
  //cvNamedWindow("background", 1);
  cvNamedWindow("foreground", 1);
  //調(diào)整窗口初始位置
  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)){
    //設(shè)置ROI裁剪圖像
    cvSetImageROI(pFrame, cvRect(0, CutHeight, pFrame->width, pFrame->height - CutHeight));
    nFrmNum++;
    //第一次要申請(qǐng)內(nèi)存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);
      //轉(zhuǎn)化成單通道圖像再處理
      cvCvtColor(pCutFrame, pCutBkImg, CV_BGR2GRAY);
      cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
      //轉(zhuǎn)換成矩陣
      cvConvert(pCutFrImg, pCutFrameMat);
      cvConvert(pCutFrImg, pCutFrMat);
      cvConvert(pCutFrImg, pCutBkMat);
    }
    else{
      //獲得剪切圖
      cvCopy(pFrame, pCutFrame, 0);
      //前景圖轉(zhuǎn)換為灰度圖
      cvCvtColor(pCutFrame, pCutFrImg, CV_BGR2GRAY);
      cvConvert(pCutFrImg, pCutFrameMat);
      //高斯濾波先,以平滑圖像
      cvSmooth(pCutFrameMat, pCutFrameMat, CV_GAUSSIAN, 3, 0, 0.0);
      //當(dāng)前幀跟背景圖相減
      cvAbsDiff(pCutFrameMat, pCutBkMat, pCutFrMat);
      //二值化前景圖
      cvThreshold(pCutFrMat, pCutFrImg, 35, 255.0, CV_THRESH_BINARY);
      //進(jìn)行形態(tài)學(xué)濾波,去掉噪音
      cvErode(pCutFrImg, pCutFrImg, 0, 1);
      cvDilate(pCutFrImg, pCutFrImg, 0, 1);
      //更新背景
      cvRunningAvg(pCutFrameMat, pCutBkMat, 0.003, 0);
      //pCutBkMat = cvCloneMat(pCutFrameMat);
      //將背景轉(zhuǎn)化為圖像格式,用以顯示
      //cvConvert(pCutBkMat, pCutBkImg);
      cvCvtColor(pCutFrame, pCutBkImg, CV_BGR2GRAY);
      //canny變化
      cvCanny(pCutFrImg, pCutFrImg, 50, 100);
      #pragma region Hough檢測(cè)
      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);
      //按鍵事件,空格暫停,其他跳出循環(huán)
      int temp = cvWaitKey(2);
      if (temp == 32){
        while (cvWaitKey() == -1);
      }
      else if (temp >= 0){
        break;
      }
    }
    //恢復(fù)ROI區(qū)域(多余可去掉)
    cvResetImageROI(pFrame);
  }
  //銷毀窗口
  cvDestroyWindow("video");
  cvDestroyWindow("background");
  cvDestroyWindow("foreground");
  //釋放圖像和矩陣
  cvReleaseImage(&pCutFrImg);
  cvReleaseImage(&pCutBkImg);
  cvReleaseImage(&pCutFrame);
  cvReleaseMat(&pCutFrameMat);
  cvReleaseMat(&pCutFrMat);
  cvReleaseMat(&pCutBkMat);
  cvReleaseCapture(&pCapture);

  return 0;
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持我們。

上一篇:opencv攝像頭捕獲識(shí)別顏色

欄    目:C語言

下一篇:C語言中的正則表達(dá)式使用示例詳解

本文標(biāo)題:opencv車道線檢測(cè)的實(shí)現(xiàn)方法

本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/246.html

網(wǎng)頁制作CMS教程網(wǎng)絡(luò)編程軟件編程腳本語言數(shù)據(jù)庫(kù)服務(wù)器

如果侵犯了您的權(quán)利,請(qǐng)與我們聯(lián)系,我們將在24小時(shí)內(nèi)進(jìn)行處理、任何非本站因素導(dǎo)致的法律后果,本站均不負(fù)任何責(zé)任。

聯(lián)系QQ:835971066 | 郵箱:835971066#qq.com(#換成@)

Copyright © 2002-2020 腳本教程網(wǎng) 版權(quán)所有