OpenCV之meanshift分割詳解

2021-08-04 14:47:08 字數 3572 閱讀 2093

用meanshift做影象平滑和分割,其實是一回事。其本質是經過迭代,將收斂點的畫素值代替原來的畫素值,從而去除了區域性相似的紋理,同時保留了邊緣等差異較大的特徵。

opencv中自帶有基於meanshift的分割方法pyrmeanshiftfiltering()。由函式名pyrmeanshiftfiltering可知,這裡是將meanshift演算法和影象金字塔相結合用來分割的。

[cpp]view plain

copy

"font-size:18px;"

>

void

pyrmeanshiftfiltering( 

const

cvarr* srcarr,          

//輸入影象

cvarr* dstarr,        //輸出影象

double

sp,            

//顏色域半徑

double

sr,            

//空間域半徑

intmax_level,     

//金字塔最大層數                    

cvtermcriteria termcrit )     //迭代終止條件

要求輸入和輸出影象都是cv_8uc3型別,而且兩者尺寸一樣。實際上並不需要去先定義dstarr,因為程式裡會將srcarr的格式賦值給dstarr。

termcrit有三種情況,迭代次數、迭代精度和兩者同時滿足。預設為迭代次數為5同時迭代精度為1。termcrit是個結構體,其結構如下

[cpp]view plain

copy

"font-size:18px;"

>

typedef

struct

cvtermcriteria  

cvtermcriteria;

使用pyrmeanshiftfiltering()進行影象分割非常簡單,只需要定義sp0,sr,max_level和termrit,然後呼叫pyrmeanshiftfiltering()就行了。

在實際操作時,為了使分割的結果顯示得更明顯,經常用floodfill( )將不同連通域塗上不同的顏色。具體情況參看下 面的例項。

來看看opencv自帶的乙個用meanshift進行分割的例子

原程式見   「  .\opencv249\sources\samples\cpp\meanshift_segmentation.cpp」

[cpp]view plain

copy

"font-size:18px;"

>#include 

"opencv2/highgui/highgui.hpp"

#include "opencv2/core/core.hpp"

#include "opencv2/imgproc/imgproc.hpp"

#include 

using

namespace

cv;  

using

namespace

std;  

static

void

help(

char

** argv)  

//this colors the segmentations

static

void

floodfillpostprocess( mat& img, 

const

scalar& colordiff=scalar::all(1) )  

}  }  }  

string winname = "meanshift"

;  int

spatialrad, colorrad, maxpyrlevel;  

mat img, res;  

static

void

meanshiftsegmentation( 

int, 

void

* )  

intmain(

intargc, 

char

** argv)  

程式很簡單,來看看floodfill()函式,有兩種形式

int floodfill( inputoutputarray image, point seedpoint, scalar newval, cv_out rect* rect=0, scalar lodiff=scalar(), scalar updiff=scalar(), int flags=4 );

int floodfill( inputoutputarray image,  inputoutputarray mask, point seedpoint,  scalar newval, 

cv_out rect* rect=0,  scalar lodiff=scalar(),  scalar updiff=scalar(),  int flags=4 );

inputoutputarray image    輸入輸出影象,要求格式為1通道或3通道,8位或浮點

inputoutputarray mask   掩膜,比image的寬和高各大兩畫素點

point seedpoint    填充的起始點

scalar newval   畫素點被染色的值

cv_out rect* rect=0  可選引數,設定floodfill()要重繪區域的最小邊界矩形區域

scalar lodiff=scalar()  定義當前畫素值與起始點畫素值的亮度或顏色負差的最大值

scalar updiff=scalar()  定義當前畫素值與起始點畫素值的亮度或顏色正差的最大值

flags 操作標誌符    

程式結果

處理後一些細小的紋理都平滑掉了,例如圖中綠色線條所指示的區域。未填充時,很多地方看得並不明顯,填充後就能明顯看出差別來了。填充後的圖很好地體現了meanshift聚類的思想!

再來看一組更「誇張」的效果圖

使用meanshift方法進行處理後,原來的三個矩形區域消失了!平滑掉了!

meanshift演算法的兩個關鍵引數是空間域半徑sr和顏色域半徑sp,別說max_level,那是構建影象金字塔的引數好

吧。最後,我們來看看sr和sp對結果的影響。

顯然顏色域半徑sp對結果的影響比空間域半徑sr對結果的影響大。sp和sr越小,細節保留得越多,sp和sr越大,平滑力度越大。邊緣和顏色突變的區域的特徵保留的較好。因為meanshift要對每個畫素點進行操作,所以演算法的時間花銷很大。

opencv之HoughCircle引數解釋

void houghcircles inputarray image,outputarray circles,int method,double dp,double mindist,double param1 100,double param2 100,int minradius 0,int max...

Opencv學習之cvCreateMat的用法

cvcreatemat的用法 分配矩陣空間 cvmat cvcreatemat int rows int cols int type type 矩陣元素型別,格式為cv s u f c 如 cv 8uc1 表示8位無符號單通道矩陣 cv 32sc2 表示32位有符號雙通道矩陣 例程 cvmat m ...

opencv之邊緣檢測

canny檢測 發展 canny 的目標是找到乙個最優的邊緣檢測演算法,最優邊緣檢測的含義是 好的檢測 演算法能夠盡可能多地標識出影象中的實際邊緣。好的定位 標識出的邊緣要盡可能與實際影象中的實際邊緣盡可能接近。最小響應 影象中的邊緣只能標識一次,並且可能存在的影象雜訊不應標識為邊緣。為了滿足這些要...