幾何不變矩 Hu 矩
【原文部分轉載】:http://blog.csdn.net/wrj19860202/archive/2011/04/16/6327094.aspx
在連續情況下,映像函數為 ,那麼映像的p+q階幾何矩(標準矩)定義為:
p+q階中心距定義為:
其中 和 代表映像的重心,
對於離散的數位影像,採用求和號代替積分:
和 分別是映像的高度和寬度;
歸一化的中心距定義為:
;其中
(PS_yang: 此處的 ρ 的取值有爭議,不同文獻 [不變矩演算法研究.丁明躍.華科] 給了不同的公式。
主要爭議在於ρ後是否要加1。個人編程實踐發現,加1應該是正確的選擇。
個人在Hu矩原著:Visual Pattern Recognition by Moment Invariants 中沒能找到原始公式。手頭也沒有相關書籍的詳細解釋,所以,暫留做疑問。還望各位讀者指點。)
利用二階和三階歸一化中心矩構造了7個不變矩 :
這7個不變矩構成一組特徵量,Hu.M.K在1962年證明了他們具有旋轉,縮放和平移不變性。
實際上,在對圖片中物體的識別過程中,只有 和 不變性保持的比較好,其他的幾個不變矩帶來的誤差比較大,有學者認為只有基於二階矩的不變矩對二維物體的描述才是真正的具有旋轉、縮放和平移不變性( 和 剛好都是由二階矩組成的)。不過我沒有證明是否是真的事這樣的。
由Hu矩組成的特徵量對圖片進行識別,優點就是速度很快,缺點是識別率比較低,我做過手勢識別,對於已經分割好的手勢輪廓圖,識別率也就30%左右,對於紋理比較豐富的圖片,識別率更是不堪入眼,只有10%左右。這一部分原因是由於Hu不變矩只用到低階矩(最多也就用到三階矩),對於映像的細節未能很好的描述出來,導致對映像的描述不夠完整。
Hu不變矩一般用來識別映像中大的物體,對於物體的形狀描述得比較好,映像的紋理特徵不能太複雜,像識別水果的形狀,或者對於車牌中的簡單字元的識別效果會相對好一些。
由OPENCV提供計算中心距、歸一化中心距和hu矩的函數為:
void cvMoments(const CvArr*image, CvMoments*moments,int isBinary=0)double cvGetCentralMoment(CvMoments*moments,int x_order,int y_order)double cvGetNormalizedCentralMoment(CvMoments*moments,int x_order,int y_order);void cvGetHuMoments(CvMoments*moments,CvHuMoments*HuMoments);
其中cvMoments和上面的cvContourMoments是同一個函數。
同時OPENCV還提供了輸入映像直接進行hu矩匹配的函數是
double cvMatchShapes(const void*object1,const void*object2,int method,double parameter=0); 因此可以協助省掉中間的步驟。
HU矩的效果並不是很好,字母旋轉後的hu矩變化還是很大的。
附上個人代碼:
//*****************************////***yangxin_szu 2013_03_24***////經驗證,第一、第二矩特徵能較好地保持不變特性////*****************************////計算矩不變紋理特徵void My_Texture::Calculate_Moment_Fea(unsigned char* Img_Data ,int Img_H ,int Img_W){int i=0 ,j=0;unsigned char temp = 0;double m_00 =0 ,m_01 =0 ,m_10 =0;double X_c =0 ,Y_c =0 ,Center_x =0 ,Center_y =0;double H_00=0,H_02=0,H_03=0,H_11=0,H_12=0,H_20=0,H_21=0,H_30=0;float eta_02=0,eta_03=0,eta_11=0,eta_12=0,eta_20=0,eta_21=0,eta_30=0;//階矩for (i=0;i<Img_H;i++){for (j=0;j<Img_W;j++){temp = Img_Data[i*Img_W + j];m_00 = m_00 + (powf(i,0)*powf(j,0)*temp);m_01 = m_01 + (powf(i,0)*powf(j,1)*temp);m_10 = m_10 + (powf(i,1)*powf(j,0)*temp);}}X_c = m_10/m_00;Y_c = m_01/m_00;//中心矩for (i=0;i<Img_H;i++){for (j=0;j<Img_W;j++){temp = Img_Data[i*Img_W + j];Center_x = i - X_c;Center_y = j - Y_c;H_00 = H_00 + pow(Center_x,0)*pow(Center_y,0)*temp;H_02 = H_02 + pow(Center_x,0)*pow(Center_y,2)*temp;H_03 = H_03 + pow(Center_x,0)*pow(Center_y,3)*temp;H_11 = H_11 + pow(Center_x,1)*pow(Center_y,1)*temp;H_12 = H_12 + pow(Center_x,1)*pow(Center_y,2)*temp;H_20 = H_20 + pow(Center_x,2)*pow(Center_y,0)*temp;H_21 = H_21 + pow(Center_x,2)*pow(Center_y,1)*temp;H_30 = H_30 + pow(Center_x,3)*pow(Center_y,0)*temp;}}//矩的歸一化eta_02 = H_02/pow(H_00 ,2);eta_03 = H_03/pow(H_00 ,2.5);eta_11 = H_11/pow(H_00 ,2);eta_12 = H_12/pow(H_00 ,2.5);eta_20 = H_20/pow(H_00 ,2);eta_21 = H_21/pow(H_00 ,2.5);eta_30 = H_30/pow(H_00 ,2.5);//矩不變特徵m_mo_1 = eta_20 + eta_02;m_mo_2 = pow(eta_20 - eta_02,2) + 4*pow(eta_11,2);m_mo_3 = pow(eta_30 - 3*eta_12,2) + pow(3*eta_21 - eta_03,2);m_mo_4 = pow(eta_30 + eta_12,2) + pow(eta_21 + eta_03,2);m_mo_5 = (eta_30 - 3*eta_12)*(eta_03 + eta_21)*(pow(eta_30+eta_12,2) - 3*pow(eta_21+eta_03,2)) + (3*eta_12 - eta_03)*(eta_21+eta_30)*(3*pow(eta_30+eta_12,2)-pow(eta_21+eta_03,2));m_mo_6 = (eta_20 - eta_02)*(pow(eta_30+eta_12,2) - pow(eta_21+eta_03,2))+ 4*eta_11*(eta_30+eta_12)*(eta_03+eta_21);}