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