openCV
目录
-
1.图像读取和展示
img_path = "C:\\Users\\User\\Desktop\\1.jpg" //图片的路径中不要有中文包括图片名称
img = cv2.imread(img_path) #imread读进去是BGR模式
print(img) # 如果直接print图片的话会得到一个三维数组
cv2.imshow("imag",img) # 引号中是展示窗口的名字
cv2.waitKey(0) # 等待敲击键盘来继续
cv2.destroyAllWindows() # 销毁所有窗口
cv2.imwrite('11.png',img) # 图像保存到本地
2.读取展示视频
vc=cv2.VideoCapture("guidao.mp3")
if vc.isOpened():
open,frame=vc.read()
else:
open=False
while open:
ret,frame=vc.read()
if frame is None:
break
if ret:
gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
cv2.imshow('result',gray)
if cv2.waitKey(100)&0xFF==27: //等多少秒播放下一帧
break
vc.release()
cv2.destroyAllWindows()
3.保留一个通道颜色
cur_img=img.copy() # imread进来是BGR
cur_img[:,:,0]=0 # B通道为0
cur_img[:,:,1]=0 # G通道为0
cv_show(cur_img) # 此时保留的R通道(红色)
4.图像填充
def img_fill(img):
top_size,bottom_size,left_size,right_size=(100,100,100,100)
# 复制拉伸边缘
replicate=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType=cv2.BORDER_REPLICATE)
# 镜面反射
reflect=cv2.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,cv2.BORDER_REFLECT)
# 去掉一点头的镜面反射
reflect_101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
# 复制整个图片取其中一部分
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
# 常数填充
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_CONSTANT,value=0)
# 0是黑色填充
plt.subplot(231), plt.imshow(img,'gray'),plt.title('original')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('replicate')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('reflect')
plt.subplot(234), plt.imshow(reflect_101, 'gray'), plt.title('reflect_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('wrap')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('cosntant')
plt.show()
5.图像合并
def img_merge(img_yue,img_zhu):
img_zhu = cv2.imread('C:\\Users\\User\\Desktop\\zhu1.jpg')
img_yue = cv2.imread('C:\\Users\\User\\Desktop\\yueyue.jpg')
print(img_zhu.shape) # 不同大小的图像不能合并
print(img_yue.shape) # 打印出两个图片大小
img_yue=cv2.resize(img_yue,(499,428)) # 转化其中的一个大小,裁剪像素
img_yue=cv2.resize(img_yue,(0,0),fx=0.3,fy=0.3) # 按比例缩放
print(img_yue.shape)
res=cv2.addWeighted(img_zhu,0.4,img_yue,0.6,5) # 两个数字为比重
plt.imshow(res)
cv_show(res)
6.图像阈值显示
img_path = "C:\\Users\\User\\Desktop\\1.jpg"
img = cv2.imread(img_path,cv2.IMREAD_GRAYSCALE) # 将图像转化成灰度
def img_thresh(img_yue): # 阈值显示必须是灰度图像
# 0-1函数
ret,thresh1=cv2.threshold(img_yue,127,255,cv2.THRESH_BINARY)
# 0-1反转函数
ret,thresh2 = cv2.threshold(img_yue, 127, 255, cv2.THRESH_BINARY_INV)
# 大于阈值设为阈值,否则不变
ret,thresh3 = cv2.threshold(img_yue, 127, 255, cv2.THRESH_TRUNC)
# 大于阈值不变,否则设为0
ret,thresh4 = cv2.threshold(img_yue, 127, 255, cv2.THRESH_TOZERO)
# TOZERO反转
ret,thresh5 = cv2.threshold(img_yue, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original ','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img_yue,thresh1,thresh2,thresh3,thresh4,thresh5]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
7.滤波函数
def img_blur(img):
# 均值滤波
# blur=cv2.blur(img,(3,3))
# 方框滤波
blur=cv2.boxFilter(img,-1,(3,3),normalize=True)
# normalize为True时与均值滤波相同,为False时容易越界,全取255
# 高斯滤波:离中心近的权重大
gaussian = cv2.GaussianBlur(img, (5, 5), 1)
# 中值滤波
median = cv2.medianBlur(img, 5)
# 集合展示
res = np.hstack((blur, gaussian, median))
cv_show(res)
8.腐蚀和膨胀
腐蚀和膨胀(相对于二色图来说)————腐蚀:黑的变多,膨胀:白的变多
def img_fushi(img):
kernel=np.ones((5,5),np.uint8)
erosion_1=cv2.erode(img,kernel,iterations=1)
erosion_2 = cv2.erode(img, kernel, iterations=2)
erosion_3 = cv2.erode(img, kernel, iterations=3)
res=np.hstack((img,erosion_1,erosion_2,erosion_3))
cv_show(res)
def img_pengzhang(img):
kernel=np.ones((5,5),np.uint8)
dilate_1=cv2.dilate(img,kernel,iterations=1)
dilate_2 = cv2.dilate(img, kernel, iterations=2)
dilate_3 = cv2.dilate(img, kernel, iterations=3)
res=np.hstack((img,dilate_1,dilate_2,dilate_3))
cv_show(res)
9.梯度计算
Sobel算法,Scharr算法,Laplacian算法
def gradient(img):
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=1)
# 对水平方向进行梯度计算
sobelx=cv2.convertScaleAbs(sobelx)
# 左右边界值有正有负检测效果不同,所以取绝对值
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=1)
sobely = cv2.convertScaleAbs(sobely)
sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0)# x,y等比例相加
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
# 对水平方向进行梯度计算
scharrx=cv2.convertScaleAbs(scharrx)
# 左右边界值有正有负检测效果不同,所以取绝对值
scharrx = cv2.Scharr(img, cv2.CV_64F, 0, 1)
scharrx = cv2.convertScaleAbs(scharrx)
scharrxy=cv2.addWeighted(scharrx,0.5,scharrx,0.5,0)# x,y等比例相加
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian=cv2.convertScaleAbs(laplacian)
res=np.hstack((img,sobelxy,scharrxy,laplacian))
cv_show(res)
10.Canny边缘检测
-
使用高斯滤波器 来平滑图像滤除噪声
-
计算图像中每个像素的梯度强度和方向
-
应用非极大值抑制,以消除边缘检测带来的杂散效应
-
应用双阈值检测来确定真实的和潜在的边缘
-
通过抑制孤立的弱边缘最终完成边缘检测
def canny(img):
img=cv2.imread(img_path+'lena.jpg',cv2.IMREAD_GRAYSCALE)
v1=cv2.Canny(img,80,150)
# 80是minvalue,小于80的不算边界
# 150是maxvalue,大于150的算边界
# 在80-150之间的如果与边界相连才算边界
v2=cv2.Canny(img,50,100)
# v2的检测阈值较小,所以将有更多的边界能被检测到,但也可能噪声过多
res=np.hstack((v1,v2))
cv_show(res)
11.高斯金字塔
高斯金字塔,拉普拉斯金字塔:对图像放大缩小
def up_down(img):
# Gauss
# 放大时候填充0然后高斯模糊,缩小直接高斯模糊
print(img.shape)
up=cv2.pyrUp(img)
print(up.shape)
down=cv2.pyrDown(img)
print(down.shape)
updown=cv2.pyrDown(up)
# Laplace
# 公式:Li=Gi-PyrUp(PyrDown(Gi))
laplace=img-updown
res=np.hstack((img,updown,laplace))
cv_show(res)
12.轮廓检测
def contours(img):
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(img_gray,127,255,cv2.THRESH_BINARY)
contours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# mode(轮廓检索模式):RETER_TREE:检索所有的轮廓,并重构轮廓的层次
# method(轮廓逼近模式): CHAIN_APPROX_NONE:以Freeman链码方式输出轮廓,其他所有方法输出多边形
# CHAIN_APPROX_SIMPLE:压缩水平的,垂直的和斜的部分,只保留终点部分
# 绘制轮廓
draw_img=img.copy()
new_img=cv2.drawContours(draw_img,contours,-1,(255,255,0),2)
# 此时要传入拷贝图像,否则会覆盖原始图像。
# -1指第几条轮廓(-1是全部轮廓)。(0,0,255)是轮廓线条的颜色。2是线条的宽度
res=np.hstack((img,new_img))
# cv_show(res)
# 轮廓特征(面积,周长)
cnt=contours[0]
print(cv2.contourArea(cnt)) # 面积
print(cv2.arcLength(cnt,True)) # 周长,True表示闭合的
# 轮廓近似
epsilon = 0.001*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)
draw_img1 = img_gray.copy()
new_img1 = cv2.drawContours(draw_img1, [approx], -1, (0, 255, 0), 3)
cv_show(new_img1)
13.模板匹配
def template(img):
img_template = cv2.imread(img_path+'face.png')
methods=['cv2.TM_CCOEFF','cv2.TM_CCOEFF_NORMED','cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED','cv2.TM_SQDIFF','cv2.TM_SQDIFF_NORMED']
h,w=img_template.shape[:2]
for meth in methods:
img2=img.copy()
# 匹配方法的真值
method=eval(meth)
print(method)
res=cv2.matchTemplate(img,img_template,method)
min_val,max_val,min_pos,max_pos=cv2.minMaxLoc(res)
# 如果是平方差匹配TM_SQDIFF或其归一化则取最小值
if method in [cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED]:
top_left=min_pos
else:
top_left=max_pos
bottom_right=(top_left[0]+w,top_left[1]+h)
# 画矩形
cv2.rectangle(img2,top_left,bottom_right,255,2)
plt.subplot(121),plt.imshow(res)
plt.xticks([]),plt.yticks([]) # 隐藏坐标轴
plt.subplot(122),plt.imshow(img2)
plt.suptitle(meth)
plt.show()
14.直方图
def calchist(img):
hist=cv2.calcHist([img],[0],None,[256],[0,256])
plt.hist(img.ravel(),256)
plt.show()
color=('b','g','r')
for i,col in enumerate(color):
histr=cv2.calcHist([img],[i],None,[256],[0,256])
plt.plot(histr,color=col)
plt.xlim([0,256])
plt.show()
# 掩码
mask=np.zeros(img.shape[:2],np.uint8)
mask[100:300,100:300]=255
masked_img=cv2.bitwise_and(img,img,mask=mask) # 与操作
hist_full=cv2.calcHist([img],[0],None,[256],[0,256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])
plt.subplot(221),plt.imshow(img,'gray')
plt.subplot(222), plt.imshow(mask,'gray')
plt.subplot(223), plt.imshow(masked_img,'gray')
plt.subplot(224), plt.plot(hist_full),plt.plot(hist_mask)
plt.xlim([0,256])
plt.show()
# 掩码均衡化
img1 = cv2.imread(img_path+'lena.jpg',0)
plt.hist(img.ravel(),256)
plt.show()
equ=cv2.equalizeHist(img1)
plt.hist(equ.ravel(),256)
plt.show()
# 自适应均衡化处理:分成很多部分独立均衡化
clahe=cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
res=clahe.apply(img1)
cv_show(res)
15.光流估计
import numpy as np
import cv2
cap=cv2.VideoCapture('C:\\Users\\User\\Desktop\\test.avi')
# 角点检测所需的参数
feature_params=dict(maxCorners=100,
qualityLevel=0.3,
minDistance=7)
# lucas-kanade参数
lk_params=dict(winSize=(15,15),
maxLevel=2)
# 随机颜色条
color=np.random.randint(0,255,(100,3))
# 拿到第一帧图像
ret,old_frame=cap.read()
old_gray=cv2.cvtColor(old_frame,cv2.COLOR_BGR2GRAY)
# 返回所有检测特征点,需要输入图像,角点最大数量(效率),品质因子(特征值越大的越好,以此筛选)
# 距离相当于这个区间有比这个角点强的就不要这个弱的了
p0=cv2.goodFeaturesToTrack(old_gray,mask=None, **feature_params)
# 创建一个mask
mask=np.zeros_like(old_frame)
while(True):
ret ,frame=cap.read()
frame_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
# 需要传入前一帧和当前帧以及前一帧检测到的角点
p1,st,err=cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,p0,None,**lk_params)
# st=1表示找到
good_new=p1[st==1]
good_old=p0[st==1]
# 绘制轨迹
for i,(new,old) in enumerate(zip(good_new,good_old)):
a,b=new.ravel()
c,d=old.ravel()
mask=cv2.line(mask,(a,b),(c,d),color[i].tolist(),2)
frame=cv2.circle(frame,(a,b),5,color[i].tolist(),-1)
img=cv2.add(frame,mask)
cv2.imshow("frame",img)
k=cv2.waitKey(150)&0xff
if k==27:
break
# 更新
old_gray=frame_gray.copy()
p0=good_new.reshape(-1,1,2)
cv2.destroyAllWindows()
cap.release()