9.1田晚、點集的最小外包
點集是坐標(biāo)點的集返弹。
9.1.1、最小外包旋轉(zhuǎn)矩形
//點集
Mat points = (Mat_<float>(5, 2) << 1, 1, 5, 1, 1, 10, 5, 10, 2, 5);
//計算點集的最小外包旋轉(zhuǎn)矩陣
RotatedRect rRect = minAreaRect(points);
//打印旋轉(zhuǎn)矩形的信息
cout << "旋轉(zhuǎn)矩形的角度" << rRect.angle << endl;
cout << "旋轉(zhuǎn)矩形的中心" << rRect.center << endl;
cout << "旋轉(zhuǎn)矩形的尺寸" << rRect.size << endl;
9.1.2沐兰、旋轉(zhuǎn)矩形的四個頂點
OpenCV3新特性
void boxPoints(RotatedRect box,OutputArray points)
便于計算旋轉(zhuǎn)矩形的四個頂點,這樣就可以使用函數(shù)line
畫出四個頂點的連線蔽挠,從而畫出旋轉(zhuǎn)矩形住闯。
9.1.3、最小外包圓
void minEnclosingCircle( InputArray points,CV_OUT Point2f& center, CV_OUT float& radius );
9.1.4澳淑、最小外包直立矩形
Rect boundingRect( InputArray points );
9.1.5比原、最小凸包
凸包是將最外層的點連接起來構(gòu)成的凸多邊形,它能包含點集的所有點杠巡。
void convexHull( InputArray points, OutputArray hull,
bool clockwise = false, bool returnPoints = true );
利用該函數(shù)求出的凸包量窘,坐標(biāo)點的順序不是隨機(jī)排列的,而是按照某順序排列的氢拥,也就是把這些點依次相連就可以得到連線蚌铜。
9.1.6、最小外包三角形
OpenCV3新特性
double minEnclosingTriangle( InputArray points, CV_OUT OutputArray triangle );
//5行2列的單通道Mat
Mat point = (Mat_<int>(5, 2) << 1, 1, 5, 1, 1, 10, 5, 10, 2, 5);
//轉(zhuǎn)換為雙通道矩陣
point = point.reshape(2, 5);
//存儲三角形的三個頂點
vector<Point> triangle;
//點集的最小外包三角形
double area;
area = minEnclosingTriangle(point, triangle);
//打印結(jié)果
cout << "三角形的三個頂點";
for (int i = 0; i < 3; i++)
{
cout << triangle[i] << ",";
}
cout << "面積" << area << endl;
9.2嫩海、霍夫直線檢測
如果知道原點到一條直線的代數(shù)距離ρ和與x軸的夾角θ冬殃,則直線方程可由以下方式表示:
當(dāng)然, 反過來也可以出革, 如果知道平面內(nèi)的一條直線造壮, 那么可以計算出唯一的ρ和θ渡讼, 即xoy平面內(nèi)的任意一條直線對應(yīng)參數(shù)空間(或稱霍夫空間) θoρ中的一點(ρ骂束, θ) 。
Hough
直線檢測的基本原理在于利用點與線的對偶性成箫≌瓜洌霍夫變換運用兩個坐標(biāo)空間之間的變換,將在一個空間中具有相同形狀的曲線或直線映射到另一個坐標(biāo)空間的一個點上形成峰值蹬昌,從而把檢測任意形狀的問題轉(zhuǎn)化為統(tǒng)計峰值問題混驰。
結(jié)論:判斷xoy平面內(nèi)哪些點是共線的,首先求出每一個點對應(yīng)到霍夫空間的曲線,然后判斷哪幾條曲線相交于一點栖榨,最后將相交于一點的曲線反過來對應(yīng)到xoy平面內(nèi)的點昆汹,這些點是共線的。
在理論上婴栽,一個點對應(yīng)無數(shù)條直線或者說任意方向的直線(在參數(shù)空間中坐標(biāo)軸表示的斜率k或者說θ有無數(shù)個)满粗,但在實際應(yīng)用中,我們必須限定直線的數(shù)量(即有限數(shù)量的方向)才能夠進(jìn)行計算愚争。
因此映皆,我們將直線的方向θ離散化為有限個等間距的離散值,參數(shù)ρ也就對應(yīng)離散化為有限個值轰枝,于是參數(shù)空間不再是連續(xù)的捅彻,而是被離散量化為一個個等大小網(wǎng)格單元。將圖像空間(直角坐標(biāo)系)中每個像素點坐標(biāo)值變換到參數(shù)空間(極坐標(biāo)系)后鞍陨,所得值會落在某個網(wǎng)格內(nèi)步淹,使該網(wǎng)格單元的累加計數(shù)器加1。當(dāng)圖像空間中所有的像素都經(jīng)過霍夫變換后诚撵,對網(wǎng)格單元進(jìn)行檢查贤旷,累加計數(shù)值最大的網(wǎng)格,其坐標(biāo)值(ρ0, θ0)就對應(yīng)圖像空間中所求的直線砾脑。
如下圖解
總結(jié):使用霍夫變換檢測直線具體步驟:
1.彩色圖像->灰度圖
2.去噪(高斯核)
3.邊緣提扔资弧(梯度算子、拉普拉斯算子韧衣、canny
盅藻、sobel
)
4.二值化(判斷此處是否為邊緣點,就看灰度值==255)
5.映射到霍夫空間(準(zhǔn)備兩個容器畅铭,一個用來展示hough-space概況氏淑,一個數(shù)組hough-space用來儲存voting的值,因為投票過程往往有某個極大值超過閾值硕噩,多達(dá)幾千假残,不能直接用灰度圖來記錄投票信息)
6.取局部極大值,設(shè)定閾值炉擅,過濾干擾直線
7.繪制直線辉懒、標(biāo)定角點
優(yōu)點:Hough
直線檢測的優(yōu)點是抗干擾能力強(qiáng),對圖像中直線的殘缺部分谍失、噪聲以及其它共存的非直線結(jié)構(gòu)不敏感眶俩,能容忍特征邊界描述中的間隙,并且相對不受圖像噪聲的影響
缺點:Hough
變換算法的特點導(dǎo)致其時間復(fù)雜度和空間復(fù)雜度都很高快鱼,并且在檢測過程中只能確定直線方向颠印,丟失了線段的長度信息纲岭。由于霍夫檢測過程中進(jìn)行了離散化,因此檢測精度受參數(shù)離散間隔制約
OpenCV支持三種霍夫直線檢測算法:
1)Standard Hough Transform(SHT线罕,標(biāo)準(zhǔn)霍夫變換)
2)Multiscale Hough Transform(MSHT止潮,多尺度霍夫變換)
3)Progressive Probability Houth Transform(PPHT,漸進(jìn)概率式霍夫變換)
在OpenCV3.0及以上版本中钞楼,霍夫直線檢測算法定義了兩個函數(shù):HoughLines
(1沽翔、2)、HoughLinesP
(3)
CV_EXPORTS_W void HoughLines( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double srn = 0, double stn = 0,
double min_theta = 0, double max_theta = CV_PI );
//InputArray image:輸入圖像窿凤,必須是8位單通道圖像仅偎。
//OutputArray lines:檢測到的線條參數(shù)集合。
//double rho:以像素為單位的距離步長雳殊。
//double theta:以弧度為單位的角度步長橘沥。
//int threshold:累加計數(shù)值的閾值參數(shù),當(dāng)參數(shù)空間某個交點的累加計數(shù)的值超過該閾值夯秃,則認(rèn)為該交點對應(yīng)了圖像空間的一條直線座咆。
//double srn:默認(rèn)值為0,用于在多尺度霍夫變換中作為參數(shù)rho的除數(shù)仓洼,rho=rho/srn介陶。
//double stn:默認(rèn)值為0,用于在多尺度霍夫變換中作為參數(shù)theta的除數(shù)色建,theta=theta/stn哺呜。
//如果srn和stn同時為0,就表示HoughLines函數(shù)執(zhí)行標(biāo)準(zhǔn)霍夫變換箕戳,否則就是執(zhí)行多尺度霍夫變換某残。
CV_EXPORTS_W void HoughLinesP( InputArray image, OutputArray lines,
double rho, double theta, int threshold,
double minLineLength = 0, double maxLineGap = 0 );
//InputArray image:輸入圖像,必須是8位單通道圖像陵吸。
//OutputArray lines:檢測到的線條參數(shù)集合玻墅。
//double rho:直線搜索時的距離步長,以像素為單位壮虫。
//double theta:直線搜索時的角度步長澳厢,以弧度為單位。
//int threshold:累加計數(shù)值的閾值參數(shù)囚似,當(dāng)參數(shù)空間某個交點的累加計數(shù)的值超過該閾值剩拢,則認(rèn)為該交點對應(yīng)了圖像空間的一條直線。
//double minLineLength:默認(rèn)值為0谆构,表示最小線段長度閾值(像素)裸扶。
//double maxLineGap:線段上最近兩點之間的閾值.默認(rèn)值為0框都,表示直線斷裂的最大間隔距離閾值搬素。即如果有兩條線段是在一條直線上呵晨,但它們之間有間隙,那么如果這個間隔距離小于該值熬尺,則被認(rèn)為是一條線段摸屠,否則認(rèn)為是兩條線段。
注意:霍夫直線變換是一種用來在圖像空間尋找直線的方法粱哼,輸入圖像要求是二值圖像季二,同時為了提高檢測直線的效率和準(zhǔn)確率,在使用霍夫線變換之前揭措,最好對圖像進(jìn)行邊緣檢測生成邊緣二值圖像胯舷,這樣的檢測效果是最好的。
9.3绊含、霍夫圓檢測
9.3.2桑嘶、標(biāo)準(zhǔn)霍夫圓檢測
與霍夫直線檢測類似, 圖像的霍夫圓檢測就是檢測哪些前景或邊緣像素點在同一個 圓上躬充, 并給出對應(yīng)圓的圓心坐標(biāo)及圓的半徑逃顶; 而且仍然需要計數(shù)器來完成該過程, 只是 這里的計數(shù)器從二維變成了三維充甚。
9.3.2以政、基于梯度的霍夫圓檢測
步驟:首先定位圓心(兩個參數(shù)),然后計算半徑 (一個參數(shù))伴找。在代碼實現(xiàn)中盈蛮,首先構(gòu)造一個二維計數(shù)器,然后再構(gòu)造一個一維計數(shù)器技矮。
OpenCV提供的函數(shù)HoughCircles
實現(xiàn)了基于梯度的霍夫圓檢測眉反, 在該函數(shù)的實現(xiàn)過 程中, 使用了Sobel
算子且內(nèi)部實現(xiàn)了邊緣的二值圖穆役, 所以輸入的圖像不用像函數(shù) HoughLinesP
和HoughLines
一樣必須是二值圖寸五。
CV_EXPORTS_W void HoughCircles( InputArray image, OutputArray circles,
int method, double dp, double minDist,
double param1 = 100, double param2 = 100,
int minRadius = 0, int maxRadius = 0 );
缺點是在不知道一些先驗知識的情況下, 需要多次調(diào)整參數(shù)才有可能得到我們想要的結(jié)果耿币。
對于霍夫變換不限于對直線梳杏、圓進(jìn)行檢測,也可以對橢圓等其他幾何形狀進(jìn)行擬合淹接。同時從原理中可以看出十性,霍夫變換的一個較大的優(yōu)點就是可以檢測出部分或者遮擋的直線和圓,當(dāng)然其他幾何形狀也可以塑悼。
9.4劲适、輪廓
9.4.1、查找厢蒜、擬制輪廓
輪廓:有序點集
CV_EXPORTS_W void findContours( InputOutputArray image, OutputArrayOfArrays contours,
OutputArray hierarchy, int mode,
int method, Point offset = Point());
CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours,
int contourIdx, const Scalar& color,
int thickness = 1, int lineType = LINE_8,
InputArray hierarchy = noArray(),
int maxLevel = INT_MAX, Point offset = Point() );
9.4.2霞势、外包烹植、擬合輪廓
介紹了尋找圖像中輪廓的方法和點集的擬合, 那么這兩部分合起來愕贡, 就可以處理圖像目標(biāo)的定位問題了 草雕。
第一步: 對圖像邊緣檢測或者閾值分割得到二值圖,有時也需要對這些二值圖進(jìn)行形態(tài)學(xué)處理固以。
第二步: 利用函數(shù)findContours
尋找二值圖中的多個輪廓墩虹。
第三步: 對于通過第二步得到的多個輪廓,其中每一個輪廓都可以作為函數(shù) convexHull
憨琳、minAreaRect
等的輸入?yún)?shù)诫钓,然后就可以擬合出包含這個輪廓的最小凸包、最小旋轉(zhuǎn)矩形等篙螟。
Mat img = imread("Koala.jpg", IMREAD_GRAYSCALE);
//step1:邊緣檢測尖坤,得到邊緣二值圖
GaussianBlur(img, img, Size(3, 3), 0.5);
Mat binaryImg;
Canny(img, binaryImg, 50, 200);
//step2:邊緣的輪廓
vector<vector<Point>> contours;
findContours(binaryImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
//step3:對每一個輪廓進(jìn)行擬合
for (int i = 0; i < contours.size(); i++)
{
Rect rect = boundingRect(contours[i]);
if (rect.area() > 500)
{
rectangle(img, rect, Scalar(255));
}
}
9.4.3、輪廓的周長和面積
用來計算點集所圍區(qū)域的周長:
參數(shù)closed
是指點集是否首尾相接闲擦。
CV_EXPORTS_W double arcLength( InputArray curve, bool closed );
用來計算點集所圍區(qū)域的面積
CV_EXPORTS_W double contourArea( InputArray contour, bool oriented = false );
9.4.4慢味、點和輪廓的位置關(guān)系
點集可以圍成一個封閉的輪廓, 那么空間中任意一點和這個輪廓無非有三種關(guān)系: 點在輪廓外墅冷、 點在輪廓上纯路、 點在輪廓內(nèi)。
CV_EXPORTS_W double pointPolygonTest( InputArray contour, Point2f pt, bool measureDist );
注:measureDist
是bool類型寞忿,當(dāng)其值為false
時驰唬,函數(shù)pointPolygonTest
的返回值有三種, 即+1腔彰、0叫编、-1, +1代表pt
在點集圍成的輪廓內(nèi)霹抛,0代表pt
在點集圍成的輪廓上搓逾,-1代表pt
在點集圍成的輪廓外;當(dāng)其值為true
時杯拐,則返回值為pt
到輪廓的實際距離霞篡。
9.4.5、輪廓的凸包缺陷
用來衡量凸包的缺陷:
void convexityDefects( InputArray contour, InputArray convexhull, OutputArray convexityDefects );
convexityDefects
代表返回的凸包缺陷的信息端逼,形式為vector< Vec4i>
朗兵,每一個Vec4i
代表一個缺陷,它的四個元素依次代表:缺陷的起點顶滩、終點余掖、最遠(yuǎn)點的索引及最遠(yuǎn)點到凸包的距離。
對凸包的缺陷檢測在判斷物體形狀等方面發(fā)揮著很重要的作用礁鲁,與凸包缺陷類似的還有如矩形度盐欺、橢圓度赁豆、 圓度等,它們均是衡量目標(biāo)物體形態(tài)的度量找田。