Opencv 學習筆記(一)——三小時精通Opencv(Chapter)
1.Images-Videos-Webcam
影象、視訊、網路攝像頭
######################## READ IMAGE ############################ # import cv2 # # LOAD AN IMAGE USING 'IMREAD' # img = cv2.imread("Resources/lena.png") # # DISPLAY # cv2.imshow("Lena Soderberg",img) # cv2.waitKey(0) ######################### READ VIDEO ############################# # import cv2 # frameWidth = 640 # frameHeight = 480 # cap = cv2.VideoCapture("Resources/test_ video.mp4") # while True: # success, img = cap.read() # img = cv2.resize(img, (frameWidth, frameHeight)) # cv2.imshow("Result", img) # if cv2.waitKey(1) & 0xFF == ord('q'): # break ######################### READ WEBCAM ############################ #開啟網路攝像頭 import cv2 frameWidth = 640 frameHeight = 480 cap = cv2.VideoCapture(0) cap.set(3, frameWidth) cap.set(4, frameHeight) cap.set(10,150) while True: success, img = cap.read() cv2.imshow("Result", img) if cv2.waitKey(1) & 0xFF == ord('q'): break
4.繪圖
import cv2 import numpy as np img = np.zeros((512,512,3),np.uint8) #print(img) #img[:]= 255,0,0 cv2.line(img,(0,0),(img.shape[1],img.shape[0]),(0,255,0),3) cv2.rectangle(img,(0,0),(250,350),(0,0,255),2) cv2.circle(img,(400,50),30,(255,255,0),5) cv2.putText(img," OPENCV ",(300,200),cv2.FONT_HERSHEY_COMPLEX,1,(0,150,0),3) cv2.imshow("Image",img) cv2.waitKey(0)
5.影象提取並顯示
提取固定位置的影象重新鋪平顯示
import cv2 import numpy as np img = cv2.imread("Resources/cards.jpg") width,height = 250,350 pts1 = np.float32([[111,219],[287,188],[154,482],[352,440]])# 獲取輪廓 pts2 = np.float32([[0,0],[width,0],[0,height],[width,height]]) # 顯示平面 matrix = cv2.getPerspectiveTransform(pts1,pts2) imgOutput = cv2.warpPerspective(img,matrix,(width,height)) cv2.imshow("Image",img) cv2.imshow("Output",imgOutput) cv2.waitKey(0)
7.顏色
import cv2
import numpy as np
def empty(a):
pass
def stackImages(scale,imgArray):
rows = len(imgArray)
cols = len(imgArray[0])
rowsAvailable = isinstance(imgArray[0], list)
width = imgArray[0][0].shape[1]
height = imgArray[0][0].shape[0]
if rowsAvailable:
for x in range ( 0, rows):
for y in range(0, cols):
if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
else:
imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
imageBlank = np.zeros((height, width, 3), np.uint8)
hor = [imageBlank]*rows
hor_con = [imageBlank]*rows
for x in range(0, rows):
hor[x] = np.hstack(imgArray[x])
ver = np.vstack(hor)
else:
for x in range(0, rows):
if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
else:
imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
hor= np.hstack(imgArray)
ver = hor
return ver
path = 'Resources/lambo.png'
cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars",640,240)
cv2.createTrackbar("Hue Min","TrackBars",0,179,empty)
cv2.createTrackbar("Hue Max","TrackBars",19,179,empty)
cv2.createTrackbar("Sat Min","TrackBars",110,255,empty)
cv2.createTrackbar("Sat Max","TrackBars",240,255,empty)
cv2.createTrackbar("Val Min","TrackBars",153,255,empty)
cv2.createTrackbar("Val Max","TrackBars",255,255,empty)
while True:
img = cv2.imread(path)
imgHSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
h_min = cv2.getTrackbarPos("Hue Min","TrackBars")
h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")
s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")
s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")
v_min = cv2.getTrackbarPos("Val Min", "TrackBars")
v_max = cv2.getTrackbarPos("Val Max", "TrackBars")
print(h_min,h_max,s_min,s_max,v_min,v_max)
lower = np.array([h_min,s_min,v_min])
upper = np.array([h_max,s_max,v_max])
mask = cv2.inRange(imgHSV,lower,upper)
imgResult = cv2.bitwise_and(img,img,mask=mask)
# cv2.imshow("Original",img)
# cv2.imshow("HSV",imgHSV)
# cv2.imshow("Mask", mask)
# cv2.imshow("Result", imgResult)
imgStack = stackImages(0.6,([img,imgHSV],[mask,imgResult]))
cv2.imshow("Stacked Images", imgStack)
cv2.waitKey(1)
8.形狀識別
繪製圖像輪廓
參考:python-opencv2利用cv2.findContours()函式來查詢檢測物體的輪廓
importcv2
img=cv2.imread('D:\\test\\contour.jpg')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,binary=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hierarchy=cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img,contours,-1,(0,0,255),3)
cv2.imshow("img",img)
cv2.waitKey(0)
cv2.findContours()函式
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])
opencv2返回兩個值:contours:hierarchy。
注:opencv3會返回三個值,分別是img, countours, hierarchy
引數
第一個引數是尋找輪廓的影象;
第二個引數表示輪廓的檢索模式,有四種(本文介紹的都是新的cv2介面):
cv2.RETR_EXTERNAL表示只檢測外輪廓
cv2.RETR_LIST檢測的輪廓不建立等級關係
cv2.RETR_CCOMP建立兩個等級的輪廓,上面的一層為外邊界,裡面的一層為內孔的邊界資訊。如果內孔內還有一個連通物體,這個物體的邊界也在頂層。
cv2.RETR_TREE建立一個等級樹結構的輪廓。
第三個引數method為輪廓的近似辦法
cv2.CHAIN_APPROX_NONE儲存所有的輪廓點,相鄰的兩個點的畫素位置差不超過1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE壓縮水平方向,垂直方向,對角線方向的元素,只保留該方向的終點座標,例如一個矩形輪廓只需4個點來儲存輪廓資訊
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似演算法
返回值
cv2.findContours()函式返回兩個值,一個是輪廓本身,還有一個是每條輪廓對應的屬性。
hierarchy返回值
此外,該函式還可返回一個可選的hierarchy結果,這是一個ndarray,其中的元素個數和輪廓個數相同,每個輪廓contours[i]對應4個hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分別表示後一個輪廓、前一個輪廓、父輪廓、內嵌輪廓的索引編號,如果沒有對應項,則該值為負數。
print(type(hierarchy))
print(hierarchy.ndim)
print(hierarchy[0].ndim)
print(hierarchy.shape)
cv2.contourArea()函式
計算輪廓面積參考:OpenCV中contourArea輪廓面積演算法
cv2.contourArea(cnt, True)
# 計算輪廓對應圖形 的面積
cnt:輸入的單個輪廓值
cv2.arcLength()函式
計算弧長/邊長
cv2.arcLength(cnt,True)
cv2.drawContours()函式
[python] view plain copy
cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset ]]]]])
- 第一個引數是指明在哪幅影象上繪製輪廓;
- 第二個引數是輪廓本身,在Python中是一個list。
- 第三個引數指定繪製輪廓list中的哪條輪廓,如果是-1,則繪製其中的所有輪廓。後面的引數很簡單。其中thickness表明輪廓線的寬度,如果是-1(cv2.FILLED),則為填充模式。繪製引數將在以後獨立詳細介紹。
計算邊的個數
findContours後的輪廓資訊contours可能過於複雜不平滑,可以用approxPolyDP函式對該多邊形曲線做適當近似,
approxPolyDP 主要功能是把一個連續光滑曲線折線化,對影象輪廓點進行多邊形擬合。原理圖:對比之前黑點連線,之後藍色連線:
Douglas-Peucker壓縮演算法
參考2:Douglas-Peucker壓縮演算法;參考3:opencv 使用approxPolyDP輪廓近似
1.連線曲線首尾兩點A、B形成一條直線AB;
2.計算曲線上離該直線段距離最大的點C,計算其與AB的距離d;
3.比較該距離與預先給定的閾值threshold的大小,如果小於threshold,則以該直線作為曲線的近似,該段曲線處理完畢。
4.如果距離大於閾值,則用點C將曲線分為兩段AC和BC,並分別對兩段曲線進行步驟[1~3]的處理。
5.當所有曲線都處理完畢後,依次連線各個分割點形成折線,作為原曲線的近似。
cv2.approxPolyDP()函式
approx = cv2.approxPolyDP(contour,epsilon,True)
(python)
void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)
(C++)
例如:approxPolyDP(contourMat, approxCurve, 10, true)
//找出輪廓的多邊形擬合曲線
第一個引數 InputArray curve:輸入的點集
第二個引數OutputArray approxCurve:輸出的點集,當前點集是能最小包容指定點集的。畫出來即是一個多邊形。
第三個引數double epsilon:指定的精度,也即是原始曲線與近似曲線之間的最大距離。
第四個引數bool closed:若為true,則說明近似曲線是閉合的;反之,若為false,則斷開。
Charpter08:
import cv2
import numpy as np
#函式:使 影象集中顯示
def stackImages(scale,imgArray):
rows = len(imgArray)
cols = len(imgArray[0])
rowsAvailable = isinstance(imgArray[0], list)
width = imgArray[0][0].shape[1]
height = imgArray[0][0].shape[0]
if rowsAvailable:
for x in range ( 0, rows):
for y in range(0, cols):
if imgArray[x][y].shape[:2] == imgArray[0][0].shape [:2]:
imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)
else:
imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]), None, scale, scale)
if len(imgArray[x][y].shape) == 2: imgArray[x][y]= cv2.cvtColor( imgArray[x][y], cv2.COLOR_GRAY2BGR)
imageBlank = np.zeros((height, width, 3), np.uint8)
hor = [imageBlank]*rows
hor_con = [imageBlank]*rows
for x in range(0, rows):
hor[x] = np.hstack(imgArray[x])
ver = np.vstack(hor)
else:
for x in range(0, rows):
if imgArray[x].shape[:2] == imgArray[0].shape[:2]:
imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)
else:
imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None,scale, scale)
if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)
hor= np.hstack(imgArray)
ver = hor
return ver
#函式:get輪廓
#需要注意的是cv2.findContours()函式接受的引數為二值圖,即黑白的(不是灰度圖),所以讀取的影象要先轉成灰度的,再轉成二值圖
def getContours(img):
contours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE) #findContours檢測外部輪廓
for cnt in contours: #for in 迴圈結構 contours輪廓
area = cv2.contourArea(cnt) #計算輪廓的面積
print(area)
if area>500:
cv2.drawContours(imgContour,cnt,-1,(255,0,0),3) # 繪製輪廓(等高線) 在 imgContour 上繪製
peri = cv2.arcLength(cnt,True) # 計算弧長/邊長
print(peri)
approx = cv2.approxPolyDP(cnt,0.02*peri,True)
objCor = len(approx) # 計算 邊的個數
print(objCor)
if objCor == 3 :objectType = "Tri"
elif objCor == 4 :
aspRatio = w/float(h) #寬長比
if aspRatio > 0.95 and aspRatio < 1.05 : objectType = "Square"
else:objectType = "Rectangle"
elif objCor>4 :objectType = "Circles"
else : objectType = "None"
# 繪製矩形框
x,y,w,h = cv2.boundingRect(approx) # x,y 寬 高
cv2.rectangle(imgContour,(x,y),(x+w,y+h),(0,255,0),2) #繪製矩形
cv2.putText(imgContour,objectType,(x+(w//2)-10,y+(h//2)-10),cv2.FONT_HERSHEY_COMPLEX,0.5,(0,0,0),2) #標註名稱
path = "Resources/shapes.png"
img = cv2.imread(path)
imgContour = img.copy()
#轉換成灰度 以便發現邊緣、拐角點
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#高斯函式 模糊處理
imgBlur = cv2.GaussianBlur(imgGray,(7,7),1)
#邊緣檢測器
imgCanny = cv2.Canny(imgBlur,50,50)
#黑白影象
imgBlank = np.zeros_like(img)
#得到輪廓
getContours(imgCanny)
imgStack = stackImages(0.6,([img,imgGray,imgBlur],
[imgCanny,imgContour,imgBlur]))
cv2.imshow("imgStack",imgStack)
# cv2.imshow("Original",img)
# cv2.imshow("Gray",imgGray)
# cv2.imshow("Blur",imgBlur)
cv2.waitKey(0)
9.面部識別
import cv2
import numpy as np
faceCascade = cv2.CascadeClassifier("Resources/haarcascade_frontalface_default.xml")
img = cv2.imread("Resources/lena.png")
img1 = cv2.imread("Resources/face1.jpg")
img2 = cv2.imread("Resources/face2.jpg")
imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(imgGray,1.1,4)
for (x,y,w,h) in faces:
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
cv2.imshow("imgStack",img)
cv2.waitKey(0)
結合charpter01 呼叫網路攝像頭進行人臉識別
import cv2
faceCascade = cv2.CascadeClassifier("Resources/haarcascade_frontalface_default.xml")
frameWidth = 640
frameHeight = 480
cap = cv2.VideoCapture(0)
cap.set(3, frameWidth)
cap.set(4, frameHeight)
cap.set(10,150)
while True:
success, img = cap.read()
imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(imgGray, 1.1, 4)
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
cv2.imshow("Result", img)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
python+opencv開啟大華攝像機視訊
import cv2
# 大華攝像機的視訊採集語句,subtype=1,輔碼流。0,主碼流。
cap = cv2.VideoCapture('rtsp://admin:[email protected]:554/cam/realmonitor?channel=1&subtype=1')
while(1):
# ret:成功返回True,失敗返回False
ret, frame = cap.read()
# 在影象上畫矩形:後面4組數字依次左上座標,右下座標,顏色,寬度
cv2.rectangle(frame,(10,0),(510,128),(0,255,0),3)
# 建立名為frame的視窗,顯示frame,
cv2.imshow('frame',frame)
# 按q鍵終止
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 釋放資源,關閉所有視窗
cap.release()
cv2.destroyAllWindows()