OpenCV Tutorial: 霍夫找線(HoughLines、HoughLinesP)

来源:互联网 发布:java表白小程序 编辑:程序博客网 时间:2024/04/19 18:51

霍夫找線(HoughLines、HoughLinesP)

計算機視覺中經常需要識別或者定位某些幾何圖形,像直線、圓、橢圓等,檢測直線的霍夫變換提供在圖像中尋找直線的一種算法,後來這概念發展到能檢測圓、橢圓等,不僅能夠識別出圖像中想要的圖形,而且能夠得到位置、角度等資訊,這邊解釋霍夫直線偵測的原理。

核心思想是把圖像中某個點集映射到另一空間的一個點集上,這個點記錄了點集合的數目,通過搜索峰值來決定線。像我們常用yi=axi+b表達空間中通過點(xi,yi)的一條線,a和b決定了通過此點的線,假設空間有另一點(xj,yj),我們以yj = a’xj+b’得到a’和b’,a’和b’決定了通過此點的線。

具體算法先設定一個二維陣列,代表所有可能的a和b,陣列大小依圖像尺寸和需求的解析度而定,陣列值為相對的a和b能通過點的數目。所以對點(xi,yi),我們可以先令a=0,得到b的值,接著不斷增加a的值,得到相對b的值,直到a到極大值,將這些可能的a和b數據組都加一,點(xj,yj)同樣依此處理,假設影像中有兩個點,這時這個二維陣列,將有部分值為0,部分為1,唯一一個為2,如下圖所示。我們對空間中所有點都依此處理,最後從a和b的二維陣列,得知空間中的某一條線,有經過幾個點,然後我們自己下個閾值,定義要通過幾點以上才稱作線。

HoughLines


但是這種一般式,可能會遇到斜率為0或無窮大的情況,造成計算上的麻煩,所以習慣上都轉換成極座標,用極座標來表達空間中的一條線,轉換的公式為r=xcosθ+ysinθ,由於轉換的方式,轉換空間會從上述的直線變成正弦曲線,但同樣可得到通過此點的所有r和θ,透過r和θ這個2維陣列,得知空間中的某一條線,總共通過幾個點。

HoughLines

線性偵測通常處理二值化後的輪廓圖,否則會因為太多的可能線段,造成很難找出正確的結果,OpenCV霍夫直線偵測有兩個式子,HoughLines()和HoughLinesP(),這兩個式子分別找出直線(無窮長)和線段。


OpenCV 直線偵測

void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0)

  • image:輸入圖,8位元單通道二值化圖。
  • lines:將所有線的資料存在vector< Vec2f >,Vec2f為每個線的資料,分別有ρ、θ這兩個參數,ρ表示和左上角(0,0)的距離,θ是線的旋轉角度,單位弧度,垂直線的θ為0,水平線的θ為π/2。
  • rho:距離解析度,越小表示定位要求越準確,但也較易造成應該是同條線的點判為不同線。
  • theta:角度解析度,越小表示角度要求越準確,但也較易造成應該是同條線的點判為不同線。
  • threshold:累積個數閾值,超過此值的線才會存在lines這個容器內。
  • srn:可有可無的距離除數。
  • stn:可有可無的角度除數。

OpenCV 直線偵測

void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0)

  • image:輸入圖,8位元單通道二值化圖。
  • lines:將所有線的資料存在vector< Vec4i >,Vec4i為每個線段的資料,分別有x1、y1、x2、y2這四個值,(x1,y1)和(x2,y2)分別表示線段的頭尾頂點。
  • rho:距離解析度,越小表示定位要求越準確,但也較易造成應該是同條線的點判為不同線。
  • theta:角度解析度,越小表示角度要求越準確,但也較易造成應該是同條線的點判為不同線。
  • threshold:累積個數閾值,超過此值的線才會存在lines這個容器內。
  • minLineLength :線段最短距離,超過此值的線才會存在lines這個容器內。
  • maxLineGap:最大間隔。

以下範例分別用HoughLines()和HoughLinesP()找出圖中的直線或線段,並用自行撰寫的drawLines()將找到的直線或線段畫出,在HoughLines()中,我們先判斷線是直的或橫的,直的線兩端點會在第一列和最後一列,橫的線兩端點會在第一欄和最後一欄。

#include <cstdio>#include <opencv2/opencv.hpp>using namespace cv;#define PI 3.1416void calcLinesP(const Mat &input, std::vector<Vec4i> &lines);void drawLinesP(Mat &input, const std::vector<Vec4i> &lines);void calcLines(const Mat &input, std::vector<Vec2f> &lines);void drawLines(Mat &input, const std::vector<Vec2f> &lines);int main(){    Mat img = imread("test.jpg",CV_LOAD_IMAGE_GRAYSCALE);    Mat result1 = imread("test.jpg",CV_LOAD_IMAGE_COLOR);    Mat result2 = imread("test.jpg",CV_LOAD_IMAGE_COLOR);    vector<Vec4i> linesP;    calcLinesP(img,linesP);    drawLinesP(result1, linesP);    vector<Vec2f> lines;    calcLines(img,lines);    drawLines(result2, lines);    namedWindow("Display window1", WINDOW_AUTOSIZE);    namedWindow("Display window2", WINDOW_AUTOSIZE);    namedWindow("Display window3", WINDOW_AUTOSIZE);    imshow("Display window1", img);      imshow("Display window2", result1);    imshow("Display window3", result2);    waitKey(0);      return 0;}void calcLinesP(const Mat &input, std::vector<Vec4i> &lines){     Mat contours;     Canny(input, contours, 50, 150);     lines.clear();     HoughLinesP(contours, lines, 1, CV_PI/180, 50); }void calcLines(const Mat &input, std::vector<Vec2f> &lines){     Mat contours;     Canny(input,contours,50,150);     lines.clear();     HoughLines(contours, lines, 1, CV_PI/180, 50);}void drawLinesP(Mat &input, const std::vector<Vec4i> &lines){     for(int i=0; i<lines.size(); i++){         line(input, Point(lines[i][0], lines[i][3]), Point(lines[i][4], lines[i][5]), Scalar(255,0,0), 3);     } }void drawLines(Mat &input, const std::vector<Vec2f> &lines){     for(int i=0; i<lines.size(); i++){         float r = lines[i][0];         float theta = lines[i][6];         if(theta<PI/4.0 || theta>3*PI/4.0){             Point pt1(r/cos(theta),0);             Point pt2((r-input.rows*sin(theta))/cos(theta), input.rows);             line(input, pt1, pt2, Scalar(255,0,0), 5);         }         else{             Point pt1(0,r/sin(theta));             Point pt2(input.cols, (r-input.cols*cos(theta))/sin(theta));             line(input, pt1, pt2, Scalar(255,0,0), 3);         }     } }

HoughLines

HoughLines

HoughLines

0 0
原创粉丝点击