学习资源
链接:链接,提取码:3vt7
简介
安装 :pip install opencv-python==3.4.2.17 测试 :
import cv2
lena=cv2.imread("1.jpg")
cv2.imshow("image",lena)
cv2.waitKey(0)
利用SIFT和SURF进行特征提取的话,还需要pip install opencv-contrib-python==3.4.2.17
基础模块 :core、highgui、imgproc
- core模块实现了最核心的数据结构及其基本运算,如绘图函数、数组操作相关函数等。
- highgui模块实现了视频与图像的读取、显示、存储等接口。
- imgproc模块实现了图像处理的基础方法,包括图像滤波、图像的几何变换、平滑、阈值分割、形态学处理、边缘检测、目标检测、运动分析和对象跟踪等。
其余模块:
features2d模块用于提取图像特征以及特征匹配,nonfree模块实现了一些专利算法,如sift特征。 stitching模块实现了图像拼接功能。 FLANN模块(Fast Library for Approximate Nearest Neighbors),包含快速近似最近邻搜索FLANN 和聚类Clustering算法。 ml模块机器学习模块(SVM,决策树,Boosting等等)。 photo模块包含图像修复和图像去噪两部分。 video模块针对视频处理,如背景分离,前景检测、对象跟踪等。 G-API模块包含超高效的图像处理pipeline引擎
基本操作
读取图像 API:cv.imread() , 参数:
- 读取的图像
- 读取方式的标志
cv.IMREADCOLOR:以彩色模式加载图像,任何图像的透明度都将被忽略。这是默认参数。 cv.IMREADGRAYSCALE:以灰度模式加载图像 cv.IMREAD_UNCHANGED:包括alpha通道的加载图像模式。 可以使用1、0或者-1来替代上面三个标志
参考代码:
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
显示图像 API:cv.imshow() , 参数:
- 显示图像的窗口名称,以字符串类型表示
- 要加载的图像
注意:在调用显示图像的API后,要调用cv.waitKey()给图像绘制留下时间,否则窗口会出现无响应情况,并且图像无法显示出来。
参考代码:
cv.imshow('image',img)
cv.waitKey(0)
plt.imshow(img[:,:,::-1])
保存图像 API:cv.imwrite() , 参数:
参考代码:
cv.imwrite('messigray.png',img)
绘制直线 API:cv.line(img,start,end,color,thickness) , 参数:
- img:要绘制直线的图像
- Start,end: 直线的起点和终点
- color: 线条的颜色
- Thickness: 线条宽度
绘制圆形 API:cv.circle(img,centerpoint, r, color, thickness) , 参数:
- img:要绘制圆形的图像
- Centerpoint, r: 圆心和半径
绘制矩形 API:cv.rectangle(img,leftupper,rightdown,color,thickness) , 参数:
- img:要绘制矩形的图像
- Leftupper, rightdown: 矩形的左上角和右下角坐标
添加文字 API:cv.putText(img,text,station, font, fontsize,color,thickness,cv.LINE_AA) , 参数:
- img: 图像
- text:要写入的文本数据
- station:文本的放置位置
- font:字体
- Fontsize :字体大小
获取并修改图像中的像素点 :我们可以通过行和列的坐标值获取该像素点的像素值。对于BGR图像,它返回一个蓝,绿,红值的数组。对于灰度图像,仅返回相应的强度值。使用相同的方法对像素值进行修改。
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
px = img[100,100]
blue = img[100,100,0]
img[100,100] = [255,255,255]
获取图像的属性 :img.shape、img.size、img.dtype 图像通道的拆分与合并 :有时需要在B,G,R通道图像上单独工作。在这种情况下,需要将BGR图像分割为单个通道。或者在其他情况下,可能需要将这些单独的通道合并到BGR图像。
b,g,r = cv.split(img)
img = cv.merge((b,g,r))
色彩空间的改变 : API:cv.cvtColor(input_image,flag) , 参数:
- input_image: 进行颜色空间转换的图像
- flag: 转换类型
cv.COLOR_BGR2GRAY : BGR?Gray cv.COLOR_BGR2HSV: BGR→HSV
图像加法 :cv.add(img1,img2) ,不推荐使用numpy数组直接相加,而是用cv的add方法 图像混合 :cv.addweight(img1,x1,img2,x2) ,相当于按权相加,
i
m
g
1
?
x
1
+
i
m
g
2
?
x
2
img_1*x_1+img_2*x_2
img1??x1?+img2??x2? 注 :这里都要求两幅图像是相同大小的。
图像处理
几何变换
图像缩放 :缩放是对图像的大小进行调整,即使图像放大或缩小。 API:cv2.resize(src,dsize,fx=0,fy=0,interpolation=cv2.INTER_LINEAR) , 参数:
- src : 输入图像
- dsize: 绝对尺寸,直接指定调整后图像的大小
- fx,fy: 相对尺寸,将dsize设置为None,然后将fx和fy设置为比例因子即可
- interpolation:插值方法,
参考代码:
import cv2 as cv
import matplotlib.pyplot as plt
img1 = cv.imread(r"./img/1.jpg")
rows,cols = img1.shape[:2]
res = cv.resize(img1,(2*cols,2*rows),interpolation=cv.INTER_CUBIC)
res1 = cv.resize(img1,None,fx=0.5,fy=0.5)
fig,axes=plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
axes[0].imshow(res[:,:,::-1])
axes[0].set_title("boost")
axes[1].imshow(img1[:,:,::-1])
axes[1].set_title("origin")
axes[2].imshow(res1[:,:,::-1])
axes[2].set_title("shrink")
plt.show()
图像平移 :图像平移将图像按照指定方向和距离,移动到相应的位置。 API:cv.warpAffine(img,M,dsize) , 参数:
- img: 输入图像
- M: 2*?3移动矩阵
- dsize: 输出图像的大小
注意:1、输出图像的大小,它应该是(宽度,高度)的形式;2、对于(x,y)处的像素点,要把它移动到
(
x
+
t
x
,
y
+
t
y
)
(x+t_x , y+t_y)
(x+tx?,y+ty?)处时,M矩阵应如下设置,并且将M设置为np.float32类型的Numpy数组。
参考代码:需求是将图像的像素点移动(50,100)的距离:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img1 = cv.imread(r"./img/1.jpg")
rows,cols = img1.shape[:2]
M = np.float32([[1,0,100],[0,1,50]])
dst = cv.warpAffine(img1,M,(cols,rows))
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("origin")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("move")
plt.show()
图像旋转 :图像旋转是指图像按照某个位置转动一定角度的过程,旋转中图像仍保持这原始尺寸。在OpenCV中图像旋转首先根据旋转角度和旋转中心获取旋转矩阵,然后根据旋转矩阵进行变换,即可实现任意角度和任意中心的旋转效果。
API:cv2.getRotationMatrix2D(center, angle, scale) ,cv.warpAffine 。 参数:
- center:旋转中心
- angle:旋转角度
- scale:缩放比例
注意:前者用于生成旋转矩阵,后者用于旋转
参考代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img1 = cv.imread(r"./img/1.jpg")
rows,cols = img1.shape[:2]
M = cv.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv.warpAffine(img1,M,(cols,rows))
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("origin")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("move")
plt.show()
仿射变换 :图像的仿射变换涉及到图像的形状位置角度的变化,是深度学习预处理中常到的功能,仿射变换主要是对图像的缩放,旋转,翻转和平移等操作的组合。 什么是仿射变换 :如下图所示,图1中的点1, 2 和 3 与图二中三个点一一映射, 仍然形成三角形, 但形状已经大大改变,通过这样两组三点(感兴趣点)求出仿射变换, 接下来我们就能把仿射变换应用到图像中所有的点中,就完成了图像的仿射变换。
API:cv2.getAffineTransform(src, dst) ,cv.warpAffine 。 参数:
- src表示原图中的三个点
- dst表示输出图像中的三个点
注意:前者用于生成仿射矩阵,后者用于变换
参考代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img1 = cv.imread(r"./img/1.jpg")
rows,cols = img1.shape[:2]
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[100,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
dst = cv.warpAffine(img1,M,(cols,rows))
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("origin")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("move")
plt.show()
透射变换 :透射变换是视角变化的结果,是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。 API:cv.getPerspectiveTransform(src,dst) ,cv.warpAffine 。 参数:
- src表示原图中的四个点,其中任意三个不共线
- dst表示输出图像中的四个点,其中任意三个不共线
注意:前者用于生成透射矩阵,后者用于变换
参考代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img1 = cv.imread(r"./img/1.jpg")
rows,cols = img1.shape[:2]
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[100,145],[300,100],[80,290],[310,300]])
T = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.warpPerspective(img1,T,(cols,rows))
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img1[:,:,::-1])
axes[0].set_title("origin")
axes[1].imshow(dst[:,:,::-1])
axes[1].set_title("move")
plt.show()
图像金字塔 :图像金字塔是图像多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效但概念简单的结构。图像金字塔用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似,层级越高,图像越小,分辨率越低。 API:上采样cv.pyrUp(img) ,下采样:cv.pyrDown(img) 参考代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img1 = cv.imread(r"./img/1.jpg")
up_img = cv.pyrUp(img1)
down_img = cv.pyrDown(img1)
fig,axes=plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
axes[0].imshow(up_img[:,:,::-1])
axes[0].set_title("up")
axes[1].imshow(img1[:,:,::-1])
axes[1].set_title("origin")
axes[2].imshow(down_img[:,:,::-1])
axes[2].set_title("down")
plt.show()
形态学操作
鸽
图像平滑
概述 :图像平滑从信号处理的角度看就是去除其中的高频信息,保留低频信息。因此我们可以对图像实施低通滤波。低通滤波可以去除图像中的噪声,对图像进行平滑。根据滤波器的不同可分为均值滤波,高斯滤波,中值滤波, 双边滤波。 噪声 :椒盐噪声:图像中随机出现的白点或者黑点;高斯噪声:噪声的概率密度分布是正态分布
均值滤波 :均值滤波的优点是算法简单,计算速度较快,缺点是在去噪的同时去除了很多细节部分,将图像变得模糊。 API:cv.blur(src, ksize, anchor, borderType) , 参数:
- src:输入图像
- ksize:卷积核的大小
- anchor:默认值 (-1,-1) ,表示核中心
- borderType:边界类型
参考代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread(r"./img/3.jpeg")
blur = cv.blur(img,(5,5))
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title('origin')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur[:,:,::-1]),plt.title('after')
plt.xticks([]), plt.yticks([])
plt.show()
高斯滤波 :高斯平滑在从图像中去除高斯噪声方面非常有效。 API:cv2.GaussianBlur(src,ksize,sigmaX,sigmay,borderType) , 参数:
- src: 输入图像
- ksize:高斯卷积核的大小,注意 : 卷积核的宽度和高度都应为奇数,且可以不同
- sigmaX: 水平方向的标准差
- sigmaY: 垂直方向的标准差,默认值为0,表示与sigmaX相同
- borderType:填充边界类型
参考代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread(r"./img/3.jpeg")
blur = cv.GaussianBlur(img,(3,3),1)
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img[:,:,::-1]),plt.title('origin')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur[:,:,::-1]),plt.title('after')
plt.xticks([]), plt.yticks([])
plt.show()
中值滤波 :去除椒盐噪声 API:cv.medianBlur(src, ksize ) , 参数:
直方图
灰度直方图 原理 :直方图是对数据进行统计的一种方法,并且将统计值组织到一系列实现定义好的 bin 当中。其中, bin 为直方图中经常用到的一个概念,可以译为 “直条” 或 “组距”,其数值是从数据中计算出的特征统计量,这些数据可以是诸如梯度、方向、色彩或任何其他特征。 图像直方图 :是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素个数。这种直方图中,横坐标的左侧为较暗的区域,而右侧为较亮的区域。因此一张较暗图片的直方图中的数据多集中于左侧和中间部分,而整体明亮、只有少量阴影的图像则相反。 注 : 术语和细节 :
- dims:需要统计的特征数目。在上例中,dims = 1 ,因为仅仅统计了灰度值。
- bins:每个特征空间子区段的数目,可译为 “直条” 或 “组距”,在上例中, bins = 16。
- range:要统计特征的取值范围。在上例中,range = [0, 255]。
直方图的意义 :
- 直方图是图像中像素强度分布的图形表达方式。
- 它统计了每一个强度值所具有的像素个数。
- 不同的图像的直方图可能是相同的
直方图的计算和绘制 API:cv2.calcHist(images,channels,mask,histSize,ranges[,hist[,accumulate]]) , 参数:
- images: 原图像。当传入函数时应该用中括号 [] 括起来,例如:[img]。
- channels: 如果输入图像是灰度图,它的值就是 [0];如果是彩色图像的话,传入的参数可以是 [0],[1],[2] 它们分别对应着通道 B,G,R。
- mask: 掩模图像。要统计整幅图像的直方图就把它设为 None。但是如果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像,并使用它。(后边有例子)
- histSize:BIN 的数目。也应该用中括号括起来,例如:[256]。
- ranges: 像素值范围,通常为 [0,256]
参考代码:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread(r'./img/cat.jpeg',0)
histr = cv.calcHist([img],[0],None,[256],[0,256])
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].plot(histr)
axes[0].set_title("up")
axes[1].imshow(img)
axes[1].set_title("origin")
plt.show()
掩膜的应用 :掩膜是用选定的图像、图形或物体,对要处理的图像进行遮挡,来控制图像 处理的区域。在数字图像处理中,我们通常使用二维矩阵数组进行掩膜。掩膜是由0和1组成一个二进制图像,利用该掩膜图像要处理的图像进行掩膜,其中1值的区域被处理,0 值区域被屏蔽,不会处理。概述 :创建蒙版,透过mask进行传递,可获取感兴趣区域的直方图
参考代码:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread(r'./img/cat.jpeg',0)
mask = np.zeros(img.shape[:2], np.uint8)
mask[400:650, 200:500] = 255
masked_img = cv.bitwise_and(img,img,mask = mask)
mask_histr = cv.calcHist([img],[0],mask,[256],[1,256])
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img,cmap=plt.cm.gray)
axes[0,0].set_title("原图")
axes[0,1].imshow(mask,cmap=plt.cm.gray)
axes[0,1].set_title("蒙版数据")
axes[1,0].imshow(masked_img,cmap=plt.cm.gray)
axes[1,0].set_title("掩膜后数据")
axes[1,1].plot(mask_histr)
axes[1,1].grid()
axes[1,1].set_title("灰度直方图")
plt.show()
直方图均衡化 :是把原始图像的灰度直方图从比较集中的某个灰度区间变成在更广泛灰度范围内的分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。这种方法提高图像整体的对比度,特别是有用数据的像素值分布比较接近时,在X光图像中使用广泛,可以提高骨架结构的显示,另外在曝光过度或不足的图像中可以更好的突出细节。概述 :增强图像对比度的一种方法
API:dst = cv.equalizeHist(img) , 参数:
- img: 灰度图像
注意:dst : 均衡化后的结果
参考代码:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread(r'./img/cat.jpeg',0)
dst = cv.equalizeHist(img)
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[0].set_title("原图")
axes[1].imshow(dst,cmap=plt.cm.gray)
axes[1].set_title("均衡化后结果")
plt.show()
自适应的直方图均衡化 :上述的直方图均衡,我们考虑的是图像的全局对比度。 的确在进行完直方图均衡化之后,图片背景的对比度被改变了,在猫腿这里太暗,我们丢失了很多信息,所以在许多情况下,这样做的效果并不好。如下图所示,对比下两幅图像中雕像的画面,由于太亮我们丢失了很多信息。为了解决这个问题, 需要使用自适应的直方图均衡化。 此时, 整幅图像会被分成很多小块,这些小块被称为“tiles”(在 OpenCV 中 tiles 的 大小默认是 8x8),然后再对每一个小块分别进行直方图均衡化。 所以在每一个的区域中, 直方图会集中在某一个小的区域中)。如果有噪声的话,噪声会被放大。为了避免这种情况的出现要使用对比度限制。对于每个小块来说,如果直方图中的 bin 超过对比度的上限的话,就把 其中的像素点均匀分散到其他 bins 中,然后在进行直方图均衡化。最后,为了 去除每一个小块之间的边界,再使用双线性差值,对每一小块进行拼接。概述 :将整幅图像分成很多小块,然后再对每一个小块分别进行直方图均衡化,最后进行拼接
API:cv.createCLAHE(clipLimit, tileGridSize) , 参数:
- clipLimit: 对比度限制,默认是40
- tileGridSize: 分块的大小,默认为
8
?
8
8*8
8?8
参考代码:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread(r'./img/cat.jpeg',0)
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[0].set_title("原图")
axes[1].imshow(cl1,cmap=plt.cm.gray)
axes[1].set_title("自适应均衡化后的结果")
plt.show()
其余API
Canny边缘检测 API:canny = cv2.Canny(image, threshold1, threshold2) , 参数:
- image:灰度图,
- threshold1: minval,较小的阈值将间断的边缘连接起来
- threshold2: maxval,较大的阈值检测图像中明显的边缘
参考代码:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('./img/horse.jpg',0)
lowThreshold = 0
max_lowThreshold = 100
canny = cv.Canny(img, lowThreshold, max_lowThreshold)
fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(10,8),dpi=100)
axes[0].imshow(img,cmap=plt.cm.gray)
axes[0].set_title("原图")
axes[1].imshow(canny,cmap=plt.cm.gray)
axes[1].set_title("自适应均衡化后的结果")
plt.show()
模板匹配 :在给定的图片中查找和模板最相似的区域 API:利用cv.matchTemplate()进行模板匹配,然后使用cv.minMaxLoc()搜索最匹配的位置。
霍夫线检测 API:cv2.HoughLines()
霍夫圆检测 API:cv.HoughCircles()
傅里叶变换 :鸽
角点检测
Harris算法,Shi-Tomasi算法(Harris算法的改进):这两种算法具有旋转不变性,但不具有尺度不变性 Shi-Tomasi API:corners = cv2.goodFeaturesToTrack ( image, maxcorners, qualityLevel, minDistance ) , 参数:
- Image: 输入灰度图像
- maxCorners : 获取角点数的数目。
- qualityLevel:该参数指出最低可接受的角点质量水平,在0-1之间。
- minDistance:角点之间最小的欧式距离,避免得到相邻特征点。
注意:Corners: 搜索到的角点,在这里所有低于质量水平的角点被排除掉,然后把合格的角点按质量排序,然后将质量较好的角点附近(小于最小欧式距离)的角点删掉,最后找到maxCorners个角点返回。
参考代码:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('./img/tv.jpg')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
corners = cv.goodFeaturesToTrack(gray,1000,0.01,10)
for i in corners:
x,y = i.ravel()
cv.circle(img,(x,y),2,(0,0,255),-1)
plt.figure(figsize=(10,8),dpi=100)
plt.imshow(img[:,:,::-1]),plt.title('shi-tomasi')
plt.xticks([]), plt.yticks([])
plt.show()
SIFT算法,SURF算法(对SIFT算法的改进):尺度不变特征转换
SURF算法 API:surf= cv.xfeatures2d.SURF_create() 实例化surf
API:kp,des = surf.detectAndCompute(gray,None) ,检测关键点并计算 参数:
返回:kp: 关键点信息,包括位置,尺度,方向信息;des: 关键点描述符,每个关键点对应128个梯度信息的特征向量
API:cv.drawKeypoints(image, keypoints, outputimage, color, flags) ,将关键点检测结果绘制在图像上 参数:
- image: 原始图像
- keypoints:关键点信息,将其绘制在图像上
- outputimage:输出图片,可以是原始图像
- color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。
- flags:绘图功能的标识设置
cv2.DRAW_MATCHES_FLAGS_DEFAULT:创建输出图像矩阵,使用现存的输出图像绘制匹配对和特征点,对每一个关键点只绘制中间点 cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG:不创建输出图像矩阵,而是在输出图像上绘制匹配对 cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS:对每一个特征点绘制带大小和方向的关键点图形 cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制
参考代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread('./img/tv.jpg')
gray= cv.cvtColor(img,cv.COLOR_BGR2GRAY)
surf = cv.xfeatures2d.SURF_create(400)
kp,des=surf.detectAndCompute(gray,None)
cv.drawKeypoints(img,kp,img,flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
plt.figure(figsize=(8,6),dpi=100)
plt.imshow(img[:,:,::-1]),plt.title('surf')
plt.xticks([]), plt.yticks([])
plt.show()
视频操作
从文件中读取视频并播放
创建读取视频的对象:cap = cv.VideoCapture(filepath) 获取视频的某些属性:retval = cap.get(propId)
propId: 从0到18的数字,每个数字表示视频的属性 常用属性:
修改视频的属性信息:cap.set(propId,value) 判断图像是否读取成功:isornot = cap.isOpened() 获取视频的一帧图像:ret, frame = cap.read()
ret: 若获取成功返回True,获取失败,返回False Frame: 获取到的某一帧的图像
调用cv.imshow()显示图像,在显示图像时使用cv.waitkey()设置适当的持续时间,如果太低视频会播放的非常快,如果太高就会播放的非常慢,通常情况下我们设置25ms就可以了。
最后,调用cap.realease()将视频释放掉
import numpy as np
import cv2 as cv
cap = cv.VideoCapture('./img/2.mp4')
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
cv.imshow('frame',frame)
if cv.waitKey(25) & 0xFF == ord('q'):
break
cap.release()
cv.destoryAllwindows()
保存视频 创建视频写入的对象:out = cv2.VideoWriter(filename,fourcc, fps, frameSize)
filename:视频保存的位置 fourcc:指定视频编解码器的4字节代码 fps:帧率 frameSize:帧大小
设置视频的编解码器,如下所示:retval = cv2.VideoWriter_fourcc( c1, c2, c3, c4 )
c1,c2,c3,c4: 是视频编解码器的4字节代码,在fourcc.org中找到可用代码列表,与平台紧密相关,常用的有: 在Windows中:DIVX(.avi) 在OS中:MJPG(.mp4),DIVX(.avi),X264(.mkv)。
利用cap.read()获取视频中的每一帧图像,并使用out.write()将某一帧图像写入视频中。 使用cap.release()和out.release()释放资源。
import cv2 as cv
import numpy as np
cap = cv.VideoCapture('./img/2.mp4')
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
out = cv.VideoWriter('outpy.avi',cv.VideoWriter_fourcc('M','J','P','G'), 10, (frame_width,frame_height))
while(True):
ret, frame = cap.read()
if ret == True:
out.write(frame)
else:
break
cap.release()
out.release()
cv.destroyAllWindows()
|