參考
- 【圖像算法】圖像特徵:幾何不變矩–Hu矩 - SkySeraph - 博客園: https://www.cnblogs.com/skyseraph/archive/2011/07/19/2110183.html
- 圖像的矩特徵 - ☆Ronny丶 - 博客園: https://www.cnblogs.com/ronny/p/3985810.html
- 《圖像處理、分析與機器視覺》
- 《數字圖像處理》岡薩雷斯–第十一章-不變矩
一、矩的概念
圖像識別的一個核心問題是圖像的特徵提取,簡單描述即爲用一組簡單的數據(圖像描述量)來描述整個圖像,這組數據越簡單越有代表性越好。良好的特徵不受光線、噪點、幾何形變的干擾。圖像識別發展幾十年,不斷有新的特徵提出,而圖像不變矩就是其中一個。
針對於一幅圖像,我們把像素的座標看成是一個二維隨機變量(X,Y)(X,Y),那麼一幅灰度圖像可以用二維灰度密度函數來表示,因此可以用矩來描述灰度圖像的特徵。
不變矩(Invariant Moments)是一處高度濃縮的圖像特徵,具有平移、灰度、尺度、旋轉不變性。M.K.Hu在1961年首先提出了不變矩的概念。1979年M.R.Teague根據正交多項式理論提出了Zernike矩。下面主要介紹這兩種矩特徵的算法原理與實現。
二、Hu矩
2.1 (p+q)階不變矩的定義
對於灰度分佈爲的圖像,其階矩定義爲:
其階中心矩定義爲:
其中,矩心爲:
由於數字圖像屬於離散化數據,離散狀態下,的階普通矩和中心矩的公式如下:
離散化後的矩心x0與y0的計算方法同連續狀態下的計算公式。
p、q即在x、y這兩個像素位置上的多少次方。在p、q不爲0時,求可以看作 x的p次方 與 y的q次方 作爲權重疊加到當前x、y位置上的灰度值,然後累加。當求時,可知僅爲圖像的灰度值進行累加。
2.2 歸一化中心距
當圖像發生變化,如平移、旋轉等,也發生變化。而由於式與中心有關,其對平移不敏感,但依舊對旋轉敏感。爲了解決這個問題,這裏提出歸一化中心矩:
式中:
歸一化中心矩使用的是中心矩進行的計算。可以注意到,歸一化中心矩計算時使用的從數值上來看,就等同於。
2.3 Hu矩定義
Hu利用二階和三階中心矩(即)構造了7個不變矩,這7個不變矩構成一組特徵量,Hu.M.K在1962年證明了他們具有旋轉,縮放和平移不變性,它們在連續圖像條件下可以保持平移、縮放和旋轉不變。具體定義如下:
2.4 Hu矩計算代碼
參考自:【圖像算法】圖像特徵:幾何不變矩–Hu矩 - SkySeraph - 博客園,修正了部分格式問題與變量名,方便對照上面進行查看。
double I[7] = {0}; //HU不變矩
bool HuMoment(IplImage* img)
{
int bmpWidth = img->width;
int bmpHeight = img->height;
int bmpStep = img->widthStep;
int bmpChannels = img->nChannels;
uchar* pBmpBuf = (uchar*)img->imageData;
double u00=0,u11=0,u20=0,u02=0,u30=0,u03=0,u12=0,u21=0; //中心矩
double x0=0,y0=0; //計算中心距時所使用的臨時變量(x-x')
double y20=0,y02=0,y11=0,y30=0,y03=0,y12=0,y21=0; //規範化後的中心矩
double t1=0,t2=0,t3=0,t4=0,t5=0; //臨時變量,
int center_x0=0,center_y0=0; //矩心
int i,j; //循環變量
// 獲得圖像的區域重心(普通矩)
double m10=0,m01=0,m00=0; //0階矩和1階矩
for(j=0;j<bmpHeight;j++)//y
{
for(i=0;i<bmpWidth;i++)//x
{
m10+=i*pBmpBuf[j*bmpStep+i];
m01+=j*pBmpBuf[j*bmpStep+i];
m00+=pBmpBuf[j*bmpStep+i];
}
}
center_x0=(int)(m10/m00+0.5);
center_y0=(int)(m01/m00+0.5);
// 計算二階、三階矩(中心矩)
u00=m00; //歸一化中心矩計算時使用的u00從數值上來看,就等同於m00。
for(j=0;j<bmpHeight;j++)
{
for(i=0;i<bmpWidth;i++)//x
{
x0=(i-center_x0);
y0=(j-center_x0);
u11+=x0*y0*pBmpBuf[j*bmpStep+i];
u20+=x0*x0*pBmpBuf[j*bmpStep+i];
u02+=y0*y0*pBmpBuf[j*bmpStep+i];
u03+=y0*y0*y0*pBmpBuf[j*bmpStep+i];
u30+=x0*x0*x0*pBmpBuf[j*bmpStep+i];
u12+=x0*y0*y0*pBmpBuf[j*bmpStep+i];
u21+=x0*x0*y0*pBmpBuf[j*bmpStep+i];
}
}
// 計算規範化後的中心矩: uij/pow(u00,((i+j+2)/2) , 而u00 = m00,故直接用m00
y20=u20/pow(m00,2);
y02=u02/pow(m00,2);
y11=u11/pow(m00,2);
y30=u30/pow(m00,2.5);
y03=u03/pow(m00,2.5);
y12=u12/pow(m00,2.5);
y21=u21/pow(m00,2.5);
// 計算中間變量
t1=(y20-y02);
t2=(y30-3*y12);
t3=(3*y21-y03);
t4=(y30+y12);
t5=(y21+y03);
// 計算不變矩
I[0]=y20+y02;
I[1]=t1*t1+4*y11*y11;
I[2]=t2*t2+t3*t3;
I[3]=t4*t4+t5*t5;
I[4]=t2*t4*(t4*t4-3*t5*t5)+t3*t5*(3*t4*t4-t5*t5);
I[5]=t1*(t4*t4-t5*t5)+4*y11*t4*t5;
I[6]=t3*t4*(t4*t4-3*t5*t5)-t2*t5*(3*t4*t4-t5*t5);
return true;
}