2021-11-13计算机视觉之OpenCV
前言
学习资料https://www.bilibili.com/video/BV1PV411774y?p=47
OpenCV学习笔记
项目一套:
一、理论基础
import cv2
from matplotlib import pyplot as plt
import numpy as np
%matplotlib inline
def img_show(img):
cv2.imshow('result',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
#图像
#读取图像
img = cv2.imread('./imgs/1.jpg')
#显示图像
cv2.imshow('img',img)
cv2.waitKey(0) #0:任意键销毁窗口,10000:10000ms后销毁窗口
cv2.destroyAllWindows()
#视频
#读取视频
video = cv2.VideoCapture('./video/1.mp4')
if video.isOpened():
open,frame =video.read()
else:
open = False
print(open)
#显示视频
while open:
ret,frame = video.read()
if frame is None:
break
if ret == True:
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
cv2.imshow('gray',gray)
if cv2.waitKey(10) & 0xFF == 27:
open = False
break
video.release()
cv2.destroyAllWindows()
#图像切割(ROI区域)
img = cv2.imread('./imgs/2.jpg')
roi = img.copy()
roi = roi[:,:,2]
img_show(roi)
#图像边缘填充
img = cv2.imread('./imgs/3.jpg')
top,bottom,left,right = (50,50,50,50)
fillborder_img = cv2.copyMakeBorder(img,top,bottom,left,right,cv2.BORDER_REFLECT)
img_show(fillborder_img)
#图像计算
#加法:
#img1+img2 注意他们的shape要一致
#cv2.add(img1,img2) 区别是:数值溢出时,'+'取多余的,add()取
#改变图像形状
#cv2.resize(img,(y,x),fx,fy)
#等比例放大4倍,fx=4,fy=4
#不等比例,fx=4,fy=8
#图像融合
#cv2.addWeighted(img1,权重1,img2,权重2,偏置b) img3= W1*img1+W2*img2+b
#图像阈值
#ret(阈值),输出的图像 = cv2.threshold(img,阈值,最大值,处理方法)
#图像平滑处理
#均值滤波
#输出图片 = cv2.blur(img,(3,3)) (3,3):滤波核大小
#作用:把滤波核中每个像素换成滤波核的均值
#滤波核大小一半为奇数
#方框滤波(作用和均值滤波一样)
#输出图片 = cv2.boxFilter(img,-1,(3,3),normalize=True)
#作用:把滤波核中每个像素换成滤波核的均值
#滤波核大小一半为奇数
#区别:可以进行标准化
#高斯滤波
#输出图片 = cv2.GaussianBlur(img,(3,3),1)
#作用:滤波核越中间权重越大
#中值滤波(去噪声效果最好)
#输出图片 = cv2.medianBlur(img,(3,3))
#作用:把滤波核中每个像素换成滤波核的中值(滤波核的中间数)
#图片拼接显示
#输出 = np.hstack((img1,img2,img3)) 横着显示
#输出 = np.vstack((img1,img2,img3)) 竖着显示
#图像腐蚀
#cv2.erode(img,(3,3),iterations=3) (3,3):腐蚀核,iteration:迭代次数
#图像膨胀
#cv2.dilate(img,(3,3),iterations=3)
#腐蚀和膨胀互逆
#图像去刺,先腐蚀,后膨胀
#开运算和闭运算
#开运算:先腐蚀,后膨胀
#cv2.morphologyEx(img,cv2.MORPH_OPEN,(3,3))
#闭运算:先膨胀,后腐蚀
#cv2.morphologyEx(img,cv2.MORPH_CLOSE,(3,3))
#梯度运算:本质是膨胀-腐蚀
#cv2.morphologyEx(img,cv2.MORPH_GRADIENT,(3,3))
#作用:得到边界
#礼帽和黑帽
#礼帽:本质是原始输入-开运算
#cv2.morphologyEx(img,cv2.MORPH_TOPHAT,(3,3))
#作用:得到刺
#黑帽:本质是闭运算-原始输入
#cv2.morphologyEx(img,cv2.MORPH_TOPHAT,(3,3))
#作用:得到膨胀多余的
#图像梯度
#Sobel算子:边缘提取cv2.Sobel
# [-1,0,+1, [-1,-2,-1,
#水平: -2,0,+2, 垂直: 0, 0, 0,
# -1,0,+1] +1,+2,+1]
#Scharr算子:边缘提取cv2.Scharr
# [- 3,0,+3, [-3,-10,-3,
#水平: -10,0,+10, 垂直:0, 0, 0,
# - 3,0,+3] +3,+10,+3]
#Laplacian算子:边缘提取cv2.Laplacian
# [0, 1,0,
# 1,-4,1,
# 0, 1,0]
img=cv2.imread('./imgs/5.jpg')
#img_show(img)
#注意:1.一半图像深度为0-255,不包含负数的,所以要使用cv2.CV_64F兼容负数
# 2.记得取绝对值
#方法1(标准)
hborder = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) #参数:输入图像,图像深度,使用水平方向,不使用垂直方向,算子大小
hborder = cv2.convertScaleAbs(hborder) #取绝对值
#img_show(hborder)
vborder = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) #参数:输入图像,图像深度,不使用水平方向,使用垂直方向,算子大小
vborder = cv2.convertScaleAbs(vborder) #取绝对值
#img_show(vborder)
border_my1 = cv2.addWeighted(hborder,0.5,vborder,0.5,0)
#img_show(border_my1)
#方法2(我的)
border_my2 = hborder+vborder
#img_show(border_my2)
#方法3(差的)
border_my3 = cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3) #水平和垂直一起算
border_my3 = cv2.convertScaleAbs(border_my3)
#img_show(border_my3)
border = np.hstack((border_my1,border_my2,border_my3))
#img_show(border)
#Sobel算子
xSobel = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
xSobel = cv2.convertScaleAbs(xSobel)
ySobel = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
ySobel = cv2.convertScaleAbs(ySobel) #取绝对值
border_Sobel = cv2.addWeighted(xSobel,0.5,ySobel,0.5,0)
#Scharr算子
xScharr = cv2.Scharr(img,cv2.CV_64F,1,0)
xScharr = cv2.convertScaleAbs(xScharr) #取绝对值
yScharr = cv2.Scharr(img,cv2.CV_64F,0,1)
yScharr = cv2.convertScaleAbs(yScharr) #取绝对值
border_Scharr = cv2.addWeighted(xScharr,0.5,yScharr,0.5,0)
#Laplacian算子
laplacian = cv2.Laplacian(img,cv2.CV_64F,ksize=3) #参数:输入图像,图像深度,不使用水平方向,使用垂直方向,算子大小
laplacian = cv2.convertScaleAbs(laplacian) #取绝对值
compare = np.hstack((border_Sobel,border_Scharr,laplacian))
img_show(compare)
#Canny边缘检测
#1.高斯滤波器进行滤波,图像平滑处理
#2.计算梯度的大小和方向
#3.应用非极大值抑制,把是梯度的像素点和周围的八个点进行比较,看看是不是最大值
#4.应用双阈值,尽可能的把边缘连接起来
#5.抑制孤立边缘
img = cv2.imread('./imgs/4.jpg',cv2.IMREAD_GRAYSCALE)
#img_show(img)
canny1 = cv2.Canny(img,50,127) #低阈值,高阈值
canny2 = cv2.Canny(img,100,200)
canny = np.hstack((canny1,canny2))
#img_show(canny2)
#图像金字塔
#高斯金字塔 (倒立的)
#Up:向上采样,放大图像1倍
#一个像素点用0填充,后核计算均值并填入
#Down:向下采样,缩小图像1倍
#先进行高斯滤波,再把偶数行和列去掉
#拉普拉斯金字塔
#用原图像-先Up在Down的图像
#图象轮廓
#读取图像(灰度图)
img = cv2.imread('./imgs/2.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#img_show(gray)
#图像二值化处理
ret,thresh = cv2.threshold(gray,100,255,cv2.THRESH_BINARY)
#img_show(thresh)
#寻找轮廓
#轮廓 图层 src 常用这个 cv2.CHAIN_APPROX_SIMPLE画点,下面的画线条
contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
#画轮廓
draw = img.copy()
# 画的src;轮廓;-1代表所有;BGR画红色;线宽
x = cv2.drawContours(draw,contours,-1,(0,0,255),2)
#img_show(draw)
#轮廓用途:
contour = contours[0]
#计算面积
area = cv2.contourArea(contour)
#计算周长
#closed:是否闭合
arcLength = cv2.arcLength(contour,closed=True)
#获得外接矩形
rect = cv2.boundingRect(contour)
#轮廓近似
#图像预处理
img = cv2.imread('./imgs/contours.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
#img_show(thresh)
#轮廓获取
contours ,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
contour = contours[1]
#轮廓近似
#0.01:越大轮廓越不精准
epsilon = 0.01*cv2.arcLength(contour,True)
approx = cv2.approxPolyDP(contour,epsilon,True)
#显示
draw_img = img.copy()
res = cv2.drawContours(draw_img,[approx],-1,(0,0,255),2)
img_show(res)
#模板匹配
#匹配的方法
#cv2.TM_CCORR,cv2.TM_CCOEFF_NORMED,cv2.TM_CCORR,cv2.TM_CCORR_NORMED,cv2.TM_SQDIFF,cv2.TM_SQDIFF_NORMED
img = cv2.imread('./imgs/5.jpg')
template = img[100:400,100:400]
#img_show(template)
res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)
#res.shape = (img-template+1,img-template+1)
#res:得到每一个窗口的结果
#匹配程度大于等于80%的坐标:
#threshold = 0.8
#loc = np.where(res>=threshold)
min_val,max_val,min_loc,max_loc = cv2.minMaxLoc(res)
#min_loc坐标
#如果是平方差匹配TM_SQDIFF或归一化平方差匹配TM_SQDIFF_NORMED,取最小,其他最大
img2 = img.copy()
top_left = max_loc
bottom_right = (top_left[0]+template.shape[0],top_left[1]+template.shape[1])
cv2.rectangle(img2,top_left,bottom_right,(0,0,255),2)
img_show(img2)
#直方图
img = cv2.imread('./imgs/5.jpg',0)
#img_show(img)
hist = cv2.calcHist([img],[0],None,[256],[0,256])
plt.hist(img.ravel(),256)
plt.show()
#傅里叶变换
#低通滤波器,使图像模糊
#高通滤波器,不留细节,只留下边界信息
img = cv2.imread('./imgs/5.jpg')
img_float32 = np.float32(img)
dft = cv2.dft(img_float32,flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))
plt.subplot(121),plt.imshow(img,cmap='gray')
plt.subplot(122),plt.imshow(magnitude_spectrum,cmap='gray')
plt.show()
#低通滤波器
img = cv2.imread('./imgs/5.jpg')
img_float32 = np.float32(img)
dft = cv2.dft(img_float32,flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
rows,cols = img.shape
crow,ccol = int(rows/2),int(cols)#中心位置
#低通滤波
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30,ccol-30:ccol+30]=1
#IDFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[,:,:,1])
plt.subplot(121),plt.imshow(img,cmap='gray')
plt.subplot(122),plt.imshow(img_back,cmap='gray')
plt.show()
#高通滤波器
img = cv2.imread('./imgs/5.jpg')
img_float32 = np.float32(img)
dft = cv2.dft(img_float32,flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
rows,cols = img.shape
crow,ccol = int(rows/2),int(cols)#中心位置
#高通滤波
mask = np.zeros((rows,cols,2),np.uint8)
mask[crow-30:crow+30,ccol-30:ccol+30]=0
#IDFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[,:,:,1])
plt.subplot(121),plt.imshow(img,cmap='gray')
plt.subplot(122),plt.imshow(img_back,cmap='gray')
plt.show()
二、实战(融汇贯通)
。。。
总结
。。。