前言
在上一章中描述了Canny邊緣檢測(cè)算子闷营,詳細(xì)描述可點(diǎn)擊查看(http://www.reibang.com/p/e25737f10a44)
目標(biāo)
本章中氛赐,將學(xué)習(xí):
- 霍夫變化介紹
- 霍夫直線變化介紹
- 相關(guān)API學(xué)習(xí)
- 代碼演示
霍夫變化介紹
我們首先來(lái)了解一下霍夫變換是什么述么?霍夫 變換是一種特征檢測(cè)(feature extraction)籍琳,被廣泛應(yīng)用在圖像分析(image analysis)菲宴、計(jì)算機(jī)視覺(jué)(computer vision)以及數(shù)位影像處理(digital image processing)∏骷保霍夫變換是用來(lái)辨別找出物件中的特征喝峦,其流程大致如下:給定一個(gè)物件、要辨別的形狀的種類呜达,算法會(huì)在參數(shù)空間(paramerter space)中執(zhí)行投票來(lái)決定物體的形狀谣蠢,而這是累加空間(accumulator space)里的局部最大值(local maximum)來(lái)決定。我們常用的霍夫變換為這兩種:1查近、霍夫直線變換:在圖像中尋找直線眉踱;2、霍夫圓變換:在圖像中尋找圓霜威。
霍夫直線變化介紹
霍夫直線變換主要用于直線特征的檢測(cè)谈喳,其主要思想如下
1.將圖形中的點(diǎn)從空域坐標(biāo)(x,y)轉(zhuǎn)化為極坐標(biāo) x=ρcosθ,y=ρsinθ戈泼,R2=(ρcosθ)2+(ρsinθ)2
2.對(duì)極坐標(biāo)進(jìn)行變換婿禽,轉(zhuǎn)化為θ與R的關(guān)系
如圖所示
在這兩個(gè)三角形中赏僧,直線上任意一個(gè)點(diǎn)通過(guò)R=xcosθ+ysinθ都可以求得直線到原點(diǎn)距離,且只要點(diǎn)在直線上谈宛,R值就是固定不變的次哈,所以直線在極坐標(biāo)中的表達(dá)式得以確定
比如平面內(nèi)有三個(gè)點(diǎn),怎樣判斷他們是不是再一條直線上呢
y=kx+b吆录,由于點(diǎn)是給定的窑滞,所以我們知道x和y的值,因此將k和b看成變量恢筝,映射到kb直角坐標(biāo)系中就可以如下表示
但是這種表示方法沒(méi)辦法表示垂直于x軸的直線(斜率k不存在)的情況哀卫,因此需要轉(zhuǎn)換到極坐標(biāo)中,如果三個(gè)點(diǎn)三個(gè)方程能解出固定的ρ和θ撬槽,則過(guò)三點(diǎn)存在一條直線
變換完極坐標(biāo)就是求解方程組的問(wèn)題此改;
霍夫變化介紹
OpenCV實(shí)現(xiàn)了兩種Hough線變換:
一個(gè)。標(biāo)準(zhǔn)Hough變換
- 標(biāo)準(zhǔn)的霍夫變換cv :: HoughLines從平面坐標(biāo)轉(zhuǎn)換到霍夫空間侄柔,最終輸出的是(θ,rθ)表示極坐標(biāo)空間
概率霍夫線變換 - 霍夫變換直線概率cv :: HoughLinesP共啃,最終輸出是直線的兩個(gè)點(diǎn)(x0,y0,x1,y1)
cv::HoughLines(
InputArray src, // 輸入圖像,必須8-bit的灰度圖像
OutputArray lines, // 輸出的極坐標(biāo)來(lái)表示直線暂题,經(jīng)過(guò)調(diào)用HoughLines函數(shù)后儲(chǔ)存了霍夫線變換檢測(cè)到線條的輸出矢量移剪。每一條線由具有兩個(gè)元素的矢量(ρ,θ)表示薪者,其中纵苛,ρ是離坐標(biāo)原點(diǎn)((0,0)(也就是圖像的左上角)的距離。 θ是弧度線條旋轉(zhuǎn)角度(0~ 垂直線言津,π/2~水平線)攻人。
double rho, // 生成極坐標(biāo)時(shí)候的像素掃描步長(zhǎng),一般取值為 1 悬槽,不要大于圖像尺寸的一半
double theta, //生成極坐標(biāo)時(shí)候的角度步長(zhǎng)怀吻,一般取值CV_PI/180,即表示一度
int threshold, // 閾值初婆,只有獲得足夠交點(diǎn)的極坐標(biāo)點(diǎn)才被看成是直線
double srn=0;// 是否應(yīng)用多尺度的霍夫變換蓬坡,如果不是設(shè)置0表示經(jīng)典霍夫變換,多尺度表示的是使用圖像金字塔烟逊,即多尺度圖上進(jìn)行霍夫變換
double stn=0;//是否應(yīng)用多尺度的霍夫變換渣窜,如果不是設(shè)置0表示經(jīng)典霍夫變換
double min_theta=0; // 表示角度掃描范圍 0 ~180之間铺根, 默認(rèn)即可
double max_theta=CV_PI
) // 一般情況是有經(jīng)驗(yàn)的開發(fā)者使用宪躯,需要自己反變換到平面空間
cv::HoughLinesP(
InputArray src, // 輸入圖像,必須8-bit的灰度圖像
OutputArray lines, // 輸出的極坐標(biāo)來(lái)表示直線位迂,經(jīng)過(guò)調(diào)用HoughLinesP函數(shù)后后存儲(chǔ)了檢測(cè)到的線條的輸出矢量访雪,每一條線由具有四個(gè)元素的矢量(x_1,y_1, x_2, y_2) 表示详瑞,其中,(x_1, y_1)和(x_2, y_2) 是是每個(gè)檢測(cè)到的線段的結(jié)束點(diǎn)臣缀。
double rho, // 生成極坐標(biāo)時(shí)候的像素掃描步長(zhǎng)坝橡,一般取值為 1
double theta, //生成極坐標(biāo)時(shí)候的角度步長(zhǎng),一般取值CV_PI/180精置,即表示一度
int threshold, // 閾值计寇,只有獲得足夠交點(diǎn)的極坐標(biāo)點(diǎn)才被看成是直線
double minLineLength=0;// 最小直線長(zhǎng)度,有默認(rèn)值0脂倦,表示最低線段的長(zhǎng)度番宁,比這個(gè)設(shè)定參數(shù)短的線段就不能被顯現(xiàn)出來(lái)。
double maxLineGap=0;// 最大間隔赖阻,有默認(rèn)值0蝶押,允許將同一行點(diǎn)與點(diǎn)之間連接起來(lái)的最大的距離。
)
代碼演示
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void main(int argc, char** argv)
{
//1. 讀取圖像
Mat src, canny, dst;
src = imread("E:/Experiment/OpenCV/Pictures/LineTest.jpg");
imshow("src", src);
//2. 獲取邊緣
Canny(src, canny, 100, 200);
imshow("canny", canny);
//3. 轉(zhuǎn)成彩色圖像
cvtColor(canny, dst, CV_GRAY2BGR);//將二值圖轉(zhuǎn)換BGR彩色圖像火欧,這里重新創(chuàng)建一張空Mat也行
//4. 霍夫變換檢測(cè)
vector<Vec4f> plines;//保存霍夫變換檢測(cè)到的直線
HoughLinesP(canny, plines, 1, CV_PI / 180, 10, 0, 10);//提取邊緣時(shí)棋电,會(huì)造成有些點(diǎn)不連續(xù),所以maxLineGap設(shè)大點(diǎn)
//5. 顯示檢測(cè)到的直線
Scalar color = Scalar(0, 0, 255);//設(shè)置顏色
for (size_t i = 0; i < plines.size(); i++)
{
Vec4f hline = plines[i];
line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);//繪制直線
}
imshow("plines", dst);
waitKey(0);
}