一:读取图片和视频文件
image = cv2.imread('image.jpg', cv2.IMREAD_COLOR) #读取彩色图像,灰度图像为IMREAD_GRAYSCALE
cv2.imshow('windoews_name', image)
cap = cv2.VideoCapure(0)
while True:
ret, frame = cap.read() # 你读取的帧是frame,后续对视频的操作也就是对每一帧frame的操作
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) # 此处灰度化,还有cv2.COLOR_BGR2HSV
cv2.imshow('gray',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.realease()
cv2.destroyAllWindows()
二:缩放图片
height, width = img.shape[:2] # 此处为缩放,采样(图像上缩小),最合适的插值方法是 cv.INTER_AREA
# 对于上采样(放大),最好的方法是 cv.INTER_CUBIC (速度较慢)和
# cv.INTER_LINEAR (速度较快)
res2 = cv2.resize(img, (2*width, 2*height), interpolation=cv.INTER_CUBIC)
三:透射变换
pts1 = np.float32([[56,65], [368,52], [28,387], [389,390]]) # 透射变换的示例代码,一般pts1是
检测出来的矩形,譬如我们想要扫描箱
子上的二维码,就可以用透射变换将箱
子表面“铺平”
pts2 = np.float32([[0,0], [300,0], [0,300], [300,300]])
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img,M,(300, 300))
四:二值化
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY) # 后面还有参数cv2.THRESH_TRUNC,
类似于渐变
th = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
# 自适应二值化,对减少光照影响很有用
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
五:一些滤波
blur = cv.GaussianBlur(img,(5,5),0) # 高斯滤波
blur = cv.bilateralFilter(img,9,75,75) # 双边滤波
median = cv.medianBlur(img,5) # 中值滤波,去除花椒噪音,不常用(正常哪来的花椒噪音)
六:腐蚀膨胀,开闭运算
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
dilation = cv2.dilate(img, kernel, iterations=1)
closing = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel,iterations=1) # 消除白色噪音
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel,iterations=1) # 填充黑色空洞
七:Canny边缘检测
edges = cv2.Canny(img,100,200)
解释一下这两个参数的意义,这两个都是强度梯度,我们认为,当强度低于前面一个参数的时候,不可能是边缘,高于后面一个参数的时候,一定是边缘。考虑到边缘具有连续性,如果一个连续的线存在一部分高于后面的参数,我们认为这就是边缘。具体可以参考如下的图片,AC是连续的,是边缘(尽管C强度不那么高,但是相连的A一定是边缘,所以C也是),B不是边缘,整体强度不够
八:寻找和绘制轮廓
1.寻找轮廓
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
第二个参数为轮廓检索模式,
-
cv.RETR_EXTERNAL
: 只检索最外层的轮廓。cv.RETR_LIST
: 检索所有轮廓,但不建立层次关系。cv.RETR_CCOMP
: 检索所有轮廓并将其组织为两级层次结构。顶层是外部边界,次层是孔的边界。cv.RETR_TREE
: 检索所有轮廓并重构嵌套轮廓的完整层次结构。
第三个参数为轮廓近似方法
-
cv.CHAIN_APPROX_NONE
: 存储所有轮廓点。cv.CHAIN_APPROX_SIMPLE
: 只存储角点,如水平、垂直和对角线的起点和终点。cv.CHAIN_APPROX_TC89_L1
和cv.CHAIN_APPROX_TC89_KCOS
: 使用 Teh-Chin 链码算法的近似方法。
contours
: 可选参数,轮廓的输出向量,每个轮廓是一个点的向量。hierarchy
: 可选参数,输出的轮廓层次信息。offset
: 可选参数,向每个轮廓点添加的偏移量
2.绘制轮廓
cv2.drawContours(img, contours, -1, (0,255,0), 3)
第二个参数-1表示绘制所有轮廓,如果是自然数则为绘制索引的轮廓。最后一个参数3表示绘制线条的粗细
九:轮廓的不同特征
1.矩
M = cv2.monents(contour)
cx = int(M['m10']/M['m00']) # x的质心
cy = int(M['m01']/M['m00']) # y的质心
2.面积,周长
area = cv2.contourArea(cnt)
perimeter = cv2.arcLength(cnt,True)
3.轮廓近似
epsilon = 0.1*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
True指的是是否闭合,epsilon是近似精度,精度越高越贴合原来的轮廓(相当于没怎么拟合,包保持复杂度)
4.矩形包围
x,y,w,h = cv2.boundingRect(cnt)
cv.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2) # 水平矩形
rect = cv2.minAreaRect(cnt) # 旋转矩形
box = cv2.boxPoints(rect)
box = np.int0(box)
cv.drawContours(img,[box],0,(0,0,255),2)
(x,y),radius = cv2.minEnclosingCircle(cnt) # 最小外接圆
center = (int(x),int(y))
radius = int(radius)
cv2.circle(img,center,radius,(0,255,0),2)
还有长宽比的比率
x,y,w,h = cv2.boundingRect(cnt)
aspect_ratio = float(w)/h
十:霍夫变换
1.霍夫线变换
lines = cv2.HoughLines(edges,1,np.pi/180,200)
for line in lines:
rho,theta = line[0]
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)
第二、第三参数分别是 \(𝜌\) 和 \(𝜃\) 的精度,第四个参数可以认为是这个直线穿过了多少点
还有概率霍夫线变换
lines = cv2.HoughLinesP(edges,1,np.pi/180,100,minLineLength=100,maxLineGap=10)
for line in lines:
x1,y1,x2,y2 = line[0]
cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)
2.霍夫圆变换
circles = cv.HoughCircles(img,cv.HOUGH_GRADIENT,1,20,
param1=50,param2=30,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv.circle(cimg,(i[0],i[1]),2,(0,0,255),3)