日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)
3.8 輪廓檢測
學習目標
- 瞭解圖像的輪廓,知道怎麼利用OPenCV查找輪廓
- 知道輪廓的特徵
- 知道圖像的矩特徵
1 圖像的輪廓
輪廓可以簡單認爲成將連續的點(連着邊界)連在一起的曲線,具有相同的顏色或者灰度。輪廓是圖像目標的外部特徵,這種特徵對於我們進行圖像分析,目標識別和理解等更深層次的處理都有很重要的意義。
輪廓提取的基本原理:對於一幅背景爲黑色、目標爲白色的二值圖像,如果在圖中找到一個白色點,且它的8鄰域(或4鄰域)也均爲白色,則說明該點是目標的內部點,將其置爲黑色,視覺上就像內部被掏空一樣;否則保持白色不變,該點是目標的輪廓點。一般在尋找輪廓之前,都要將圖像進行閾值化或Canny邊緣檢測,轉換爲二值化圖像。
在這裏我們看下邊緣提取和輪廓檢測的區別:
邊緣檢測主要是通過一些手段檢測數字圖像中明暗變化劇烈(即梯度變化比較大)像素點,偏向於圖像中像素點的變化。如canny邊緣檢測,結果通常保存在和源圖片一樣尺寸和類型的邊緣圖中。
輪廓檢測指檢測圖像中的對象邊界,更偏向於關注上層語義對象。如OpenCV中的findContours()函數, 它會得到每一個輪廓並以點向量方式存儲,除此也得到一個圖像的拓撲信息,即一個輪廓的後一個輪廓、前一個輪廓等的索引編號。
1.1 查找輪廓
在OPenCV中查找輪廓的API:
binary, contours, hierarchy = cv2.findContours(img, mode, method)
參數:
-
img: 輸入圖像,二值圖
-
mode: 輪廓的檢索模式,主要有四種方式:
cv2.RETR_EXTERNAL:只檢測外輪廓,所有子輪廓被忽略
cv2.RETR_LIST:檢測的輪廓不建立等級關係,所有輪廓屬於同一等級
cv2.RETR_CCOMP:返回所有的輪廓,只建立兩個等級的輪廓。一個對象的外輪廓爲第 1 級組織結構。而對象內部中空洞的輪廓爲 第 2 級組織結構,空洞中的任何對象的輪廓又是第 1 級組織結構。
cv2.RETR_TREE:返回所有的輪廓,建立一個完整的組織結構的輪廓。
-
method:輪廓的近似方法,主要有以下兩種:
cv2.CHAIN_APPROX_NONE:存儲所有的輪廓點,相鄰的兩個點的像素位置差不超過1。
cv2.CHAIN_APPROX_SIMPLE:壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點座標,例如一個矩形輪廓只需4個點來保存輪廓信息。
返回:
-
binary: 返回的二值圖像
-
contours: 檢測出的輪廓,所有輪廓的列表結構,每個輪廓是目標對象邊界點的座標的數組
-
hierarchy:輪廓的層次結構。
在檢測輪廓時:有時對象可能位於不同的位置,也有可能一個形狀在另外一個形狀的內部,這種情況下我們稱外部的形狀爲父,內部的形狀爲子。按照這種方式分類,一幅圖像中的所有輪廓之間就建立父子關係。這樣我們就可以確定一個輪廓與其他輪廓是怎樣連接的,比如它是不是某個輪廓的子輪廓,或者是父輪廓。這種關係就是輪廓的層次關係。
-
在這幅圖像中,我給這幾個形狀編號爲 0-5。2 和 2a 分別代表最外邊矩形的外輪廓和內輪廓。
在這裏邊輪廓 0,1,2 在外部或最外邊。我們可以稱他們爲 0 級,簡單來說就是他們屬於同一級,接下來輪廓 2a,把它當成輪廓 2 的子輪廓。它就成爲第 1 級。輪廓 3 是輪廓 2a 的子輪廓,成爲第 3 級。輪廓 3a 是輪廓 3 的子輪廓,成爲第 4 級,最後輪廓 4,5 是輪廓 3a 的子輪廓,成爲5級,這樣我們就構建的輪廓的層級關係。
我們再回到返回值中,不管層次結構是什麼樣的, 每一個輪廓都包含自己的信息。hierarchy使用包含四個元素的數組來表示:
[Next,Previous, First_Child,Parent]。
其中:
Next 表示同一級組織結構中的下一個輪廓,
以上圖中的輪廓 0 爲例,輪廓 1 就是他的 Next。同樣,輪廓 1 的 Next 是 2,Next=2。 那輪廓 2 呢?在同一級沒有 Next。這時 Next=-1。而輪廓 4 的 Next 爲 5,所以它的 Next=5。
Previous 表示同一級結構中的前一個輪廓。
輪廓 1 的 Previous 爲輪廓 0,輪廓 2 的 Previous 爲輪 廓 1。輪廓 0 沒有 Previous,所以 Previous=-1。
First_Child 表示它的第一個子輪廓。
輪廓 2 的子輪廓爲 2a。 所以它的 First_Child 爲 2a。那輪廓 3a 呢?它有兩個子輪廓。但是我們只要第一個子輪廓,所以是輪 廓 4(按照從上往下,從左往右的順序排序)。
Parent 表示它的父輪廓。
與 First_Child 剛好相反。輪廓 4 和 5 的父輪廓是輪廓 3a。而輪廓 3a 的父輪廓是 3。
注意:如果輪廓沒有父輪廓或子輪廓時,則將其置爲-1。
1.2 繪製輪廓
我們查找到圖像中的輪廓後,怎麼將他繪製在圖像上呢?
cv2.drawContours(img, contours, index, color, width)
參數:
- img: 輪廓檢測的原圖像
- contours: 檢測出的輪廓。
- Index: 輪廓的索引,繪製單個輪廓時指定其索引,繪製全部的輪廓時設爲-1即可。
- color和width: 繪製時輪廓的顏色及線型的寬度。
示例:
在北京市的圖片上進行輪廓檢測,如下圖所示:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 圖像讀取
img = cv.imread('beijing.jpg')
imgray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 2 邊緣檢測
canny = cv.Canny(imgray,127,255,0)
# 3 輪廓提取
image, contours, hierarchy = cv.findContours(canny,cv.RETR_TREE,cv.CHAIN_APPROX_NONE)
# 4 將輪廓繪製在圖像上
img = cv.drawContours(img, contours, -1, (0,0,255), 2)
# 5 圖像顯示
plt.imshow(img[:,:,::-1])
plt.xticks([]), plt.yticks([])
plt.show()
檢測結果如下圖所示:
2 輪廓的特徵
在提取了圖像的輪廓後,可以計算輪廓的不同特徵,我們現在主要看下:輪廓的面積,周長,邊界框等。
2.1 輪廓面積
輪廓面積是輪廓所包圍的區域的面積,在OpenCV中使用的API是:
area = cv.contourArea(cnt)
2.2 輪廓周長
輪廓周長也被成爲弧長,在OpenCV中使用的API是:
perimeter = cv2.arcLength(cnt,isclosed)
參數:
- Isclosed: 指定輪廓的形狀是閉合的(True),還是開放的。
2.3 輪廓近似
輪廓近似是將輪廓形狀近似爲到另外一種由更少點組成的輪廓形狀,新輪廓的點的數目由我們設定的準確度來決定。
假設我們要在一幅圖像中查找一個矩形,然而這個圖凹凸不平,直接提取輪廓無法提取到一個完美的矩形。因此我們就可以使用輪廓近似函數來近似這個形狀了。
在OpenCV中使用的API是:
approx = cv.approxPolyDP(cnt,epsilon,isclosed)
參數:
- cnt: 要進行輪廓近似的原始輪廓
- epsilon:從原始輪廓到近似輪廓的最大距離,是一個準確度參數,該參數對調整後的結果很重要。
- Isclosed: 指定輪廓是否閉合
返回:
- approx: 返回的點集,繪製時將其連接起來繪製最終的近似輪廓。
示例:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 圖像讀取
img = cv.imread('rec.png')
imgray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 2 轉換爲二值圖
ret,thresh = cv.threshold(imgray,127,255,0)
# 3 輪廓提取
image, contours, hierarchy = cv.findContours(thresh,cv.RETR_LIST,cv.CHAIN_APPROX_NONE)
# 4 輪廓近似
epsilon = 0.1*cv.arcLength(contours[0],True)
approx = cv.approxPolyDP(contours[0],epsilon,True)
# 5 將輪廓繪製在圖像上
# 5.1 原始輪廓
img1 = cv.drawContours(img, contours, -1, (0,0,255), 2)
# 5.2 輪廓近似後的結果
img2 = cv.polylines(img, [approx], True, (0, 0, 255), 2)
# 6 圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title('輪廓檢測結果')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img[:,:,::-1]),plt.title('輪廓近似後結果')
plt.xticks([]), plt.yticks([])
plt.show()
2.4 凸包
凸包是計算機幾何圖形學中的概念,簡單來說,給定二維平面點集,凸包就是將最外層的點連接起來構成的凸多邊形,他能夠包含物體中所有的點。物體的凸包常應用在物體識別,手勢識別及邊界檢測等領域。
在OpenCV中檢測凸包的API是:
hull = cv2.convexHull(points, clockwise, returnPoints)
參數:
- points: 傳入的輪廓
- clockwise: 方向標誌。如果設置爲 True,輸出的凸包是順時針方向的。 否則爲逆時針方向
- returnPoints 默認值爲 True。它會返回凸包上點的座標。 如果設置 爲 False,就會返回與凸包點對應的輪廓上的點的索引。
返回:
- hull: 輸出的凸包結果
示例:
我們檢測一個五角星的凸包結果,代碼如下:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 圖像讀取
img = cv.imread('star.jpeg')
img1 =img.copy()
imgray = cv.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 2 邊緣檢測
canny = cv.Canny(imgray,127,255,0)
# 3 輪廓提取
image, contours, hierarchy = cv.findContours(canny,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# 4 將輪廓繪製在圖像上
img = cv.drawContours(img, contours, 1, (255,0,0), 2)
# 5 凸包檢測
hulls=[]
for cnt in contours:
# 尋找凸包使用cv2.convexHull(contour)
hull = cv.convexHull(cnt)
hulls.append(hull)
draw_hulls = cv.drawContours(img1,hulls, -1, (0, 255, 0), 2)
# 5 圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title('輪廓檢測結果')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(draw_hulls[:,:,::-1]),plt.title('凸包結果')
plt.xticks([]), plt.yticks([])
plt.show()
檢測結果:
2.5 邊界矩形
輪廓檢測中的邊界矩形有兩種,一種是直邊界矩形,一種是旋轉邊界矩形,分別介紹如下:
直邊界矩形 :一個直矩形,沒有進行旋轉。它不會考慮對象是否旋轉,所以該邊界矩形的面積不是最小的。可以使用函數cv2.boundingRect()查找得到的。
x,y,w,h = cv2.boundingRect(cnt)
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
返回值中,(x,y)是矩陣左上角的座標,(w,h)是舉行的寬和高。
旋轉邊角矩形 :這個邊界矩形是面積最小的,他考慮了對象的旋轉。用函數cv2.minAreaRect(),返回的是一個Box2D結構,其中包含矩形左上角角點的座標(x,y),以及矩形的寬和高(w,h),以及旋轉角度。但是要繪製這個矩形需要矩形的4個角點。可以通過函數cv2.boxPoints()獲得。
s = cv2.minAreaRect(cnt)
a = cv2.boxPoints(s)
a = np.int0(a)#必須轉換a的類型爲int型
cv2.polylines(im,[a],True,(0,0,255),3)
示例:
我們找到以下圖形的邊界矩形:
代碼如下:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 圖像讀取
img = cv.imread('./image/arrows.jpg')
imgray = cv.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 2 轉換爲二值圖
ret,thresh = cv2.threshold(imgray,127,255,0)
# 3 輪廓提取
image, contours, hierarchy = cv.findContours(thresh,1,2)
# 4 將輪廓繪製在圖像上
#img = cv.drawContours(img, contours, 1, (0,0,255), 2)
cnt = contours[1]
# 5 邊界矩形
# 5.1 直邊界矩形
x,y,w,h = cv.boundingRect(cnt)
img = cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),3)
# 5.2 旋轉邊界矩形結果
s = cv.minAreaRect(cnt)
a = cv.boxPoints(s)
a = np.int0(a)#轉換a的類型爲int型
cv.polylines(img,[a],True,(0,0,255),3)
# 5 圖像顯示
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img[:,:,::-1]),plt.title('矩形結果')
plt.xticks([]), plt.yticks([])
plt.show()
檢測結果如下所示:其中紅色的是旋轉邊界矩形的結果,綠色的爲直邊界矩形的結果
2.6 最小外接圓
最小外接圓是對象的外切圓,它是所有包含目標對象的圓中面積最小的一個,我們使用函數cv2.minEnclosingCircle()獲取最小外接圓。
將上述案例中的邊界矩形的代碼改爲如下所示,即可檢測對象的最小外接圓
(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)
檢測結果如下所示:
2.7 橢圓擬合
橢圓擬合法的基本思路是:對於給定平面上的一組樣本點,尋找一個橢圓,使其儘可能接近這些樣本點。也就是說,將圖像中的一組數據以橢圓方程爲模型進行擬合,使某一橢圓方程儘量滿足這些數據,並求出該橢圓方程的各個參數。
就橢圓擬合而言,就是先假設橢圓參數,得到每個待擬合點到該橢圓的距離之和,也就是點到假設橢圓的誤差,求出使這個和最小的參數。
在OPenCV中我們使用cv2.ellipse()來進行橢圓擬合,將邊界矩形中的代碼改爲如下所示,就可得到橢圓擬合的結果:
ellipse = cv.fitEllipse(cnt)
img = cv.ellipse(img,ellipse,(0,255,0),2)
結果如下所示:
2.8 直線擬合
直線擬合就是將圖像中的對象擬合成一條直線過程,在OPenCV中擬合直線的API是:
output = cv2.fitLine(points, distType, param, reps, aeps)
參數:
-
points: 待擬合直線的點的集合,可以是檢測處理輪廓結果
-
distype: 距離公式,在進行擬合是,要使輸入點到擬合直線的距離之和最小,常用的用以下幾種:
cv2.DIST_L1: 曼哈頓距離
cv2.DIST_L2: 歐式距離
cv2.DIST_C:切比雪夫距離
-
param: 距離參數,可以設爲0
-
Reps,aeps:用於表示擬合曲線所需要的徑向和角度精度,通常設爲0.01
返回:
- output: [vx,vy,x,y]的1*4 的數組,前兩個表示直線的方向,即vy/vx表示斜率,後兩位表示直線上的一個點。
將邊界矩形中的代碼改爲如下示,即可進行直線擬合:
rows,cols = img.shape[:2]
[vx,vy,x,y] = cv.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
im = cv.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)
3 圖像的矩特徵
矩函數在圖像分析中有着廣泛的應用,如模式識別、目標分類、目標識別與方位估計、圖像的編碼與重構等。從一幅圖像計算出來的矩集,不僅可以描述圖像形狀的全局特徵,而且可以提供大量關於該圖像不同的幾何特徵信息,如大小,位置、方向和形狀等。
3.1 矩的概念
矩是概率與統計中的一個概念,是隨機變量的一種數字特徵。矩的定義如下:
3.2 圖像中的矩特徵
對於一幅圖像,我們把像素的座標看成是一個二維隨機變量(𝑋,𝑌),那麼一幅灰度圖像可以用二維灰度密度函數來表示,因此可以用矩來描述灰度圖像的特徵。
在OpenCV中有直接計算圖像矩的API,分爲兩個函數:moments()函數用於計算中心矩,HuMoments函數用於由中心矩計算Hu矩。
moments(array, binaryImage=false )
參數:
- array:輸入數組,也可以是灰度圖像,也可以是二維數組,例如提取的輪廓結果。
- BinaryImage:默認是false,若爲True,則所有非零的像素都會按值1對待,也就是說相當於對圖像進行了二值化處理,閾值爲1,此參數僅對圖像有效。
返回:
- moment: 返回數組的中心矩
計算Hu矩時,將中心距輸入即可。
示例:
計算上一章節中箭頭的矩特徵,代碼如下所示:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 圖像讀取
img = cv.imread('./image/arrows.jpg')
imgray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 2 計算圖像的Hu矩
imgmn = cv.moments(imgray)
imghu = cv.HuMoments(imgmn)
print("圖像Hu矩結果:\n",imghu)
# 3 計算輪廓的Hu矩
# 3.1 轉換爲二值圖
ret,thresh = cv.threshold(imgray,127,255,0)
# 3.2 輪廓提取
image, contours, hierarchy = cv.findContours(thresh,1,2)
# 3.3 計算輪廓的Hu矩
cnt = contours[1]
mn = cv.moments(cnt)
hu = cv.HuMoments(mn)
print("Hu矩結果:\n",hu)
Hu矩常常作爲描述圖像的特徵,訓練分類器,來進行目標識別。
總結
-
圖像的輪廓
輪廓是圖像目標的外部特徵,是具有相同的顏色或者灰度的連續點連成的曲線。
查找輪廓:cv.findContours()
注意:輪廓的檢索方式,近似方式以及輪廓的層次
繪製輪廓:cv.drawContours()
-
輪廓的特徵
面積:ContourArea()
周長:ArcLength()
輪廓近似:approxPolyDP() 逼近圖像的多邊形曲線
凸包:ConvexHull()
邊界矩形:BoundingRect()和MinAreaRect()
最小外接圓:MinEnclosingCircle()
橢圓擬合:fitEllipse()
直線擬合:fitline()
-
圖像的矩特徵
矩是統計與概率中的概念
在圖像中的應用:空間矩,中心矩,Hu矩
API: moments()
HuMoments()
In [1]:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
輪廓檢測
In [2]:
img = cv.imread("./image/beijing.jpg")
In [3]:
img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
In [4]:
canny = cv.Canny(img_gray,127,255,0)
In [5]:
bianry,contours,hi = cv.findContours(canny,cv.RETR_TREE,cv.CHAIN_APPROX_SIMPLE)
In [6]:
img = cv.drawContours(img,contours,-1,(0,0,255),2)
In [7]:
plt.imshow(img[:,:,::-1])
Out[7]:
<matplotlib.image.AxesImage at 0x11bda7bd0>
輪廓特徵
In [8]:
img = cv.imread("./image/rec.png")
In [9]:
img1 = img.copy()
In [10]:
img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
In [11]:
ret,thresh = cv.threshold(img_gray,127,255,0)
In [12]:
bianry,contours,hi = cv.findContours(thresh,cv.RETR_LIST,cv.CHAIN_APPROX_NONE)
In [13]:
plt.imshow(img[:,:,::-1])
Out[13]:
<matplotlib.image.AxesImage at 0x11f0c8e10>
In [14]:
img = cv.drawContours(img,contours,0,(0,0,255),2)
In [15]:
plt.imshow(img[:,:,::-1])
Out[15]:
<matplotlib.image.AxesImage at 0x11f265e50>
In [16]:
cnt = contours[0]
In [17]:
area = cv.contourArea(cnt)
In [18]:
area
Out[18]:
58129.5
In [19]:
length = cv.arcLength(cnt,True)
In [20]:
length
Out[20]:
1560.256921172142
In [21]:
esplion = 0.1*length
In [22]:
approx = cv.approxPolyDP(cnt,esplion,True)
In [23]:
img1 = cv.polylines(img1,[approx],True,(0,0,255),2)
In [25]:
plt.imshow(img1[:,:,::-1])
Out[25]:
<matplotlib.image.AxesImage at 0x120734690>
In [26]:
img= cv.imread("./image/star 2.jpeg")
In [27]:
img1 = img.copy()
In [28]:
imggray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
In [29]:
canny = cv.Canny(imggray,127,255,0)
In [30]:
bianry,contours,hi = cv.findContours(canny,cv.RETR_LIST,cv.CHAIN_APPROX_SIMPLE)
In [31]:
cv.drawContours(img,contours,-1,(0,0,255),2)
Out[31]:
array([[[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], ..., [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]]], dtype=uint8)
In [32]:
plt.imshow(img[:,:,::-1])
Out[32]:
<matplotlib.image.AxesImage at 0x1266a20d0>
In [33]:
hulls = []
In [34]:
for cnt in contours:
hull = cv.convexHull(cnt)
hulls.append(hull)
In [35]:
img1 = cv.drawContours(img1,hulls,-1,(0,255,0),2)
In [36]:
plt.imshow(img1[:,:,::-1])
Out[36]:
<matplotlib.image.AxesImage at 0x1270c5490>
In [37]:
img = cv.imread("./image/arrows.jpg")
In [38]:
img_gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
In [39]:
ret,thresh = cv.threshold(img_gray,127,255,0)
In [40]:
bianry,contours,hi = cv.findContours(thresh,1,2)
In [41]:
cnt = contours[1]
In [42]:
x,y,w,h = cv.boundingRect(cnt)
In [43]:
imgRect = cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),3)
In [44]:
plt.imshow(imgRect[:,:,::-1])
Out[44]:
<matplotlib.image.AxesImage at 0x1266a09d0>
In [45]:
s = cv.minAreaRect(cnt)
In [46]:
a = cv.boxPoints(s)
In [47]:
a = np.int0(a)
In [48]:
cv.polylines(imgRect,[a],True,(0,0,255),3)
Out[48]:
array([[[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], ..., [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255], ..., [255, 255, 255], [255, 255, 255], [255, 255, 255]]], dtype=uint8)
In [49]:
plt.imshow(imgRect[:,:,::-1])
Out[49]:
<matplotlib.image.AxesImage at 0x12691bf50>
In [50]:
(x,y),r = cv.minEnclosingCircle(cnt)
In [51]:
center = (int(x),int(y))
In [52]:
r = int(r)
In [53]:
imgcircle = cv.circle(img,center,r,(0,255,0),3)
In [54]:
plt.imshow(imgcircle[:,:,::-1])
Out[54]:
<matplotlib.image.AxesImage at 0x126d6ae50>
In [57]:
ellipse = cv.fitEllipse(cnt)
In [59]:
imgellipse = cv.ellipse(img,ellipse,(0,255,255),3)
In [62]:
plt.imshow(imgellipse[:,:,::-1])
Out[62]:
<matplotlib.image.AxesImage at 0x129f2be10>
In [63]:
[vx,vy,x,y] = cv.fitLine(cnt,cv.DIST_L2,0,0.01,0.01)
In [64]:
rows,cols = img.shape[:2]
In [65]:
lefty = int((-x*vy/vx)+y)
In [66]:
righty = int(((cols-x)*vy/vx)+y)
In [67]:
imgline = cv.line(img,(0,lefty),(cols-1,righty),(0,0,255),3)
In [68]:
plt.imshow(imgline[:,:,::-1])
Out[68]:
<matplotlib.image.AxesImage at 0x12b122e50>
矩特徵
In [69]:
img = cv.imread("./image/arrows.jpg",0)
In [70]:
imgmn = cv.moments(img)
In [71]:
imghu = cv.HuMoments(imgmn)
In [72]:
imghu
Out[72]:
array([[ 7.43826217e-04], [ 7.67696084e-08], [ 8.10101462e-15], [ 1.74290590e-14], [ 4.60486533e-29], [-4.79741272e-19], [ 2.01915908e-28]])
In [73]:
ret,thresh = cv.threshold(img,127,255,0)
In [74]:
bianry,contours,hi = cv.findContours(thresh,1,2)
In [75]:
cnt = contours[1]
In [76]:
mn = cv.moments(cnt)
In [77]:
humn = cv.HuMoments(mn)
In [78]:
humn
Out[78]:
array([[ 3.44041333e-01], [ 8.09585868e-02], [ 8.01740895e-03], [ 3.39099215e-03], [ 1.75550484e-05], [ 9.15527105e-04], [-2.10679127e-06]])