1. 程式人生 > >opencv繪製圖形輪廓並篩選面積操作

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