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()函数来查找检测物体的轮廓
import cv2
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:password@192.168.1.108: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()