日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

OpenCV(十八)霍夫变换(直线、线段与圆检测)

發布時間:2023/11/27 生活经验 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV(十八)霍夫变换(直线、线段与圆检测) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、基礎理論

1、作用:

2、定義

3、原理

二、直線檢測

?1、基礎理論

?1、原理

2、過程

2、HoughLines函數(直線檢測)

3、HoughLinesP函數(線段檢測)

三、圓檢測

1、基礎理論

1、概念

?2、原理

2、HoughCircles函數

C++ API:?

python API:

總代碼

參考資料


一、基礎理論

1、作用:

提取直線等幾何形狀。

2、定義

霍夫變換(Hough Transform)是圖像處理中的一種特征提取技術,它通過一種投票算法檢測具有特定形狀的物體。Hough變換是圖像處理中從圖像中識別幾何形狀的基本方法之一。Hough變換的基本原理在于利用點與線的對偶性,將原始圖像空間的給定的曲線通過曲線表達形式變為參數空間的一個。這樣就把原始圖像中給定曲線的檢測問題轉化為尋找參數空間中的峰值問題。也即把檢測整體特性轉化為檢測局部特性。比如直線、橢圓、圓、弧線等。

????????原則上霍夫變換可以檢測任何形狀,但復雜的形狀需要的參數就多,霍夫空間的維數就多,因此在程序實現上所需的內存空間以及運行效率上都不利于把標準霍夫變換應用于實際復雜圖形的檢測中。霍夫梯度法是霍夫變換的改進(圓檢測),它的目的是減小霍夫空間的維度,提高效率。

3、原理

直線檢測原理:將要檢測的對象轉到霍夫空間中,利用累加器找到最優解,即為所求直線。

(注:檢測前要對圖像二值化處理)

圓檢檢測原理:霍夫梯度法,找到達到閾值的原點和半徑。

兩個點決定直線的斜率和截距情況:

三個點決定直線斜率和截距情況:

極坐標系:

求出了“極坐標”空間下相交的點,自然也就可以用哪個求出直線的三個點坐標。

?

得到曲線:采用不同的遍歷值

?使用累加器檢測直線:

累加器是一個二維數組。

二、直線檢測

?1、基礎理論

霍夫變換 (Hough Line Transform) 是圖像處理中的一種特征提取技術. 通過平面空間極值坐標空間的轉換, 可以幫助我們實現直線檢測

?1、原理

1、首先邊緣檢測,得到許多點

2、遍歷第一個點的各個方向的,得到第一個點的曲線

3、遍歷每一個點,得到多條曲線

4、多曲線相交,就是最終的,通過它可以確定最終直線

(左:笛卡爾坐標系? ? ? ? 右:霍夫空間)????????

2、過程

1、首先邊緣檢測,得到許多點

2、遍歷第一個點的各個方向的,得到第一個點的曲線

???????

3、遍歷每一個點,得到多條曲線

4、多曲線相交,就是最終的和,通過它可以確定最終直線

2、HoughLines函數(直線檢測)

HoughLines函數:

void HoughLines(InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn=0, double stn=0 )  
  • 第一個參數,InputArray類型的image,輸入圖像,即源圖像,需為8位的單通道二進制圖像,可以將任意的源圖載入進來后由函數修改成此格式后,再填在這里。
  • 第二個參數,InputArray類型的lines,經過調用HoughLines函數后儲存了霍夫線變換檢測到線條的輸出矢量。每一條線由具有兩個元素的矢量表示,其中,是離坐標原點((0,0)(也就是圖像的左上角)的距離。?是弧度線條旋轉角度(0~垂直線,π/2~水平線)。
  • 第三個參數,double類型的rho,以像素為單位的距離精度。另一種形容方式是直線搜索時的進步尺寸的單位半徑。PS:Latex中/rho就表示?。
  • 第四個參數,double類型的theta,以弧度為單位的角度精度。另一種形容方式是直線搜索時的進步尺寸的單位角度。
  • 第五個參數,int類型的threshold,累加平面的閾值參數,即識別某部分為圖中的一條直線時它在累加平面中必須達到的值。大于閾值threshold的線段才可以被檢測通過并返回到結果中。
  • 第六個參數,double類型的srn,有默認值0。對于多尺度的霍夫變換,這是第三個參數進步尺寸rho的除數距離。粗略的累加器進步尺寸直接是第三個參數rho,而精確的累加器進步尺寸為rho/srn。
  • 第七個參數,double類型的stn,有默認值0,對于多尺度霍夫變換,srn表示第四個參數進步尺寸的單位角度theta的除數距離。且如果srn和stn同時為0,就表示使用經典的霍夫變換。否則,這兩個參數應該都為正數。
HoughLines(dst, lines, 1,                       CV_PI / 180,        150);//                距離精度(像素)           角度精度(弧度)     累加平面閾值  
//霍夫直線檢測
void Hough_Line()
{//1、邊緣檢測Canny(src, dst, 50, 200, 3);imshow("canny edge", dst);//2、霍夫變換vector<Vec2f> lines;        //定義一個矢量結構lines用于存放得到的線段矢量集合  HoughLines(dst, lines, 1, CV_PI / 180, 150);//                                  距離精度(像素)   角度精度(弧度)     累加平面閾值  //3、依次繪制每條線段for (size_t i = 0; i < lines.size(); i++){float rho = lines[i][0], theta = lines[i][1];    //距離精度、角度精度Point pt1, pt2;                                  //定義兩點p1和p2double a = cos(theta), b = sin(theta);           //a:cos  b:sin//以x0和y0作為參照點,求出(x1, y1)和(x2, y2)double x0 = a * rho, y0 = b * rho;pt1.x = cvRound(x0 - 1000 * (-b));pt1.y = cvRound(y0 - 1000 * (a));pt2.x = cvRound(x0 + 1000 * (-b));pt2.y = cvRound(y0 + 1000 * (a));line(dst, pt1, pt2, Scalar(200, 0, 0), 3);       //繪制直線}imshow("Hough", dst);
}

3、HoughLinesP函數(線段檢測)

HoughLinesP函數:

此函數在HoughLines的基礎上末尾加了一個代表Probabilistic(概率)的P,表明它可以采用累計概率霍夫變換(PPHT)來找出二值圖像中的線段。

void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )  
  • 第一個參數,InputArray類型的image,輸入圖像,即源圖像,需為8位的單通道二進制圖像,可以將任意的源圖載入進來后由函數修改成此格式后,再填在這里。
  • 第二個參數,InputArray類型的lines,經過調用HoughLinesP函數后后存儲了檢測到的線條的輸出矢量,每一條線由具有四個元素的矢量(x_1,y_1, x_2, y_2)??表示,其中,(x_1, y_1)和(x_2, y_2)?是是每個檢測到的線段的結束點。
  • 第三個參數,double類型的rho,以像素為單位的距離精度。另一種形容方式是直線搜索時的進步尺寸的單位半徑。
  • 第四個參數,double類型的theta,以弧度為單位的角度精度。另一種形容方式是直線搜索時的進步尺寸的單位角度。
  • 第五個參數,int類型的threshold,累加平面的閾值參數,即識別某部分為圖中的一條直線時它在累加平面中必須達到的值。大于閾值threshold的線段才可以被檢測通過并返回到結果中。
  • 第六個參數,double類型的minLineLength,有默認值0,表示最低線段的長度,比這個設定參數短的線段就不能被顯現出來。
  • 第七個參數,double類型的maxLineGap,有默認值0,允許將同一行點與點之間連接起來的最大的距離。
HoughLinesP(dst, lines, 1,                      CV_PI / 180,        80,                 50,                 10);//                  距離精度(像素)          角度精度(弧度)     累加平面閾值         最低線段長度  同一行點與點連接的最大距離
//霍夫線段檢測
void Hough_LineP()
{//1、邊緣檢測Canny(src, dst, 50, 200, 3);imshow("canny edge", dst);//2、霍夫變換vector<Vec4i> lines;        //定義一個矢量結構lines用于存放得到的線段矢量集合  HoughLinesP(dst, lines, 1,                      CV_PI / 180,        80,                 50,                 10);//                      距離精度(像素)         角度精度(弧度)     累加平面閾值  最低線段長度  同一行點與點連接的最大距離//3、依次繪制每條線段for (size_t i = 0; i < lines.size(); i++){Vec4i l = lines[i];line(dst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(255, 0, 0), 3);}imshow("Hough", dst);
}

?

三、圓檢測

1、基礎理論

1、概念

??

霍夫圓變換 (Hough Circle Transform) 的原理和霍夫直線變換類似. 對于一條直線, 我們可以用參數表示, 對于圓我們需要三個參數 ?,分別代表三個參數 圓心(x, y), r半徑。?(也叫霍夫梯度法

因為霍夫圓檢測對噪聲比較敏感, 所以首先要對圖像做中值濾波。

?2、原理

霍夫變換圓檢測是基于圖像梯度實現:

圓心檢測的原理︰圓心是圓周法線的交匯處設置一個閾值在某點的相交的直線的條數大于這個閾值就認為該交匯點為圓心。
圓半徑確定原理:圓心到圓周上的距離〔半徑)是相同的設置一個閾值只要相同距離的數量大于該閾值就認為該距離是該圓心的半徑。

霍夫圓檢測里面包含有canny邊緣檢測

2、HoughCircles函數

C++ API:?

void HoughCircles(InputArray image,OutputArray circles, int method, double dp, double minDist, double param1=100,double param2=100, int minRadius=0, int maxRadius=0 )  
  • 第一個參數,InputArray類型的image,輸入圖像,即源圖像,需為8位的灰度單通道圖像。
  • 第二個參數,InputArray類型的circles,經過調用HoughCircles函數后此參數存儲了檢測到的圓的輸出矢量,每個矢量由包含了3個元素的浮點矢量(x, y, radius)表示。
  • 第三個參數,int類型的method,即使用的檢測方法,目前OpenCV中就霍夫梯度法一種可以使用,它的標識符為CV_HOUGH_GRADIENT,在此參數處填這個標識符即可。
  • 第四個參數,double類型的dp,用來檢測圓心的累加器圖像的分辨率于輸入圖像之比的倒數,且此參數允許創建一個比輸入圖像分辨率低的累加器。上述文字不好理解的話,來看例子吧。例如,如果dp= 1時,累加器和輸入圖像具有相同的分辨率。如果dp=2,累加器便有輸入圖像一半那么大的寬度和高度。
  • 第五個參數,double類型的minDist,為霍夫變換檢測到的圓的圓心之間的最小距離,即讓我們的算法能明顯區分的兩個不同圓之間的最小距離。這個參數如果太小的話,多個相鄰的圓可能被錯誤地檢測成了一個重合的圓。反之,這個參數設置太大的話,某些圓就不能被檢測出來了。
  • 第六個參數,double類型的param1,有默認值100。它是第三個參數method設置的檢測方法的對應的參數。對當前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示傳遞給canny邊緣檢測算子的高閾值,而低閾值為高閾值的一半。
  • 第七個參數,double類型的param2,也有默認值100。它是第三個參數method設置的檢測方法的對應的參數。對當前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在檢測階段圓心的累加器閾值。它越小的話,就可以檢測到更多根本不存在的圓,而它越大的話,能通過檢測的圓就更加接近完美的圓形了。
  • 第八個參數,int類型的minRadius,有默認值0,表示圓半徑的最小值。
  • 第九個參數,int類型的maxRadius,也有默認值0,表示圓半徑的最大值。
HoughCircles(dst, circles, HOUGH_GRADIENT, 1.5, 10,                     200, 100,               0,  0);//                     霍夫梯度法       dp  圓心間最小距離          高閾值  累加閾值    圓半徑最小、最大值      

python API:

def HoughCircles(image: Any,method: Any,dp: Any,minDist: Any,circles: Any = None,param1: Any = None,param2: Any = None,minRadius: Any = None,maxRadius: Any = None) -> None

參數:?

  • 第二個參數,int類型的method,即使用的檢測方法,目前OpenCV中就霍夫梯度法一種可以使用,它的標識符為CV_HOUGH_GRADIENT,在此參數處填這個標識符即可。
  • 第三個參數,double類型的dp,用來檢測圓心的累加器圖像的分辨率于輸入圖像之比的倒數,且此參數允許創建一個比輸入圖像分辨率低的累加器。上述文字不好理解的話,來看例子吧。例如,如果dp= 1時,累加器和輸入圖像具有相同的分辨率。如果dp=2,累加器便有輸入圖像一半那么大的寬度和高度。
  • 第四個參數,double類型的minDist,為霍夫變換檢測到的圓的圓心之間的最小距離,即讓我們的算法能明顯區分的兩個不同圓之間的最小距離。這個參數如果太小的話,多個相鄰的圓可能被錯誤地檢測成了一個重合的圓。反之,這個參數設置太大的話,某些圓就不能被檢測出來了。
  • 第五個參數,InputArray類型的circles,經過調用HoughCircles函數后此參數存儲了檢測到的圓的輸出矢量,每個矢量由包含了3個元素的浮點矢量(x, y, radius)表示。
  • 第六個參數,double類型的param1,有默認值100。它是第三個參數method設置的檢測方法的對應的參數。對當前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示傳遞給canny邊緣檢測算子的高閾值,而低閾值為高閾值的一半。
  • 第七個參數,double類型的param2,也有默認值100。它是第三個參數method設置的檢測方法的對應的參數。對當前唯一的方法霍夫梯度法CV_HOUGH_GRADIENT,它表示在檢測階段圓心的累加器閾值。它越小的話,就可以檢測到更多根本不存在的圓,而它越大的話,能通過檢測的圓就更加接近完美的圓形了。
  • 第八個參數,int類型的minRadius,有默認值0,表示圓半徑的最小值。
  • 第九個參數,int類型的maxRadius,也有默認值0,表示圓半徑的最大值。

//霍夫圓檢測
void Hough_Circle()
{//1、轉化為灰度圖并圖像平滑cvtColor(src, gray, COLOR_BGR2GRAY);GaussianBlur(gray, dst, Size(9, 9), 2, 2);imshow("濾波", dst);//2、霍夫圓變換(用灰度圖)vector<Vec3f> circles;HoughCircles(dst, circles, HOUGH_GRADIENT, 1.5, 10,                     200, 100,               0,  0);//                         霍夫梯度法      dp  圓心間最小距離           高閾值  累加閾值    圓半徑最小、最大值      //3、依次在圖中繪制出圓 for (size_t i = 0; i < circles.size(); i++){Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));   //圓心int radius = cvRound(circles[i][2]);                            //半徑//繪制圓心  circle(src, center, 3, Scalar(0, 255, 255), -1);//繪制圓輪廓  circle(src, center, radius, Scalar(0, 255, 255), 3);}imshow("Hough", src);
}

最佳地匹配每個圖像,參數不一樣?

HoughCircles(dst, circles, HOUGH_GRADIENT, 1.5, 10, 50,    100, 0, 0);

HoughCircles(dst, circles, HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);

總代碼

//霍夫變換(直線和圓檢測)
#include <opencv2/opencv.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include<vector>using namespace cv;
using namespace std;Mat src, dst, gray;//霍夫直線檢測(不推薦)
void Hough_Line()
{//1、邊緣檢測Canny(src, dst, 50, 200, 3);imshow("canny edge", dst);//2、霍夫變換vector<Vec2f> lines;        //定義一個矢量結構lines用于存放得到的線段矢量集合  HoughLines(dst, lines, 1, CV_PI / 180, 150);//                                  距離精度(像素)   角度精度(弧度)     累加平面閾值  //3、依次繪制每條線段for (size_t i = 0; i < lines.size(); i++){float rho = lines[i][0], theta = lines[i][1];       //距離精度、角度精度Point pt1, pt2;                                               //定義兩點p1和p2double a = cos(theta), b = sin(theta);           //a:cos  b:sin//以x0和y0作為參照點,求出(x1, y1)和(x2, y2)double x0 = a * rho, y0 = b * rho;pt1.x = cvRound(x0 - 1000 * (-b));pt1.y = cvRound(y0 - 1000 * (a));pt2.x = cvRound(x0 + 1000 * (-b));pt2.y = cvRound(y0 + 1000 * (a));line(dst, pt1, pt2, Scalar(200, 0, 0), 3);          //繪制直線}imshow("Hough", dst);
}//霍夫線段檢測(推薦)
void Hough_LineP()
{//1、邊緣檢測Canny(src, dst, 50, 200, 3);imshow("canny edge", dst);//2、霍夫變換vector<Vec4i> lines;        //定義一個矢量結構lines用于存放得到的線段矢量集合  HoughLinesP(dst, lines, 1, CV_PI / 180, 80, 100, 10);//                                  距離精度(像素)   角度精度(弧度)     累加平面閾值  最低線段長度  同一行點與點連接的最大距離//3、依次繪制每條線段for (size_t i = 0; i < lines.size(); i++){Vec4i l = lines[i];line(dst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(255, 0, 0), 3);}imshow("Hough", dst);
}//霍夫圓檢測
void Hough_Circle()
{//1、轉化為灰度圖并圖像平滑cvtColor(src, gray, COLOR_BGR2GRAY);GaussianBlur(gray, dst, Size(9, 9), 2, 2);imshow("濾波", dst);//2、霍夫圓變換(用灰度圖)vector<Vec3f> circles;HoughCircles(dst, circles, HOUGH_GRADIENT, 1.5, 10, 50, 100, 0, 0);//                                      霍夫梯度法                 dp  圓心間最小距離   高閾值  累加閾值    圓半徑最小、最大值      //HoughCircles(dst, circles, HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);//3、依次在圖中繪制出圓 for (size_t i = 0; i < circles.size(); i++){Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));   //圓心int radius = cvRound(circles[i][2]);                                         //半徑//繪制圓心  circle(src, center, 3, Scalar(0, 0, 255), -1);//繪制圓輪廓  circle(src, center, radius, Scalar(0, 0, 255), 3);}imshow("Hough", src);
}int main()
{src = imread("Resource/4.jpg");imshow("原圖", src);Hough_Line();                   //霍夫直線檢測Hough_LineP();                   //霍夫線段檢測Hough_Circle();                 //霍夫圓檢測waitKey(0);return 0;
}

參考資料

https://blog.csdn.net/zhu_hongji/article/details/81632611

【OpenCV】 ??高手勿入! 半小時學會基本操作 13?? 直線檢測_我是小白呀的博客-CSDN博客

OpenCV之霍夫變換_天下對手教會少林武僧-CSDN博客_opencv霍夫變換

Opencv2.4學習::邊緣檢測(5)Canny算法_dieju8330的博客-CSDN博客_canny

邊緣檢測-Canny_今天你學習了嗎?-CSDN博客

黑馬程序員人工智能教程_10小時學會圖像處理OpenCV入門教程_嗶哩嗶哩_bilibili

總結

以上是生活随笔為你收集整理的OpenCV(十八)霍夫变换(直线、线段与圆检测)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。