溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

OpenCV中霍夫變換直線檢測的示例分析

發(fā)布時間:2021-06-11 14:40:26 來源:億速云 閱讀:148 作者:小新 欄目:編程語言

這篇文章將為大家詳細講解有關OpenCV中霍夫變換直線檢測的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

霍夫變換(Hough Transform)的主要思想:

一條直線在平面直角坐標系(x-y)中可以用y=ax+b式表示,對于直線上一個確定的點(x0,y0),總符合y0-ax0=b,而它可以表示為參數平面坐標系(a-b)中的一條直線。因此,圖像中的一個點對應參數平面的一條直線,同樣,圖像中的一條直線對應參數平面上的一個點。

基本Hough變換檢測直線:

由于同一條直線上的不同點在參數平面中是會經過同一個點的多條線。對圖像的所有點作霍夫變換,檢測直線就意味著找到對應參數平面中的直線相交最多的點。對這些交點做票數累計,然后取出票數大于最小投票數的點,即為原坐標系里檢測出的直線。

一般,直線的參數方程為 ρ=xcosθ+ysinθ

OpenCV中的基本霍夫變換直線檢測函數 cv::HoughLines:

函數輸入為一幅二值圖像(有很多待檢測點),其中一些點排列后形成直線,通常這是一幅邊緣圖像,比如來自Sobel算子或Canny算子。函數的輸出是cv::Vec2f的向量,每個元素都是一對代表檢測到的直線的浮點數(ρ, θ)。函數的作法是先求出原圖像中每點的極坐標方程,若相交于一點的極坐標曲線的個數大于最小投票數,則將該點(ρ, θ)(參數坐標系點)放入輸出向量。

#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
 
#define PI 3.1415926
 
class LineFinder{
private:
 std::vector<cv::Vec2f> lines;
 double deltaRho; // 參數坐標系的步長(theta表示與直線垂直的角度)
 double deltaTheta;
 int minVote;  // 判斷是直線的最小投票數 
public:
 LineFinder() {
 deltaRho = 1;
 deltaTheta = PI / 180;
 minVote = 80;
 }
 void setAccResolution(double dRho, double dTheta) {
 deltaRho = dRho;
 deltaTheta = dTheta;
 }
 void setMinVote(int minv) {
 minVote = minv;
 }
 // Hough變換檢測直線;rho=1,theta=PI/180參數坐標系里的步長,threshold=最小投票數
 void findLines(cv::Mat& binary){
 lines.clear();
 cv::HoughLines(binary, lines, deltaRho, deltaTheta, minVote);
 }
 
 void drawDetectedLines(cv::Mat& result){
 std::vector<cv::Vec2f>::const_iterator it = lines.begin();
 while (it != lines.end())
 {
 // 以下兩個參數用來檢測直線屬于垂直線還是水平線
 float rho = (*it)[0];
 float theta = (*it)[1];
 if (theta < PI / 4. || theta > 3.*PI / 4.)
 { // 若檢測為垂直線,直線交于圖片的上下兩邊,先找交點
 cv::Point pt1(rho / cos(theta), 0);
 cv::Point pt2((rho - result.rows*sin(theta)) / cos(theta), result.rows);
 cv::line(result, pt1, pt2, cv::Scalar(255), 1); //
 }
 else // 若檢測為水平線,直線交于圖片的左右兩邊,先找交點
 {
 cv::Point pt1(0, rho / sin(theta));
 cv::Point pt2(result.cols, (rho - result.cols*cos(theta)) / sin(theta));
 cv::line(result, pt1, pt2, cv::Scalar(255), 1);
 }
 ++it;
 }
 }
};
 
int main(int argc, char *argv[])
{
 cv::Mat image = cv::imread("D:/VS_exercise/images/road1.jpg");
 cv::Mat imageGray;
 cv::Mat contours;
 cv::cvtColor(image, imageGray, cv::COLOR_RGB2GRAY);
 cv::Canny(imageGray, contours, 190, 300);
 // 在原圖的拷貝上畫直線
 cv::Mat result(contours.rows, contours.cols, CV_8U, cv::Scalar(255));
 image.copyTo(result);
 // Hough變換檢測
 LineFinder finder;
 finder.setMinVote(130);
 finder.findLines(contours);
 finder.drawDetectedLines(result);
 
 // 顯示
 cv::namedWindow("Detected Lines with Hough");
 cv::imshow("Detected Lines with Hough", result);
 cv::waitKey(0);
 return 0;
}

OpenCV中霍夫變換直線檢測的示例分析

概率Hough變換檢測線段:

霍夫變換檢測直線的目的,是找到二值圖像中經過足夠多數量點的所有直線,當同一直線穿過許多點,便意味著這條線的存在足夠明顯。

概率霍夫變換在原算法的基礎上增加了一些改動,主要是:

1. 不再系統(tǒng)地逐行掃描圖像,而是隨機挑選(輪廓圖像的)前景點,一旦累加器中的某一項交點的票數達到給定的最小值,就搜索輪廓圖像在對應直線上的前景點,連成線段(要小于maxLineGap),然后記錄線段參數(起終點),最后刪除所有經過的點(即使它們并未投過票)。

2. 概率霍夫變換定義了兩個額外的參數:一個是可以接受的最小線段長度(minLineLength),另一個是允許組成連續(xù)線段的最大像素間隔(maxLineGap),雖然額外步驟增加了算法的復雜度,但由于參與投票的點數有所減少,因此得到了一些補償。

openCV中的概率霍夫變換直線檢測函數 cv::HoughLinesP:

函數的輸出是cv::Vec4i組成的向量,每個元素是檢測到的線段的兩個坐標點(pt1x, pt1y, pt2x, pt2y)。

#include "opencv2/highgui.hpp"
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
 
#define PI 3.1415926 
 
class LineFinder{
private:
 std::vector<cv::Vec4i> lines;
 double deltaRho; // 步長(theta表示與直線垂直的角度)
 double deltaTheta;
 int minVote;  // 判斷是直線的最小投票數 
 double minLength; // 判斷是直線的最小線段長度 
 double maxGap; // 允許組成連續(xù)線段的最大像素間隔
public:
 LineFinder() {
 deltaRho = 1;
 deltaTheta = PI / 180;
 minVote = 10;
 minLength = 0.0;
 maxGap = 0.0;
 }
 void setAccResolution(double dRho, double dTheta) {
 deltaRho = dRho;
 deltaTheta = dTheta;
 }
 void setMinVote(int minv) {
 minVote = minv;
 }
 void setLineLengthAndGap(double length, double gap) {
 minLength = length;
 maxGap = gap;
 }
 
 // Hough變換檢測線段
 void findLines(cv::Mat& binary) {
 lines.clear();
 cv::HoughLinesP(binary, lines, deltaRho, deltaTheta, minVote, minLength, maxGap);
 }
 
 void drawDetectedLines(cv::Mat &image, cv::Scalar color = cv::Scalar(255)) {
 std::vector<cv::Vec4i>::const_iterator it2 = lines.begin();
 while (it2 != lines.end()) {
 cv::Point pt1((*it2)[0], (*it2)[1]);
 cv::Point pt2((*it2)[2], (*it2)[3]);
 cv::line(image, pt1, pt2, color, 1.5); //畫線段
 ++it2;
 }
 }
};
 
int main(int argc, char *argv[])
{
 cv::Mat image = cv::imread("D:/VS_exercise/images/road1.jpg");
 cv::Mat imageGray;
 cv::Mat contours;
 cv::cvtColor(image, imageGray, cv::COLOR_RGB2GRAY);
 // 邊緣檢測
 cv::Canny(imageGray, contours, 190, 300);
 // Hough變換檢測
 LineFinder finder;
 finder.setMinVote(80);
 finder.setLineLengthAndGap(100, 10); //概率Hough變換增加的兩個參數
 finder.findLines(contours);
 finder.drawDetectedLines(image);
 
 // 顯示
 cv::imshow("Detected Lines with Hough", image);
 cv::waitKey(0);
 return 0;
}

OpenCV中霍夫變換直線檢測的示例分析

關于“OpenCV中霍夫變換直線檢測的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI