图像形状特征(七)--Zernike矩
原文:http://blog.csdn.net/wrj19860202/article/details/6334275
?
Zernike在1934年引入了一組定義在單位圓 上的復(fù)值函數(shù)集{ },{ }具有完備性和正交性,使得它可以表示定義在單位圓盤(pán)內(nèi)的任何平方可積函數(shù)。其定義為:
表示原點(diǎn)到點(diǎn) 的矢量長(zhǎng)度; 表示矢量 與 軸逆時(shí)針?lè)较虻膴A角。
是實(shí)值徑向多項(xiàng)式:
稱(chēng)為Zernike多項(xiàng)式。
Zernike多項(xiàng)式滿(mǎn)足正交性:
其中
為克羅內(nèi)克符號(hào),
是 的共軛多項(xiàng)式。
由于Zernike多項(xiàng)式的正交完備性,所以在單位圓內(nèi)的任何圖像 都可以唯一的用下面式子來(lái)展開(kāi):
式子中 就是Zernike矩,其定義為:
注意式子中 和 采用的是不同的坐標(biāo)系( 采用直角坐標(biāo),而 采用的極坐標(biāo)系,在計(jì)算的時(shí)候要進(jìn)行坐標(biāo)轉(zhuǎn)換)
對(duì)于離散的數(shù)字圖像,可將積分形式改為累加形式:
我們?cè)谟?jì)算一副圖像的Zernike矩時(shí),必須將圖像的中心移到坐標(biāo)的原點(diǎn),將圖像的像素點(diǎn)映射到單位圓內(nèi),由于Zernike矩具有旋轉(zhuǎn)不變性,我們可以將 作為圖像的不變特征,其中圖像的低頻特征有p值小的 提取,高頻特征由p值高的 提取。從上面可以看出,Zernike矩可以構(gòu)造任意高階矩。
由于Zernike矩只具有旋轉(zhuǎn)不變性,不具有平移和尺度不變性,所以要提前對(duì)圖像進(jìn)行歸一化,我們采用標(biāo)準(zhǔn)矩的方法來(lái)歸一化一副圖像,標(biāo)準(zhǔn)矩定義為:
,
由標(biāo)準(zhǔn)矩我們可以得到圖像的"重心",
我們將圖像的"重心"移動(dòng)到單位圓的圓心(即坐標(biāo)的原點(diǎn)),便解決了平移問(wèn)題。
我們知道 表征了圖像的"面積",歸一圖像的尺度無(wú)非就是把他們的大小變?yōu)橐恢碌?#xff0c;(這里的大小指的是圖像目標(biāo)物的大小,不是整幅圖像的大小,"面積"也是目標(biāo)物的"面積")。
所以,對(duì)圖像進(jìn)行變換 就可以達(dá)到圖像尺寸一致的目的。
綜合上面結(jié)果,對(duì)圖像進(jìn)行 變換,最終圖像 的Zernike矩就是平移,尺寸和旋轉(zhuǎn)不變的。
Zernike 不變矩相比 Hu 不變矩識(shí)別效果會(huì)好一些,因?yàn)樗枋隽藞D像更多的細(xì)節(jié)內(nèi)容,特別是高階矩,但是由于 Zernike 不變矩計(jì)算時(shí)間比較長(zhǎng),所以出現(xiàn)了很多快速的算法,大家可以 google 一下。
用 Zernike 不變矩來(lái)識(shí)別手勢(shì)輪廓,識(shí)別率大約在 40%~50% 之間,跟 Hu 不變矩一樣, Zernike 不變矩一般用來(lái)描述目標(biāo)物形狀占優(yōu)勢(shì)的圖像,不適合用來(lái)描述紋理豐富的圖像,對(duì)于紋理圖像,識(shí)別率一般在 20%~30% 左右,很不占優(yōu)勢(shì)。
?
C++代碼如下:/*計(jì)算一行的像素個(gè)數(shù)
imwidth:圖像寬度
deep:圖像深度(8位灰度圖為1,24位彩色圖為3)
*/
#define bpl(imwidth, deep) ((imwidth*deep*8+31)/32*4)
/*獲取像素值
psrcBmp:圖像數(shù)據(jù)指針
nsrcBmpWidth:圖像寬度,以像素為單位
x,y:像素點(diǎn)
deep:圖像的位數(shù)深度,(1表示8位的灰度圖,3表示24位的RGB位圖)
*/
COLORREF J_getpixel( const BYTE *psrcBmp, const int nsrcBmpWidth, const int x, const int y, int deep = 3)
{if (deep == 3){return RGB(*(psrcBmp + x*3 + y*bpl(nsrcBmpWidth, deep) + 2 ) , *(psrcBmp + x*3 + y*bpl(nsrcBmpWidth, deep) + 1 ) , *(psrcBmp + x*3 + y*bpl(nsrcBmpWidth, deep) +0 ));}else if (deep == 1){return *(psrcBmp + x + y*bpl(nsrcBmpWidth, deep));}
}//獲取標(biāo)準(zhǔn)矩(只支持8位灰度圖)
void GetStdMoment(BYTE *psrcBmp , int nsrcBmpWidth,int nsrcBmpHeight,double *m)
{for ( int p = 0 ; p < 2 ; p++ )for ( int q = 0 ; q < 2 ; q++ ){if( p == 1 && q == 1)break;for ( int y = 0 ; y < nsrcBmpHeight ; y++ )for ( int x = 0 ; x < nsrcBmpWidth ; x++ )m[p*2+q] += (pow( (double)x , p ) * pow( (double)y , q ) * J_getpixel(psrcBmp , nsrcBmpWidth , x ,y, 1));}
}//階乘
double Factorial( int n )
{if( n < 0 )return -1;double m = 1;for(int i = 2 ; i <= n ; i++){m *= i;}return m;
}//階乘數(shù),計(jì)算好方便用,提高速度
double factorials[11] = {1 , 1 , 2 , 6 , 24 , 120 , 720 , 5040 , 40320 , 362880 , 39916800};//把圖像映射到單位圓,獲取像素極坐標(biāo)半徑
double GetRadii(int nsrcBmpWidth,int nsrcBmpHeight,int x0,int y0,int x,int y)
{double lefttop = sqrt(((double)0 - x0)*(0 - x0) + (0 - y0)*(0 - y0));double righttop = sqrt(((double)nsrcBmpWidth - 1 - x0)*(nsrcBmpWidth - 1 - x0) + (0 - y0)*(0 - y0));double leftbottom = sqrt(((double)0 - x0)*(0 - x0) + (nsrcBmpHeight - 1 - y0)*(nsrcBmpHeight - 1 - y0));double rightbottom = sqrt(((double)nsrcBmpWidth - 1 - x0)*(nsrcBmpWidth - 1 - x0) + (nsrcBmpHeight - 1 - y0)*(nsrcBmpHeight - 1 - y0));double maxRadii = lefttop;maxRadii < righttop ? righttop : maxRadii;maxRadii < leftbottom ? leftbottom : maxRadii;maxRadii < rightbottom ? rightbottom : maxRadii;double Radii = sqrt(((double)x - x0)*(x - x0) + (y - y0)*(y - y0))/maxRadii;if(Radii > 1){Radii = 1;}return Radii;
}//把圖像映射到單位圓,獲取像素極坐標(biāo)角度
double GetAngle(int nsrcBmpWidth,int nsrcBmpHeight,int x,int y)
{double o;double dia = sqrt((double)nsrcBmpWidth*nsrcBmpWidth + nsrcBmpHeight*nsrcBmpHeight);int x0 = nsrcBmpWidth / 2;int y0 = nsrcBmpHeight / 2;double x_unity = (x - x0)/(dia/2); double y_unity = (y - y0)/(dia/2);if( x_unity == 0 && y_unity >= 0 )o=pi/2;else if( x_unity ==0 && y_unity <0)o=1.5*pi;elseo=atan( y_unity / x_unity );if(o*y<0) //第三象限o=o+pi;return o;
}//Zernike不變矩
J_GetZernikeMoment(BYTE *psrcBmp , int nsrcBmpWidth,int nsrcBmpHeight,double *Ze )
{double R[count][count] = {0.0};double V[count][count] = {0.0};double M[4] = {0.0};GetStdMoment(psrcBmp , nsrcBmpWidth , nsrcBmpHeight , M);int x0 = (int)(M[2]/M[0]+0.5);int y0 = (int)(M[1]/M[0]+0.5);for(int n = 0 ; n < count ; n++){for (int m = 0 ; m < count ; m++){//優(yōu)化算法,只計(jì)算以下介數(shù)if( (n == 1 && m == 0) ||(n == 1 && m == 1) ||(n == 2 && m == 0) ||(n == 2 && m == 1) ||(n == 2 && m == 2) ||(n == 3 && m == 0) ||(n == 3 && m == 1) ||(n == 3 && m == 2) ||(n == 3 && m == 3) ||(n == 4 && m == 0) ||(n == 4 && m == 1) ||(n == 4 && m == 2) ||(n == 4 && m == 3) ||(n == 4 && m == 4)){for(int y = 0 ; y < nsrcBmpHeight ; y++){for (int x = 0 ; x < nsrcBmpWidth ; x++){for(int s = 0 ; (s <= (n - m)/2 ) && n >= m ; s++){R[n][m] += pow( -1.0, s )* ( n - s > 10 ? Factorial( n - s ) : factorials[ n - s ] )* pow( GetRadii( nsrcBmpWidth, nsrcBmpHeight, x0, y0, x, y ), n - 2 * s )/ ( ( s > 10 ? Factorial( s ) : factorials[ s ] )* ( ( n + m ) / 2 - s > 10 ? Factorial( ( n + m ) / 2 - s ) : factorials[ ( n + m ) / 2 - s ] )* ( ( n - m ) / 2 - s > 10 ? Factorial( ( n - m ) / 2 - s ) : factorials[ ( n - m ) / 2 - s ] ) );}Ze[ n * count + m ] += R[ n ][ m ]* J_getpixel( psrcBmp, nsrcBmpWidth, x ,y, 1)* cos( m * GetAngle( nsrcBmpWidth, nsrcBmpHeight, x, y) );//實(shí)部V[n][m] += R[ n ][ m ] * J_getpixel( psrcBmp, nsrcBmpWidth, x, y, 1)* sin( m * GetAngle( nsrcBmpWidth, nsrcBmpHeight, x, y ) );//虛部R[n][m] = 0.0;}}*(Ze+n*count + m) = sqrt( (*(Ze+n*count + m))*(*(Ze+n*count + m)) + V[n][m]*V[n][m] )*(n+1)/pi/M[0];}}}
}
?
?
?
總結(jié)
以上是生活随笔為你收集整理的图像形状特征(七)--Zernike矩的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: RTP有效负载(载荷)类型 (RTP P
- 下一篇: (一)GNURadio3.9 安装教程