OpenCV(3.2)+Python(3.6)學習(基於官方API)(三)
1.3 Drawing Functions in OpenCV
Goal
- 學習如何用 OpenCV 畫各種不同的圖形。
- 我們將學習這些函式:
cv2.line()
,cv2.circle()
,cv2.rectangle
,cv2.ellipse()
,cv2.putText()
等等。
Code
在上面提到的所有函式中,他們都有一些共同的引數:
- img : 畫板,也就是你要在哪個影象上畫圖。
- color : 你所畫圖形的顏色。BGR模式,需要傳遞一個元組,例如(255,0,0)就表示藍色。對於灰度圖傳遞一個標量值就行了。
- thickness : 直線、圓環等圖形的線條的粗細。如果這個值是-1就代表閉合的圖形,這時圖形將被 color 填充。這個引數的預設值是1.
- lineType : 線型,生成線條的方式,預設值是 8-connected,對這個感興趣的可以參考這裡。其中
cv2.LINE_AA
可以讓曲線獲得抗鋸齒的效果,從而使曲線更加平滑。
Drawing Line
要畫一條直線,我們需要傳遞直線起始點的座標。下面的程式碼我們將在一張黑色的圖片上畫一條從左上角到右下角的藍色直線。
import numpy as np
import cv2
# 建立一個黑色的背景
img = np.zeros((512,512,3),np.uint8)
# 畫一個寬度為5個畫素,顏色為藍色的對角線。
img = cv2.line(img,(0,0),(511 ,511),(255,0,0),5)
這裡說明一下numpy.zeros()
函式把一個影象所需要的長寬和通道數用一個三維陣列表示出來,並且裡面的資料都用0填充,這樣我們就會得到一個純黑的背景。要了解 numpy
裡面的array
可以參考這裡。
Drawing Rectangle
要畫一個長方形,你需要知道它的左上角與右下角頂點的座標,我們在背景的右上角畫一個綠色的長方形。
img = cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)
Drawing Circle
要畫一個圓,我們需要指定圓心位置與半徑。我們在之前畫的長方形內部畫一個圓。
img = cv2.circle(img,(447,63),63,(0,0,255),-1)
Drawing Ellipse
要畫一個橢圓,我們需要傳遞一系列的引數。第一個引數是中心點的位置。下一個引數是橢圓長軸與短軸的長度。angle 引數代表橢圓本身以逆時針方向偏轉的角度。startAngle 和 endAngle 代表橢圓的哪一部分被渲染,從長軸開始順時針方向從 startAngle 到 endAngle 的部分會被渲染。下面我們在背景的中心位置畫一個半橢圓。
img = cv2.ellipse(img,(255,255),(100,50),0,0,180,(255,0,0),-1)
Drawing Polygon
要畫一個多邊形,我們首先需要知道它頂點的座標。然後把所有的頂點放到一個形狀為ROWSx1x2
的數組裡面。這裡ROWS就是頂點的個數,它必須是 int32 型別的值。
pts = np.array([[10,5],[20,30],[70,20],[50,10]],np.int32)
pts = pts.reshape((-1,1,2))
img = cv2.polylines(img,[pts],True,(0,255,255))
現在我們討論上面的幾個函式,第一個是numpy.array()
這個函式用來生成一個數組,它比 Python 自帶的 list 效能要好。這裡我們給它傳了一個二維陣列,我們要用reshape()
函式將它轉換為一個ROWSx1x2
格式的三維陣列。reshape
函式裡面的-1代表這個維度是有其他兩個維度計算而來的,陣列的轉換規律是不能改變原陣列中的元素,原來二維陣列中有8個元素,那麼轉換後的三維陣列也是8個元素,所以其實上面的-1的位置就是4,對numpy.array
不熟悉的請參考這裡。接下來使用畫多條直線的函式cv2.polylines()
將多邊形畫出來。其中的第三個引數如果是 False 的話圖形第一個點和最後一個點不會連起來,你就得不到一個閉合的圖形了。
提示:
cv2.polylines()
可以被用來畫一組直線,它比用cv2.line()
一條一條的畫直線效率高很多。
Adding Text to Images
要在影象上顯示文字,你需要指定以下內容
- 你想要寫的文字資料
- 你想要放置文字的座標位置
- 字型
- 字號
- 顏色、粗細、線型等等,這裡推薦使用
lineType = cv2.LINE_AA
線型
我們寫一個白色的 RYAN 在影象的底部。
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'RYAN',(10,500),font,4,(255,255,255),2,cv2.LINE_AA)
下面將上面的程式碼整合一下(部分資料做了更改)
import numpy as np
import cv2
# zeros() 函式第一個引數是一個元組(高,寬,通道數(1,3或4的一個列舉值))
# 第二個引數是一個 DataType [參考](https://docs.scipy.org/doc/numpy-dev/reference/c-api.dtype.html)
img = np.zeros((512,512,3),np.uint8)
# line() 函式第一個引數是畫板,第二個第三個分別是起始點(左上角為(0,0))
# 第四個引數是線的顏色(BGR模式),最後一個是線的粗細。
img = cv2.line(img,(10,10),(501,501),(255,0,0),1)
img = cv2.rectangle(img,(384,0),(510,128),(0,255,0),2)
img = cv2.circle(img,(255,255),63,(0,0,255),-1)
# 畫橢圓需要這麼幾個引數
# 畫板、中心點座標、長短軸的長度、橢圓的旋轉角度、橢圓的起始角度、顏色、線的粗細
img = cv2.ellipse(img,(255,255),(100,50),0,30,360,(0,255,0),-1)
pts = np.array([[15,15],[100,90],[210,70],[300,20]],np.int32)
pts = pts.reshape((-1,1,2))
img = cv2.polylines(img,[pts],True,(0,255,255))
font = cv2.FONT_HERSHEY_SIMPLEX
img = cv2.putText(img,'Ryan',(10,450),font,6,(255,255,255),2,cv2.LINE_AA)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果如下圖所示