封閉連續區域的面積和周長計算【2】--面積與周長

上次本來想介紹怎麼計算封閉連續區域的面積和周長,結果不小心說成了sobel算子的介紹,這次真的介紹如何計算面積和周長。這裏試驗用到三幅圖片,test1,test2,test3.test4如下圖所示:

 封閉連續區域的面積和周長計算【2】--面積與周長

                                            圖實際場景中圖片


封閉連續區域的面積和周長計算【2】--面積與周長

人造數據集,場景包含多個物體

封閉連續區域的面積和周長計算【2】--面積與周長
人造數據集,邊界棱角較多
封閉連續區域的面積和周長計算【2】--面積與周長

圖4 假想圖像

注意,這裏已經將物體從背景中分離開,即背景爲0,前景在計算中會被設置爲255,即黑色代表背景,白色代表物體,分離的辦法很多,暫不解釋,不然又要走題了。

首先介紹的是腳趾頭法,爲什麼叫腳趾頭法呢,因爲用腳趾頭都能想到這個方法,就是直接統計像素點,對於周長就計算邊界像素點個數,面積就計算整個物體包含像素點個數。對圖片test1和test3計算結果如表1所示。

代碼如下,注意這裏使用的是VS208+OpenCV 2.4 環境:

int main( int argc, char** argv )

{

    Mat image,image_gray,image_edge,image_bin; //

        image=cv::imread("test3.bmp",1);

        cvtColor( image, image_gray, CV_BGR2GRAY );//變成灰度圖

       threshold(image_gray,image_bin,10,255,THRESH_BINARY);//二值化圖像

    int start;

       double timeConsume;  

       // 統計像素點個數,慢速

       double circle=0;

       double area=0;

       start=GetTickCount();

       Canny(image_bin,image_edge,100,200,3);

       image_bin.convertTo(image_bin,CV_64FC1);

       image_edge.convertTo(image_edge,CV_64FC1);

       for(int p=0;p<image_bin.rows;p++)

       for(int q=0;q<image_bin.cols;q++)

       {     {

              if(image_edge.at<double>(p,q)>0)  circle++;

              if(image_bin.at<double>(p,q)>0)          area++;          

              }           

       }

              timeConsume=(GetTickCount()-start)*1.0/1000;// test  0.171 test3 1.782

       return 0;

}

 看起來很簡單,如其名字,但是現在用的是效率很高的C/C++尚且需要那麼長時間,想想其他編譯器吧,只能說這個算法效率太差!算法的總結如表2所述。

       接着頭腦法,本質還是統計像素點,但用大腦對統計的方法做出了改進,使之效率飛昇,在計算中我們常常用到像素點的統計,但是沒有引起重視,本質原因就是統計像素點我們一般直接在matlab中敲命令add即可,真方便,可惜離開了matlab命令就用不上去了。所以用大腦考慮從這一點出發,設計快速統計的方法,計算結果如表1.

 

代碼如下:

 

       // //統計像素點個數,快速

       ////////canny算子來提取邊界

       // start=GetTickCount();

       // Canny(image_bin,image_edge,100,200,3);

   //image_edge.convertTo(image_edge,CV_64FC1);

       //image_edge=addmatrix(image_edge);

       //image_edge=addmatrix(image_edge.t());

       //double circle=image_edge.at<double>(0,0)/255;

 

       //image_bin.convertTo(image_bin,CV_64FC1);

       //image_bin=addmatrix(image_bin);

       //image_bin=addmatrix(image_bin.t());

       //double area=image_bin.at<double>(0,0)/255;

        //timeConsume=(GetTickCount()-start)*1.0/1000

   //addmatrix爲我自己寫的函數,但根據函數格式,應該能猜到算法

 

如表1所示效率得到了極大提高,然而本質的缺陷沒有得到解決, 對該算法的分析如表2所述。

       下面就得坐下來用心好好想想問題了,考慮通過邊界直接計算面積,就像計算長方形正方形面積一樣,通過邊界就能給出面積和周長,當然這裏的圖形明顯比長方形和正方形複雜,但是我們學過微積分,不斷分割,總能分割成近似的正方形和三角形。這時候從邊界信息入手,考慮到了用鏈碼的方法來計算周長和麪積。

 

代碼如下:

…………..

…………..

 

(等待添加)

…………..

…………..

此時效率得到了更大的提高,畢竟只計算了邊界像素點,對其詳細分析如表2所述。

 

和大家經驗一樣,很多好的算法OpenCV裏面已經自帶了,這些工具包的目的是方便大家使用,但是使用多了就會發現很多很常用的算法其實都根本不懂,時間長了之後很容易忘掉。但這裏還是介紹下OpenCV自帶的鏈碼方法,名字叫眼睛法,因爲用眼睛看就行了,這種方法。計算結果如表1所示

 

代碼如下:

//自帶函數計算

start=GetTickCount();

vector<vector<Point> > contours;

findContours(image_bin, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); double Leafarea=contourArea(contours[0]);

double Leaflength=arcLength(contours[0],1);

timeConsume=(GetTickCount()-start)*1.0/1000;

此時效率大大提高,時間消耗已經接近0,具體分析如表2所示。


封閉連續區域的面積和周長計算【2】--面積與周長

封閉連續區域的面積和周長計算【2】--面積與周長 

 這裏提到了OPenCV自帶輪廓相關的函數,順便給出繪製輪廓的相關代碼如下

////繪製出輪廓

//image=cv::imread("test2.bmp",1);

//cvtColor( image, image_gray, CV_BGR2GRAY );//變成灰度圖

//Mat dst = Mat::zeros(image.rows, image.cols, CV_8UC3);

//vector<Vec4i> hierarchy;

//findContours( image_gray, contours, hierarchy,       CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );

//int idx = 0;

//for( ; idx >=0; idx = hierarchy[idx][0] )//畫出所有的輪廓,idx爲索引

//{

//Scalar color( rand()&255, rand()&255, rand()&255 );

//drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );

//}

//namedWindow( "Components", 1 );

//imshow( "Components", dst );

//waitKey(0);

從表1細心的可以發現,用像素點統計的方法和鏈碼的方法在計算面積上差異比較大,在test1測試中差異所佔比例爲(386607-385016)/386607=0.41%,在test3測試中差異所佔比例爲(82376-81428)/82376=1.15%.

假設像素點爲矩形,放大像素點如圖4所示,有個物體覆蓋了三個像素帶,按照統計像素點個數的方法面積計算爲3. 而用鏈碼計算面積則爲2*2/2=2,此時明白統計像素點僅僅是統計像素點個數而不是計算面積,用像素點個數來逼近面積,當邊角比較多的時候這種差異會更加明顯。


源自:http://blog.sina.com.cn/s/blog_c144a0e40101aa9s.html

發佈了27 篇原創文章 · 獲贊 21 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章