OpenCV3 Trackbar軌跡條運用與輪廓查找填充

OpenCV3 Trackbar軌跡條運用與輪廓查找填充

插入頭文件:

#include "opencv2/imgproc/imgproc.hpp"  
#include "opencv2/highgui/highgui.hpp"  
using namespace cv;  

聲明全局變量:

Mat img;  
int threshval = 160;    //軌跡條滑塊對應的值,給初值160  

聲明定義軌跡回調函數:

static void on_trackbar(int, void*)  
{  
    Mat bw = threshval < 128 ? (img < threshval) : (img > threshval);//如果threshval小於128,則當bw中相應元素小於threshval時賦255,大於threshval時賦0。如果threshval大於128,則當bw相應元素大於threshval時賦255,小於threshval時賦0  
    //定義點和向量  
    vector<vector<Point> > contours;//存放輪廓,但是每個vector<Point>元素不一定只表示一個輪廓。  
    vector<Vec4i> hierarchy;//存放輪廓之間的拓撲關係。hierarchy[idx][0]、 hierarchy[idx][1]、 hierarchy[idx][2]、 hierarchy[idx][3]分別表示索引爲idx的輪廓的前一個、後一個、子、父輪廓對應的索引;當索引爲0時,表示相應的輪廓不存在。  
    findContours( bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );//查找輪廓  
    Mat dst = Mat::zeros(img.size(), CV_8UC3);//初始化dst  
    if( !contours.empty() && !hierarchy.empty() )//開始處理  
    {  
        //遍歷所有頂層輪廓,隨機生成顏色值繪製給各連接組成部分  
        int idx = 0;  
        for( ; idx >= 0; idx = hierarchy[idx][0] )  
        {  
            Scalar color( (rand()&255), (rand()&255), (rand()&255) );  
            drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );//繪製填充輪廓  
        }  
    }  
    imshow("Connected Components", dst);//顯示窗口  
}  

關於函數參數只有類型沒有名稱,要聯繫到createTrackbar這個函數,這個函數定義具體如下:

int createTrackbar(conststring& trackbarname, conststring& winname,  
int* value, int count, TrackbarCallback onChange=0,void* userdata=0);  

第一個參數,const string&類型的trackbarname,表示軌跡條的名字,用來代表我們創建的軌跡條。
第二個參數,const string&類型的winname,填窗口的名字,表示這個軌跡條會依附到哪個窗口上,即對應namedWindow()創建窗口時填的某一個窗口名。
第三個參數,int* 類型的value,一個指向整型的指針,表示滑塊的位置。並且在創建時,滑塊的初始位置就是該變量當前的值。
第四個參數,int類型的count,表示滑塊可以達到的最大位置的值。PS:滑塊最小的位置的值始終爲0。
第五個參數,TrackbarCallback類型的onChange,首先注意他有默認值0。這是一個指向回調函數的指針,每次滑塊位置改變時,這個函數都會進行回調。並且這個函數的原型必須爲void XXXX(int,void*);其中第一個參數是軌跡條的位置,第二個參數是用戶數據(看下面的第六個參數)。如果回調是NULL指針,表示沒有回調函數的調用,僅第三個參數value有變化。
第六個參數,void*類型的userdata,他也有默認值0。這個參數是用戶傳給回調函數的數據,用來處理軌跡條事件。如果使用的第三個參數value實參是全局變量的話,完全可以不去管這個userdata參數。

 

看完第五、六個參數的定義,就可知道我們問題的答案了。因爲回調函數要求這種格式,是故一定要遵循這種格式進行定義。而我們已經將第三個參數聲明爲全局變量,則不需要由第一個參數的值來獲得軌跡條的位置,又我們第六個參數採取默認值,則亦可無視回調函數的第二個參數,是故我們僅僅只是把參數的類型放在那裏而無需聲明參數名來加以調用。

另:在這個程序中沒用到但是關於軌跡條很常用的一個函數爲:

C++: int getTrackbarPos(conststring& trackbarname, conststring& winname);
//<span style="font-family: 'Microsoft YaHei'; font-size: 14px; line-height: 26px;">用於獲取當前軌跡條的位置並返回</span>  

第一個參數,const string&類型的trackbarname,表示軌跡條的名字。
第二個參數,const string&類型的winname,表示軌跡條的父窗口的名稱。

主體代碼

img = imread("1.jpg", 0);//載入圖片  
if( !img.data ) { printf("Oh,no,讀取img圖片文件錯誤~! \n"); return -1; }  
  
namedWindow( "Image", 1 );//顯示原圖  
imshow( "Image", img );  
  
namedWindow( "Connected Components", 1 );//創建處理窗口  
createTrackbar( "Threshold", "Connected Components", &threshval, 255, on_trackbar );//創建軌跡條  
on_trackbar(threshval, 0);//軌跡條回調函數 

軟件運行效果圖(圖片上方爲生成軌跡條):

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章