2021-11-13计算机视觉之OpenCV

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:任意键销毁窗口,1000010000ms后销毁窗口
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()

二、实战(融汇贯通)

。。。

总结

。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值