opencv繪製圖形輪廓並篩選面積操作
1、 類比halcon的篩選區域面積的操作select_shape運算元,opencv也可以對圖形的輪廓進行面積的篩選,剔除無效區域。
int main() { Mat srcImage = imread("D:\\Opencv\\Project\\ConnectionProject\\modules_08.png"); imshow("【原圖】", srcImage);
//首先對影象進行空間的轉換 Mat grayImage; cvtColor(srcImage, grayImage, CV_BGR2GRAY); //對灰度圖進行濾波 GaussianBlur(grayImage, grayImage, Size(3, 3), 0, 0); imshow("【濾波後的影象】", grayImage);
//為了得到二值影象,對灰度圖進行邊緣檢測 Mat cannyImage; Canny(grayImage, cannyImage, 128, 255, 3); //在得到的二值影象中尋找輪廓 vector<vector<Point>> contours; vector<Vec4i> hierarchy; findContours(cannyImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
//繪製輪廓 for (int i = 0; i < (int)contours.size(); i++) { drawContours(cannyImage, contours, i, Scalar(255), 1, 8); } imshow("【處理後的影象】", cannyImage);
//計算輪廓的面積 cout << "【篩選前總共輪廓個數為】:" << (int)contours.size() << endl; for (int i = 0; i < (int)contours.size(); i++) { double g_dConArea = contourArea(contours[i], true); cout << "【用輪廓面積計算函式計算出來的第" << i << "個輪廓的面積為:】" << g_dConArea << endl; }
//篩選剔除掉面積小於100的輪廓 vector <vector<Point>>::iterator iter = contours.begin(); for (; iter != contours.end();) { double g_dConArea = contourArea(*iter); if (g_dConArea < 100) { iter = contours.erase(iter); } else { ++iter; } } cout << "【篩選後總共輪廓個數為:" << (int)contours.size() << endl; for (int i = 0; i < (int)contours.size(); i++) { double g_dConArea = contourArea(contours[i], true); cout << "【用輪廓面積計算函式計算出來的第" << i << "個輪廓的面積為:】" << g_dConArea << endl; } Mat result(srcImage.size(), CV_8U, Scalar(0)); drawContours(result, contours, -1, Scalar(255), 1); // -1 表示所有輪廓 namedWindow("result"); imshow("result", result); waitKey(0); return 0;
}
篩選前和篩選後的面積對比:
控制檯輸出資料:第一次輪廓面積個數為295,第二次篩選後面積個數為145,注意這裡輪廓面積有正有負。
這裡重點是2個運算元,findcontours和drawcontours
//! retrieves contours and the hierarchical information from black-n-white image. CV_EXPORTS_W void findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point());
Image必須為二值圖,可以通過compare(),inRange(),threshold(),adaptiveThreshold(),Canny()這些運算元來實現對原圖的二值化。
contours為輸出的輪廓陣列,每一個輪廓用Point型別的vector容器表示。
hierarchy引數和輪廓個數相同,每一個輪廓contour[i]都包含著hieracrchy[i][0],hieracrchy[i][1],hieracrchy[i][2],hieracrchy[i][3],分別表示前一個輪廓,後一個輪廓,父輪廓,內嵌輪廓的索引編號。
mode 表示輪廓的檢索模式;
RETR_EXTERNAL表示只檢索最外延的輪廓。
RETR_LIST表示檢測的輪廓不建立等級關係
RETR_CCOMP建立兩個等級的輪廓,上面一層為外邊界,裡面一層為內孔邊界資訊,如果孔內還有一個聯通物體,這個物體的邊界也在頂上,
RETR_TREE建立一個等級樹的輪廓,這個例項中採用這種方法。
method表示輪廓的逼近方法
CHAIN_APPROX_NONE儲存所有的輪廓點,相鄰兩個輪廓點的位置差不超過1,
CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點座標,例如一個矩形只保留4個點來儲存輪廓資訊。
CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似演算法 offset表示輪廓的偏移資料,可以設定任何值,在ROI中尋找輪廓,並要在這個影象中分析時,還是很有用的。
//! draws contours in the image
CV_EXPORTS_W void drawContours( InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() );
contouridx指明畫第幾個輪廓,如果該引數為負數,-1,則畫全部輪廓,
color為輪廓的顏色
thickness為輪廓的線寬,如果為負數或者CV_FILLED表示輪廓內部填充。
linetype表示線型
//繪製輪廓 for (int i = 0; i < (int)contours.size(); i++) { drawContours(cannyImage, contours, i, Scalar(255), 1, 8); } imshow("【處理後的影象】", cannyImage);
等效於以下程式碼:
Mat result(srcImage.size(), CV_8U, Scalar(0)); drawContours(result, contours, -1, Scalar(255), 1); // -1 表示所有輪廓 --------------------- 作者:RobotHeartGo 原文:https://blog.csdn.net/wuguanghao/article/details/69941598