1. 程式人生 > >C/C++ 影象處理(14)------影象の輪廓填充

C/C++ 影象處理(14)------影象の輪廓填充

所謂影象的輪廓填充,是建立在影象的輪廓已然查詢完成的情況下的,以下面影象為例:
這裡寫圖片描述
我們首先需要查詢到影象中的圓形和正方形的幾個輪廓,之後才能對這些輪廓進行處理(查詢的過程我們用到OpenCV的findContours函式)。
在得到輪廓之後,難點就轉變為如何填充輪廓了,對於左上角的圓來說,直接填充即可,然而對於圓環和“田”字,則一般只希望填充兩個輪廓直接的區域,中間的孔洞則保留,因此在對輪廓進行填充之前需要做進一步的判斷工作(通過判斷findContours函式的第三個引數物件實現),具體的實現程式碼如下:

#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp" #include "time.h" using namespace cv; using namespace std; int main(int argc, char** argv) { long time = clock(); int r = 100; Mat src = Mat::zeros(Size(8 * r, 4 * r), CV_8UC1); //繪製輪廓,因為線段本身有粗細,則繪製一個圓會檢測出兩個輪廓,需要特別注意 //繪製三個圓,其中一個巢狀著另一個 circle(src, cvPoint(2
* r, 2 * r), 80, Scalar(255), 2); circle(src, cvPoint(2 * r, 2 * r), 50, Scalar(255), 2); circle(src, cvPoint(r, r), 30, Scalar(255), 2); //繪製一個田字 rectangle(src, cvPoint(4 * r - r / 2, 2 * r - r / 2), cvPoint(4 * r + r / 2, 2 * r + r / 2), Scalar(255), 2); rectangle(src, cvPoint(4 * r - r * 2
/ 5, 2 * r - r * 2 / 5), cvPoint(4 * r - r * 1 / 20, 2 * r - r * 1 / 20), Scalar(255), 2); rectangle(src, cvPoint(4 * r - r * 2 / 5, 2 * r + r * 1 / 20), cvPoint(4 * r - r * 1 / 20, 2 * r + r * 2 / 5), Scalar(255)); rectangle(src, cvPoint(4 * r + r * 2 / 5, 2 * r - r * 2 / 5), cvPoint(4 * r + r * 1 / 20, 2 * r - r * 1 / 20), Scalar(255), 2); rectangle(src, cvPoint(4 * r + r * 2 / 5, 2 * r + r * 1 / 20), cvPoint(4 * r + r * 1 / 20, 2 * r + r * 2 / 5), Scalar(255), 2); Mat raw_dist1(src.size(), CV_32FC1); vector<vector<Point> > contours; vector<Vec4i> hierarchy; Mat src_copy = src.clone(); findContours(src_copy, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);//查詢輪廓,並以樹狀圖結果儲存輪廓資訊 for (size_t i = 0; i < contours.size(); i++) { if (hierarchy[i][3] != -1)//表示其為某一個輪廓的內嵌輪廓 { if (hierarchy[hierarchy[i][3]][3] == -1)//表示其為最外層輪廓,上面檢測到的是其線條的內部 { drawContours(raw_dist1, contours, i, Scalar(255), -1); } else { drawContours(raw_dist1, contours, i, Scalar(0), -1); } } else { drawContours(raw_dist1, contours, i, Scalar(0), -1); } } printf("花費時間%dms\n", clock() - time); char* source_window = "Source"; namedWindow(source_window, CV_WINDOW_AUTOSIZE); imshow(source_window, src); namedWindow("Distance1", CV_WINDOW_AUTOSIZE); imshow("Distance1", raw_dist1); imwrite("輪廓查詢影象.jpg", src); imwrite("輪廓查詢完成影象.jpg", raw_dist1); waitKey(0); return(0); }

通過上面的程式碼,我們把影象中的輪廓進行了白色的填充,結果如下圖所示
這裡寫圖片描述
到此,我們得到了一副輪廓填充完成的影象,其中的填充區域為白色,如果需要進一步處理,則可以通過連通域檢測演算法找到各個輪廓畫素點的集合。
需要注意的是,上面的程式碼只支援到兩層輪廓的巢狀(一般而言,對於CAD等軟體出來的圖形最多隻會有兩層),再多層的巢狀則需要修改程式碼中的判斷部分。