天天看點

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

目錄

  • 轉載本文請注明詳細位址
  • 本文介紹了矩和圖像矩的含義
  • 本文介紹了不變矩的計算、應用
  • 本文介紹了如何計算圖像相似度

一、思維導圖

二、普通矩的定義

1、零階矩

2、二階矩

3、二階以上矩

4、怎麼判斷是幾階矩

三、什麼是圖像矩?

四、hu不變矩(cv2.humoments())

1、幾何矩

幾何矩前幾階的意義

2、中心矩(決定了平移不變性)

3、歸一化中心矩(決定了尺度不變性)

4、hu不變矩計算(決定了旋轉不變性)

5、hu不變矩的性質

6、hu不變矩的應用與意義

7、适用條件

五、Python+opencv實作不變矩計算

1、自帶函數cv2.moments()和cv2.humoments()

2、自定義函數

3、結果

4、 網絡上的典型例子

六、形狀相似度計算(cv2.matchshapes())

參數解析:

距離計算方法

自定義距離計算方法

一、思維導圖

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

二、普通矩的定義

1、零階矩

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

2、二階矩

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

3、二階以上矩

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

對于三階或三階以上矩,使用圖像在軸或軸上的投影比使用圖像本身的描述更友善。 

三階矩:投影扭曲,描述了圖像投影的扭曲程度。扭曲是一個經典統計量,用來衡量關于均值對稱分布的偏差程度。 

四階矩:投影峰度,峰度是一個用來測量分布峰度的經典統計量。可以計算峰度系數。當峰度系數為0時,表示高斯分布;當峰度系數小于0時,表示平坦的少峰分布;當峰度系數大于0時,表示狹窄的多峰分布。 

4、怎麼判斷是幾階矩

在計算矩的表達式中,将x,y的指數進行相加,得到的值就是圖像矩的階數

三、什麼是圖像矩?

最初接觸的矩的概念就是力矩的概念,力與距離的乘積叫做力矩。圖像矩因為涉及到兩個距離x,y,是以是和兩個距離、一個像素強度(灰階值有關),具體定義如下:

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

其中:M、N分别是圖像的長寬,f是對應像素點的灰階值

四、hu不變矩(cv2.humoments())

1、幾何矩

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

幾何矩前幾階的意義

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

2、中心矩(決定了平移不變性)

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

3、歸一化中心矩(決定了尺度不變性)

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

比較大的争議是在r的求值上,是否加上1,一般情況下加上1會結果準确些

4、hu不變矩計算(決定了旋轉不變性)

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

5、hu不變矩的性質

圖像形狀平移不變性

圖像形狀尺度不變性

圖像形狀旋轉不變性

6、hu不變矩的應用與意義

圖像形狀比對

圖像形狀區分

圖像形狀相似度計算

7、适用條件

适用于紋理不複雜的圖像

五、Python+opencv實作不變矩計算

1、自帶函數cv2.moments()和cv2.humoments()

前者輸入的是灰階值圖像,後者輸入的是由幾何矩、中心矩、歸一化的中心矩組成的一個字典

import cv2
import numpy as np
np.set_printoptions(suppress=True)#定義輸出的精度


def sys_moments(img):
    '''
    opencv_python自帶求矩以及不變矩的函數
    :param img: 灰階圖像,對于二值圖像來說就隻有兩個灰階0和255
    :return: 傳回以10為底對數化後的hu不變矩
    '''
    moments = cv2.moments(img)#傳回的是一個字典,三階及以下的幾何矩(mpq)、中心矩(mupq)和歸一化的矩(nupq)
    humoments = cv2.HuMoments(moments)#根據幾何矩(mpq)、中心矩(mupq)和歸一化的矩(nupq)計算出hu不變矩
    # 因為直接計算出來的矩可能很小或者很大,是以取對數好比較,這裡的對數底數為e,通過對數除法的性質将其轉換為以10為底的對數,一般是負值,是以加一個負号将其變為正的
    humoment = -(np.log(np.abs(humoments)))/np.log(10)
    return humoment
           

2、自定義函數

有兩個前面這個是在求(p+q)階中心矩的時候采用了一些推導公式,後面那個是嚴格按照公式來的,建議看後面那個

def def_moments(img_gray):
    '''
    自定義求矩函數,主要是根據公式将一個個參數求出
    :param img_gray:  灰階圖像,對于二值圖像來說就隻有兩個灰階0和255
    :return: 傳回以10為底對數化後的hu不變矩
    '''
    '''
        由于7個不變矩的變化範圍很大,為了便于比較,可利用取對數的方法進行資料壓縮;
        同時考慮到不變矩有可能出現負值的情況,是以,在取對數之前先取絕對值
        經修正後的不變矩特征具有平移 、旋轉和比例不變性
    '''
    # 标準矩定義為m_pq = sumsum(x^p * y^q * f(x, y))其中f(x,y)為像素點處的灰階值
    row, col = img_gray.shape
    # 計算圖像的0階幾何矩
    m00 = img_gray.sum()
    ##初始化一到三階幾何矩
    #計算一階矩陣
    m10 = m01 = 0
    # 計算圖像的二階、三階幾何矩
    m11 = m20 = m02 = m12 = m21 = m30 = m03 = 0
    for i in range(row):
        m10 += (i * img_gray[i]).sum()#sum表示将一行的灰階值進行相加
        m20 += (i ** 2 * img_gray[i]).sum()
        m30 += (i ** 3 * img_gray[i]).sum()
        for j in range(col):
            m11 += i * j * img_gray[i][j]
            m12 += i * j ** 2 * img_gray[i][j]
            m21 += i ** 2 * j * img_gray[i][j]
    for j in range(col):
        m01 += (j * img_gray[:, j]).sum()
        m02 += (j ** 2 * img_gray[:, j]).sum()
        m30 += (j ** 3 * img_gray[:, j]).sum()
    # 由标準矩我們可以得到圖像的"重心"
    u10 = m10 / m00
    u01 = m01 / m00
    # 計算圖像的二階中心矩、三階中心矩
    y00 = m00
    y10 = y01 = 0
    y11 = m11 - u01 * m10
    y20 = m20 - u10 * m10
    y02 = m02 - u01 * m01
    y30 = m30 - 3 * u10 * m20 + 2 * u10 ** 2 * m10
    y12 = m12 - 2 * u01 * m11 - u10 * m02 + 2 * u01 ** 2 * m10
    y21 = m21 - 2 * u10 * m11 - u01 * m20 + 2 * u10 ** 2 * m01
    y03 = m03 - 3 * u01 * m02 + 2 * u01 ** 2 * m01
    # 計算圖像的歸一化中心矩
    n20 = y20 / m00 ** 2
    n02 = y02 / m00 ** 2
    n11 = y11 / m00 ** 2
    n30 = y30 / m00 ** 2.5
    n03 = y03 / m00 ** 2.5
    n12 = y12 / m00 ** 2.5
    n21 = y21 / m00 ** 2.5
    # 計算圖像的七個不變矩
    h1 = n20 + n02
    h2 = (n20 - n02) ** 2 + 4 * n11 ** 2
    h3 = (n30 - 3 * n12) ** 2 + (3 * n21 - n03) ** 2
    h4 = (n30 + n12) ** 2 + (n21 + n03) ** 2
    h5 = (n30 - 3 * n12) * (n30 + n12) * ((n30 + n12) ** 2 - 3 * (n21 + n03) ** 2) + (3 * n21 - n03) * (n21 + n03) \
                                                                                     * (3 * (n30 + n12) ** 2 - (
        n21 + n03) ** 2)
    h6 = (n20 - n02) * ((n30 + n12) ** 2 - (n21 + n03) ** 2) + 4 * n11 * (n30 + n12) * (n21 + n03)
    h7 = (3 * n21 - n03) * (n30 + n12) * ((n30 + n12) ** 2 - 3 * (n21 + n03) ** 2) + (3 * n12 - n30) * (n21 + n03) \
                                                                                     * (3 * (n30 + n12) ** 2 - (
        n21 + n03) ** 2)
    inv_m7 = [h1, h2, h3, h4, h5, h6, h7]
    humoments = np.log(np.abs(inv_m7))
    return humoments


def main():
    img = cv2.imread('roi.png',0)
    sys_humoments = sys_moments(img)
    def_humoments = def_moments(img)
    print('自帶函數:\n',sys_humoments)
    print('自定義函數:\n',def_humoments)

if __name__ == '__main__':
    main()
           
def def_moments(img_gray):
	'''
	自定義求矩函數,主要是根據公式将一個個參數求出
	:param img_gray:  灰階圖像,對于二值圖像來說就隻有兩個灰階0和255
	:return: 傳回以10為底對數化後的hu不變矩
	'''
	'''
		由于7個不變矩的變化範圍很大,為了便于比較,可利用取對數的方法進行資料壓縮;
		同時考慮到不變矩有可能出現負值的情況,是以,在取對數之前先取絕對值
		經修正後的不變矩特征具有平移 、旋轉和比例不變性
	'''
	# 标準矩定義為m_pq = sumsum(x^p * y^q * f(x, y))其中f(x,y)為像素點處的灰階值
	row, col = img_gray.shape
	# 計算圖像的0階幾何矩
	m00 = 0.0
	##初始化一到三階幾何矩
	# 計算一階矩陣
	m10 = m01 = 0.0
	# 計算圖像的二階、三階幾何矩
	m11 = m20 = m02 = m12 = m21 = m30 = m03 = 0.0
	for i in range(row):
		for j in range(col):
			m00 += img_gray[i][j]
			m10 += i*img_gray[i][j]
			m20 += i**2*img_gray[i][j]
			m30 += i**3*img_gray[i][j]
			m11 += i * j * img_gray[i][j]
			m12 += i * j ** 2 * img_gray[i][j]
			m21 += i ** 2 * j * img_gray[i][j]
	for j in range(col):
		for i in range(row):
			m01 += (j * img_gray[i, j])
			m02 += (j ** 2 * img_gray[i, j])
			m03 += (j ** 3 * img_gray[i, j])
	# 由标準矩我們可以得到圖像的"重心"
	u10 = m10 / m00
	u01 = m01 / m00
	# 計算圖像的二階中心矩、三階中心矩
	y00 = y10 = y01 = y11 = y20 = y02 = y30 = y12 = y21 = y03 = 0.0
	for x in range(row):
		for y in range(col):
			x_ = x - u10
			y_ = y - u01
			y00 += img_gray[x][y]
			y10 += x_*img_gray[x][y]
			y01 += y_*img_gray[x][y]
			y11 += x_*y_*img_gray[x][y]
			y02 += y_**2*img_gray[x][y]
			y20 += x_**2*img_gray[x][y]
			y03 += y_**3*img_gray[x][y]
			y30 += x_**3*img_gray[x][y]
			y12 += x_*y_**2*img_gray[x][y]
			y21 += x_**2*y_*img_gray[x][y]
	# 計算圖像的歸一化中心矩
	n20 = y20 / (y00 ** 2)
	n02 = y02 / (y00 ** 2)
	n11 = y11 / (y00 ** 2)
	n30 = y30 / (y00 ** 2.5)
	n03 = y03 / (y00 ** 2.5)
	n12 = y12 / (y00 ** 2.5)
	n21 = y21 / (y00 ** 2.5)
	# 計算圖像的七個不變矩
	h1 = n20 + n02
	h2 = (n20 - n02) ** 2 + 4 * (n11 ** 2)
	h3 = (n30 - 3 * n12) ** 2 + (3 * n21 - n03) ** 2
	h4 = (n30 + n12) ** 2 + (n21 + n03) ** 2
	h5 = (n30 - 3 * n12) * (n30 + n12) * ((n30 + n12) ** 2 - 3 * (n21 + n03) ** 2) + (3 * n21 - n03) * (n21 + n03) \
																					 * (3 * (n30 + n12) ** 2 - (
		n21 + n03) ** 2)
	h6 = (n20 - n02) * ((n30 + n12) ** 2 - (n21 + n03) ** 2) + 4 * n11 * (n30 + n12) * (n21 + n03)
	h7 = (3 * n21 - n03) * (n30 + n12) * ((n30 + n12) ** 2 - 3 * (n21 + n03) ** 2) + (3 * n12 - n30) * (n21 + n03) \
																					 * (3 * (n30 + n12) ** 2 - (
		n21 + n03) ** 2)
	inv_m7 = [h1, h2, h3, h4, h5, h6, h7]
	humoments = np.log(np.abs(inv_m7))
	return humoments
           

3、結果

結果不是很理想,可能在編寫計算中心矩和不變矩的公式的時候出現了錯誤,可以自行糾正

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

4、 網絡上的典型例子

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

可以看到,圖像K0.png就是字母K,而S0.png就是字母S。接下來,我們将字母S移到S1中。在s2。png中移動+縮放。我們添加了一些旋轉使S3.png,并進一步翻轉圖像使S4.png。

注意,S0、S1、S2、S3和S4的所有Hu矩的值都很接近,除了S4的最後Hu矩的符号被翻轉了。另外,注意它們都與K0非常不同。

六、形狀相似度計算(cv2.matchshapes())

我們将學習如何使用Hu矩來找出兩個圖形之間的距離。如果距離小,形狀的外觀接近,如果距離大,形狀的外觀較遠。

OpenCV提供了一個名為matchShapes的實用程式函數,它可以擷取兩幅圖像(或輪廓),并使用Hu矩查找它們之間的距離。是以,你不需要明确地計算Hu力矩。簡單地對圖像進行二值化并使用matchShapes。

dist = matchShapes(contour1, contour2, method, parameter)
           

這裡是利用兩個圖像的不變矩來進行距離的計算

參數解析:

前兩個參數是兩個圖像

method:進行距離計算的方法即公式,分别有以下三種方法

parameter:一般設定為0即可

距離計算方法

注意:以下的計算方法的hu不變矩陣都是經過log函數變換的

兩個圖像(im1和im2)是相似的,如果上面的距離很小。你可以使用任何距離測量。它們通常産生相似的結果。我個人更喜歡d2。

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

自定義距離計算方法

【圖像處理】——Python+opencv實作圖像的hu不變矩特征提取(含原理、推導過程、應用、代碼等)一、思維導圖二、普通矩的定義三、什麼是圖像矩?四、hu不變矩(cv2.humoments())五、Python+opencv實作不變矩計算六、形狀相似度計算(cv2.matchshapes())七、參考文獻

七、參考文獻

https://zhuanlan.zhihu.com/p/117344473(中文版)

https://www.learnopencv.com/shape-matching-using-hu-moments-c-python/(英文版)

hu不變矩的原理:https://www.researchgate.net/publication/224146066_Analysis_of_Hu's_moment_invariants_on_image_scaling_and_rotation

https://blog.csdn.net/qq_37207090/article/details/83986950

https://blog.csdn.net/qq_23541329/article/details/60963456