區域生長算法的基本思想是將有相似性質的像素點合並到一起。對每一個區域要先指定一個種子點作為生長的起點,然后將種子點周圍領域的像素點和種子點進行對比,將具有相似性質的點合並起來繼續向外生長,直到沒有滿足條件的像素被包括進來為止。這樣一個區域的生長就完成了。這個過程中有幾個關鍵的問題:
1 給定種子點(種子點如何選取?)
種子點的選取很多時候都采用人工交互的方法實現,也有用其他方式的,比如尋找物體並提取物體內部點或者利用其它算法找到的特征點作為種子點。
2 確定在生長過程中能將相鄰像素包括進來的准則
這個准則很重要:例如包括灰度值的差值;彩色圖像的顏色;梯度特征,包括梯度的方向和幅值特征。該點周圍的區域特征,例如harr特征,也就是區域像素和特征。
舉個例子:發在PAMI上的LSD直線檢測算法中的關鍵一步就是找line support regions.這個區域的查找就是利用區域生長法則,生長的條件就是梯度的方向角度。
上圖第一張圖是原始圖像,第二張圖就是計算梯度角度,第三章圖就是根據梯度角度區域生長的結果,相同顏色就是一個區域生長結果
這個是論文中區域生長的偽代碼。
上圖就是Harr特征,這個特征很有用,由於是區域特征,在圖像干擾很大的時候,能對感興趣的區域進行有效的提取。當然也可以作為生長的准則。
3 生長的停止條件
算法實現的步驟:
1> 創建一個空白的圖像(全黑);
2> 將種子點存入vector(或者stack)中,vector中存儲待生長的種子點;
3> 依次彈出種子點,一般從尾部彈出,也就是后進先出,並判斷種子點如周圍8領域的關系(生長規則),相似的點則作為下次生長的種子點;
4> vector中不存在種子點后就停止生長。
上代碼:
View Code

1 #include "stdafx.h" 2 #include <opencv2/opencv.hpp> 3 #include <vector> 4 #include <stack> 5 6 using namespace std; 7 using namespace cv; 8 9 10 11 void regiongrowth(IplImage* &inputimg,IplImage* &outputimg,CvPoint pt,int th) 12 { 13 14 CvPoint ptGrowing;//待生長點的位置 15 int nGrowLabel=0;//是否被標記 16 int nScrValue=0;//生長起始點的灰度值 17 int nCurValue=0;//當前生長點的灰度值 18 19 IplImage* Dstimg=cvCreateImage(cvGetSize(inputimg),8,1); 20 if (Dstimg==NULL) 21 { 22 printf("image read error too"); 23 return; 24 } 25 cvZero(Dstimg); 26 27 int DIR[8][2]={{-1,-1}, {0,-1}, {1,-1}, {1,0}, {1,1}, {0,1}, {-1,1}, {-1,0}}; 28 29 vector<CvPoint>vcGrowpt;//生長點的堆棧 30 vcGrowpt.push_back(pt);//將初始生長點壓入堆棧 31 32 //標記初始生長點 33 Dstimg->imageData[pt.x+pt.y*Dstimg->widthStep]=255; 34 nScrValue=inputimg->imageData[pt.x+pt.y*inputimg->widthStep]; 35 36 37 while(!vcGrowpt.empty()) 38 { 39 CvPoint curpt=vcGrowpt.back();//在堆棧中取出一個生長點 40 vcGrowpt.pop_back(); 41 42 for(int i=0;i<8;i++) 43 { 44 ptGrowing.x=curpt.x+DIR[i][0]; 45 ptGrowing.y=curpt.y+DIR[i][1]; 46 //檢查邊緣點 47 if(ptGrowing.x<0||ptGrowing.y<0||(ptGrowing.x>inputimg->width-1)||(ptGrowing.y>inputimg->height-1)) 48 continue; 49 nGrowLabel=Dstimg->imageData[ptGrowing.x+ptGrowing.y*Dstimg->widthStep]; 50 if (nGrowLabel==0)//表示還未標記過 51 { 52 nCurValue=inputimg->imageData[ptGrowing.x+ptGrowing.y*inputimg->widthStep]; 53 if(abs(nCurValue-nScrValue)<=th) 54 { 55 Dstimg->imageData[ptGrowing.x+ptGrowing.y*Dstimg->widthStep]=255; 56 vcGrowpt.push_back(ptGrowing); 57 58 } 59 } 60 61 } 62 63 64 } 65 cvCopy(Dstimg,outputimg); 66 cvReleaseImage(&Dstimg); 67 68 } 69 70 71 72 int _tmain(int argc, _TCHAR* argv[]) 73 { 74 75 IplImage* sourceimage=cvLoadImage("H:\\programm\\test.jpg",0); 76 77 if (sourceimage==NULL) 78 { 79 printf("image read error"); 80 } 81 82 83 84 IplImage* outputimg=cvCreateImage(cvGetSize(sourceimage),8,1); 85 IplImage* resultimg=cvCreateImage(cvGetSize(sourceimage),8,1); 86 cvZero(resultimg); 87 cvCopy(sourceimage,outputimg); 88 regiongrowth(sourceimage,outputimg,cvPoint(392,282),12); 89 cvAdd(outputimg,resultimg,resultimg); 90 91 regiongrowth(sourceimage,outputimg,cvPoint(587,195),8); 92 cvAdd(outputimg,resultimg,resultimg); 93 94 regiongrowth(sourceimage,outputimg,cvPoint(707,356),8); 95 cvAdd(outputimg,resultimg,resultimg); 96 97 regiongrowth(sourceimage,outputimg,cvPoint(546,549),10); 98 cvAdd(outputimg,resultimg,resultimg); 99 100 regiongrowth(sourceimage,outputimg,cvPoint(310,435),10); 101 cvAdd(outputimg,resultimg,resultimg); 102 103 cvNamedWindow("source",0); 104 cvShowImage("source",sourceimage); 105 106 cvNamedWindow("result",0); 107 cvShowImage("result",resultimg); 108 cvWaitKey(0); 109 110 cvReleaseImage(&sourceimage); 111 cvReleaseImage(&outputimg); 112 cvReleaseImage(&resultimg); 113 system("pause"); 114 return 0; 115 }
這個代碼實現結果,就是提取下面左圖中的5個區域,右邊為提取結果,由於用的是灰度差作為生長條件,效果一般般。
參考文章:http://blog.csdn.net/robin__chou/article/details/50071313