opencv求最小外接矩陣
求最小外接矩陣的基本原理:
獲取點簇最開始的minx,maxx,miny,maxy確定最初的外接矩形,求外接矩形的面積,然後對點簇進行旋轉,按照下面公式即可:
旋轉之後,求出新的minx,maxx,miny,maxy,計算此時的面積,直到面積達到最小,對應的即為最小外接矩形。
關於影象旋轉參考:https://blog.csdn.net/zhouxuguang236/article/details/31820095
1.輸入是一幅圖,如邊緣圖(如canny邊緣檢測後,僅有0與255)
測試程式碼:
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(edge, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
Mat imageContours = Mat::zeros(edge.size(), CV_8UC1);
int idx, maxcontours = 0;
vector<Point> selectpoint;
for (int i = 0; i < contours.size(); i++)//有可能識別出幾組點簇分佈,取出最大的點簇
{
vector<Point> ptmp = contours[i];
if (ptmp.size() > maxcontours)
{
selectpoint = ptmp;
idx = i;
}
}
//繪製輪廓
drawContours(imageContours, contours, idx, Scalar(255), 1, 8, hierarchy);
//繪製輪廓的最小外接矩形
RotatedRect rect = minAreaRect(selectpoint);
Point2f P[4];
rect.points(P);//外接矩形的四個頂點
for (int j = 0; j <= 3; j++)
{
line(imageContours, P[j], P[(j + 1) % 4], Scalar(255), 2);
}
imshow("MinAreaRect", imageContours);
waitKey(0);
注意:
(1)部分關鍵量解釋
contours;//向量內每個元素儲存了一組由連續的Point點構成的點的集合的向量,每一組Point點集就是一個輪廓。
//有多少輪廓,向量contours就有多少元素
hierarchy;//向量內每一個元素包含了4個int型變數,向量hiararchy內的元素和輪廓向量contours內的元素是一一對應的,向量的容量相同。每一個元素的4個int型變數——hierarchy[i][0] ~hierarchy[i][3],分別表示第i個輪廓的後一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號。如果當前輪廓沒有對應的後一個輪廓、前一個輪廓、父輪廓或內嵌輪廓的話,則hierarchy[i][0] ~hierarchy[i][3]的相應位被設定為預設值-1。
findContours(edge, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
//RETR_EXTERNAL,只檢測最外圍輪廓,包含在外圍輪廓內的內圍輪廓被忽略。
//CHAIN_APPROX_NONE,儲存物體邊界上所有連續的輪廓點到contours向量中。
(2)可能出現的問題
一般情況下,我們都期望找到包括影象所有邊緣的最小外接矩陣,但這種方法可能產生問題。如輸入影象如下圖:
其會分成兩組點簇:藍圈部分與紅圈部分。
取最大的點簇可能取不完整我們需要的矩形邊界,但可能外接矩陣沒問題,如下圖。但是點簇右下邊缺失,不利於後續操作,所以不推薦使用這種方法。
2.輸入是一組點(x,y)
測試程式碼:
vector<Point> pointxy;
vector<vector<Point>> aglcontours0;
find_edge_coordinate(edge,pointxy);//提取邊緣部分,將影象中邊緣部分的點提取出來,並儲存
aglcontours0.push_back(pointxy);
Mat imageContours = Mat::zeros(edge.size(), CV_8UC1);
drawContours(imageContours, aglcontours0, 0, Scalar(255), 1, 8);
RotatedRect rect = minAreaRect(pointxy);//查詢最小外接矩形
Point2f P[4];
rect.points(P);//外接矩形的四個頂點
for (int j = 0; j <= 3; j++)
{
line(imageContours, P[j], P[(j + 1) % 4], Scalar(128), 2);
}
imshow("MinAreaRect", imageContours);
waitKey(0);
輸出顯示:
說明:不知道為啥中間部分也成了白色的。。。。。。