根據上一篇博客可知,單純的通過求取最大面積而進行定位的局限性,因此我們接下來將通過cv2.moments()和cv2.HuMoments()這兩個方法來在更複雜的環境中去找到我們的目標區域。 cv2.moments(): 參數: array:表示輸入圖像的單通道數組。通常是灰度圖像,可以是8位或浮點 ...
根據上一篇博客可知,單純的通過求取最大面積而進行定位的局限性,因此我們接下來將通過cv2.moments()和cv2.HuMoments()這兩個方法來在更複雜的環境中去找到我們的目標區域。
cv2.moments():
參數:
- array:表示輸入圖像的單通道數組。通常是灰度圖像,可以是8位或浮點型。
- binaryImage:一個可選參數,如果設置為 True,則將 array 視為二進位圖像。預設為 False。
返回值:
- moments:一個包含圖像矩特征信息的字典對象。這些矩包括圖像的原始矩、中心矩以及一些其他相關的信息。您可以使用這些矩特征來描述圖像的幾何形狀和分佈情況。
cv2.HuMoments():
參數:
- moments:一個字典對象,包含通過
cv2.moments()
函數計算得到的圖像矩特征。
返回值:
- huMoments:一個包含7個不變矩特征值的一維數組。這些特征值對圖像的形狀、輪廓和幾何特征進行了描述。通常用於圖像識別和匹配。
簡易的介紹一下moments(矩)這個東西,它是用來描述一個形狀的特性,比如說正方形,我們能分辨出來是因為知道其四個邊是相等的,這便是在我們的認知中所知的正方形的輪廓特性,
而在電腦中呈現的就是一組數據,通過和這組數據進行比對,我們就可以較為準確的去尋找我們的目標區域。
但是相較於上一篇博客的直接在輸入圖像中查找,使用矩我們需要事先獲取目標的完整輪廓,並保存其矩特性數據。
圖像準備,一張沒有完整的只有barcode的圖像
Code:
1 import cv2 2 import numpy 3 4 img = cv2.imread('../images/barcode.jpg') 5 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 6 kernel_x = numpy.array( 7 [ 8 [-1, 0, 1], 9 [-2, 0, 2], 10 [-1, 0, 1] 11 ] 12 ) 13 sobel_x = cv2.filter2D(gray, -1, kernel_x) 14 _, thresh = cv2.threshold(sobel_x, 127, 255, cv2.THRESH_BINARY) 15 kernel_ed = numpy.ones((3, 3), dtype=numpy.uint8) 16 img_d = cv2.dilate(thresh, kernel_ed, iterations=6) 17 contours, hir = cv2.findContours(img_d, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 18 print(cv2.HuMoments(cv2.moments(contours[0]))) 19 cv2.drawContours(img, contours, -1, (0, 255, 0), 3) 20 cv2.imshow('', img) 21 cv2.waitKey() 22 cv2.destroyAllWindows()
Result:
我就直接和上一篇博客的barcode的輪廓矩特性進行對比:
只有barcode圖 包含其他圖形的barcode圖
通過對比數據我們可以發現,在第1不變矩中,數據是最接近的,這個時候就可以利用這個特性數據來進行輪廓特征比對尋找目標區域。
當然因為OpenCV提供了一個方法為我們減免了比較的操作cv2.matchShapes()方法。
cv2.matchShapes()
參數:
- contour1:第一個輪廓,通常是一個包含點集的 NumPy 數組。
- contour2:第二個輪廓,也是一個包含點集的 NumPy 數組。
- method:表示相似性度量方法的整數值。可以是 1、2 或 3,分別代表不同的計算方法。
返回值:
- match:一個表示兩個輪廓之間相似性的浮點數值。該值越小表示兩個輪廓形狀越相似。
至此,當我們所得到的圖像源包含了其他複雜的圖形時,我們則可以使用矩特性來進一步提高我們的檢測能力,但是還有其他更為複雜的場景,所以還需要優化我們的解決思路。