文章目录
- 在这里插入图片描述
- 图像基本操作
- 色彩空间与通道
- GRAY色彩空间
- HSV色彩空间
- 绘图和文字
- 图像几何变换
- cv2.resize()
- cv2.flip()
- cv2.warpAffine()
- 平移
- 旋转
- 倾斜
- cv2.warpPerspective()
- 图像阈值处理
- cv2.threshold()
- cv2.adaptiveThreshold()
- Otsu方法
- 图像的运算
- 掩模
- 图像的加法运算
- cv2.add(src1,src2,mask,dtype)
- 图像的位运算
- 合并图像
- cv2.addWeighted(src1,alpha,src2,beta,gamma)
- 模板匹配
- cv2.matchTemplate()
- 单目标匹配
- cv2.minMaxLoc(src,mask)
- 滤波器
- 均值滤波器
- cv2.blur()
- 中值滤波器
- cv2.medianBlur()
- 高斯滤波器
- cv2.GaussianBlu()
- 双边滤波器
- bilateralFilter()
- 腐蚀与膨胀
- 腐蚀
- cv2.erode()
- 膨胀
- cv2.dilate()
- 开运算
- 闭运算
- 形态学运算
- cv2.morphologyEx()
- 梯度运算
- 顶帽运算
- 黑帽运算
- 图形检测
- 图像的轮廓
- cv2.findContours()
- cv2.drawContours()
- 轮廓拟合
- 矩形包围框
- boundingRect()
- 圆形包围框
- minEnclosingCircle()
- 凸包
- convexHull()
- Canny边缘检测
- Canny()
- 霍夫变换
- 直线检测
- HoughLinesP()
- 圆环检测
- HoughCircles()
- 视屏处理
- 读取视屏
- cv2.VideoCapture()
- 播放视屏
- cv2.VideoCapture()
- 获取视屏文件属性
- cv2.VideoCapture.get()
- 保存视屏文件
- cv2.VideoWriter()
- 人脸检测和人脸识别
- 人脸检测
- 级联分类器
- 方法
- 人脸识别
- Eigenfaces 人脸识别器
- cv2.face.EigenFaceRecognizer_create()
- Fisherfaces 人脸识别器
- cv2.face.FisherFaceRecognizer create()
- Local Binary Pattern Histogram 人脸识别器
- cv2.face.LBPHFaceRecognizer create()
图像基本操作
基本操作 | |
---|---|
读取图像: | imread() |
显示图像: | imshow(),waitKey(),destroyAllWindows() |
保存图像: | imwrite() |
获取图像属性: | shape,size,dtype |
cv2.imread(filename,flags)
filename:文件名,flags:默认为1,读取彩色,0是灰度图像
cv2.imshow(winname,mat)
winname:窗口显示名称,mat:要显示的图片
cv2.waitKey(delay)
等待用户按键后,窗口保持时间(ms),负值是永久保持,不传值是立刻关闭
例题
import cv2img = cv2.imread("cat.png", 1)print(img.shape)print(img[78,244]) #获取(78,244)上的BGRprint(img[78,244,0])#获得(78,244)上的blue值print(img[78,244,1])#0:blue,1:green,2:redprint(img[78,244,2])
(762, 1027, 3)[219 215 226]219215226
色彩空间与通道
GRAY色彩空间
cv2.cvtColor(src,code)
scr:原图像,code:色彩转换码
常见色彩转换码: | |
---|---|
cv2.COLOR_BGR2GRAY | |
cv2.COLOR_BGR2HSV | BGR到HSV |
cv2.COLOR_BGR2BGRA | alpha通道 |
HSV色彩空间
H:色调,取值[0,180]
S:饱和度
V:亮度
cv2.split()
b,g,r=cv2.split(img)
拆分通道。img:图名
cv2.merge()
cv2.merge([b,g,r])
合并通道
绘图和文字
绘图和文字 | |
---|---|
cv2.line() | 线 |
cv2.rectangle() | 矩形 |
cv2.circle() | 圆 |
cv2.polylines() | 多折线 |
cv2.putText() | 文字绘制 |
cv2.line(img,pt1,pt2,color,thickness)
img:画布,pt1:起点坐标, pt2:终点,color:颜色例如(0,255,0)是绿色 ,thickness:厚度
cv2.rectangle(img,pt1,pt2,color,thickness)
pt1:左上角, pt2:右下角
cv2.circle(img,center,radius,color,thickness)
center:圆心 ,radius:半径,‘=-1’为实心
cv2.polylines(img,pts,isClosed,color,thickness)
pts:多个坐标点,是列表,坐标需要顺序排放
isClosed:‘=True’闭环
cv2.putText()
图像几何变换
cv2.resize()
cv2.resize(src,dsize,fx,fy,interpolation)
缩放
src:原始图片
dsize:输出图像大小(宽,高)单位像素
fx:可选,水平缩放比例
fy:可选,垂直缩放比例
cv2.flip()
cv2.flip(src,flipCode)
翻转
flopCode:翻转类型,0沿X轴翻转。正数Y轴翻转。负数同时沿X,Y轴翻转
cv2.warpAffine()
cv2.warpAffine(src,M,dsize,flags,borderMode,dorderValue)
仿射变换
M:一个(2,3)矩阵,根据此矩阵的值变换原图像素的位置,M又叫仿射矩阵
flags:可选,插值方式,建议默认
borderMode:可选,建议默认值,边界类型
dorderValue:可选,边界值,默认值0
平移
M=1,0,水平移动距离,0,1,垂直移动距离
旋转
旋转也是根据M矩阵,但是由于复杂,提供cv2.getRotationMatrix2D(center,angle,scale)
center:旋转中心
angle:旋转角度
scale:缩放比例
返回值为M:计算出的放射矩阵
倾斜
倾斜也是根据M矩阵,但是由于复杂,提供cv2.getAffineTransform(src,dst)
src:原图的三个坐标点,格式(3,2)32位浮点数
dst:倾斜图像3个点
返回值为M:计算出的放射矩阵
cv2.warpPerspective()
cv2.warpPerspective(src,M,dsize,flags,borderMode,borderValue)
透视
透视也是根据M矩阵,但是由于复杂,提供cv2.getPerspectiveTransform(src,dst)
src:原图的4个坐标点,格式(4,2)32位浮点数
dst:倾斜图像4个点
返回值为M:计算出的透视矩阵
图像阈值处理
阈值处理函数
cv2.threshold()
cv2.threshold(src,thresh,maxval,type)
src:被处理图像可以是多通道
thresh:阈值125~150取值最好
maxval:阈值处理采用最大值
type:阈值处理类型如表所示:
返回值:(retval,dst)retval:处理时采用的阈值,dst:阈值处理后的图像
表1 阈值处理类型
类型 | 含义 |
---|---|
cv2.THRESH_BINARY | 二值化阈值处理 |
cv2.THRESH_BINARY_INV | 反二值化阈值处理 |
cv2.THRESH_TOZERO | 低于阈值零处理 |
cv2.THRESH_TOZERO_INV | 超出阈值零处理 |
cv2.THRESH_TURNC | 截断阈值处理 |
二值化处理
if 像素<= 阈值 像素=0
if 像素 >阈值 像素=最大值
反二值化处理
if 像素<= 阈值 像素=最大值
if 像素 >阈值 像素=0
零处理
低于阈值零处理
if 像素<= 阈值 像素=0
if 像素 >阈值 像素=原值
超出阈值零处理
if 像素<= 阈值 像素=原值
if 像素 >阈值 像素=0
截断处理
if 像素<= 阈值 像素=原值
if 像素 >阈值 像素=阈值
cv2.adaptiveThreshold()
自适应处理
cv2.adaptiveThreshold(src,maxValue,adaptiveMethod,threshodType,blockSize,C)
src:被处理的图像,需要灰度图
maxValue:阈值处理最大值
adaptiveMethod:自适应阈值的计算方法。如图所示:
计算方法 | 含义 |
---|---|
cv2.ADAPTIVE_THRESH_MEAN_C | 对一个正方形区域内所有像素平均加权 |
cv2.ADAPTIVE_THRESH_GAUSSIAN_C | 根据高斯函数按照像素与中心点的距离对一个正方形区域内的所有像素进行加权计算 |
threshodType:阈值处理类型,只能选cv2.THRESH_BINARY或cv2.THRESH_BINARY_INV
blockSize:一个正方形区域的大小,例:5,指的是5X5区域
C:常量。阈值等于平均值或者加权值减去这个常量。
Otsu方法
前面在讲解5种阈值处理类型的过程中,每个实例设置的阈值都是127,这个127是笔者设置的,并不是通过算法计算得到的。对于有些图像,当阈值被设置为127 时,得到的效果并不好,这时就需要一个个去尝试,直到找到最合适的阈值。
逐个寻找最合适的阈值不仅工作量大,而且效率低。为此,OpenCV提供了 Otsu 方法。Otsu 方法能够遍历所有可能的阈值,从中找到最合适的阈值。Otsu方法的语法与threshold()方法的语法基本一致,只不过在为type传递参数时,要多传递一个参数。
cv2.threshold(src,thresh,maxval,type)
src:被处理图像,灰度图像
thresh:阈值,且要把阈值设置为0
maxval:阈值处理采用最大值,即255
type:阈值处理类型如表1所示选择一种阈值,还要多传递一个参数,即cv2.THRESH_OTSU,例如:cv2.THRESH_BINARY+cv2.THRESH_OTSU。
返回值:(retval,dst)retval:由otsu方法计算得到的最合适的阈值,dst:阈值处理后的图像
图像的运算
掩模
图像的加法运算
cv2.add(src1,src2,mask,dtype)
src1,src2:图像1,2
mask:可选,掩模,建议使用默认值
dtype:可选参数,图像深度,建议默认值
返回:相加后的图像,大于255,则取255
图像的位运算
按位与cv2.bitwise_and(src1,src2,mask)
按位或cv2.bitwise_or(src1,src2,mask)
按位取反cv2.bitwise_not(src,mask)
按位异或cv2.bitwise_xor(src,mask)
合并图像
cv2.addWeighted(src1,alpha,src2,beta,gamma)
src1,2:第1,2副图像
alpha,beta:第1,2副图像权重
gamma:在和结果上添加标量,值越大越亮,相反暗
模板匹配
模板匹配是一种最原始、最基本的识别方法,可以在原始图像中寻找特定图像的位置。模板匹配经常应用于简单的图像查找场景中,例如,在集体合照中找到到某个人的位置。
cv2.matchTemplate()
cv2.matchTemplate(image,templ,method,mask)
image:原始图像
templ:模板图像
method:匹配方法 如表
参数值 | 值 | 含义 |
---|---|---|
cv2.TM_SQDIFF | 0 | 差值平方和匹配,也叫平方差匹配。可以理解为差异程度。匹配程度越高,计算结果越小。完全匹配的结果为0 |
cv2.TM_SQDIFF_NORMED | 1 | 标准差值平方和匹配,也叫标准平方差匹配,规则同上 |
cv2.TM_CCORR | 2 | 相关匹配。可以理解为相似程度,匹配程度越高,计算结果越大 |
cv2.TM_CCORR_NORMED | 3 | 标准相关匹配,规则同上 |
cv2.TM_CCOEFF | 4 | 相关系数匹配,也属于相似程度,计算结果为-1~1的浮点数,1表示完全匹配,0表示毫无关系,-1表示2张图片亮度刚好相反 |
cv2.TM_CCOEFF_NORMED | 5 | 标准相关系数匹配,规则同上 |
mask:可选参数。掩模,只有 cv2.TM_SQDIFF 和 cv2.TM_CCORR_NORMED 支持此参数,建议采用默认值。
返回:计算得出的匹配结果。如果原始图像的宽、高分别为 W、H,模板图像的宽、高分别为w、h,result 就是一个 W-w+1 列、H-h+1 行的 32 位浮点型数组。数组中每一个浮点数都是原始图像中对应像素位置的匹配结果,其含义需要根据 method 参数来解读。
在模板匹配的计算过程中,模板会在原始图像中移动。模板与重叠区域内的像素逐个对比,最后将对比的结果保存在模板左上角像素点索引位置对应的数组位置中。
单目标匹配
cv2.minMaxLoc(src,mask)
src:matchTemplate()方法计算得出的数组
mask:可选,掩模
返回(minValue,maxValue,minLoc,maxLoc)minValue:数组最小值,minValue:数组最大值,minLoc:最小值坐标如(x,y),maxLoc:最大值坐标
滤波器
均值滤波器
均值滤波器,计算像素的平均值,赋值给核心像素。
cv2.blur()
cv2.blur(src,ksize,anchor,borderType)
src:被处理的图像。
ksize:滤波核大小,其格式为(高度,宽度),建议使用如(3,3)、(5,5)、(7,7)等宽、高相等的奇数边长。滤波核越大,处理之后的图像就越模糊。
anchor:可选参数,滤波核的锚点,建议采用默认值,可以自动计算锚点。
MborderType:可选参数,边界样式,建议采用默认值
中值滤波器
中值滤波器的原理与均值滤波器非常相似,唯一的不同就是不计算像素的平均值,而是将所有像素值排序,把最中间的像素值取出,赋值给核心像素。
cv2.medianBlur()
cv2.medianBlur(src,ksize)
参数说明:
src:被处理的图像。
ksize:滤波核的边长,必须是大于1的奇数,如 3、5、7 等。该方法根据此边长个正方形的滤波核。返回值说明:
dst:经过中值滤波处理之后的图像。
注意
中值滤波器的 ksize参数是边长,而其他滤波器的 ksize 参数通常为(高,宽)
高斯滤波器
高斯滤波也被称为高斯模糊或高斯平滑,是目前应用最广泛的平滑处理算法。高斯滤波可以很好地在降低图片噪声、细节层次的同时保留更多的图像信息,经过处理的图像呈现“磨砂玻璃”的滤镜效果。
进行均值滤波处理时,核心周围每个像素的权重都是均等的,也就是每个像素都同样重要,所以计算平均值即可。但在高斯滤波中,越靠近核心的像素权重越大,越远离核心的像素权重越小,像素权重不同不能取平均值,要从权重大的像素中取较多的信息,从权重小的像素中取较少的信息。简单概括就是“离谁更近,跟谁更像”
cv2.GaussianBlu()
cv2.GaussianBlu(src,ksize,sigmaX,sigmaY,borderType)
src:被处理的图像。
ksize:滤波核大小,其格式为(高度,宽度),建议使用如(3,3)、(5,5)、(7,7)等宽、高相等的奇数边长。滤波核越大,处理之后的图像就越模糊。
sigmaX:卷积核水平方向的标准差
sigmaY:卷积核垂直方向的标准差
修改 sigmaX或sigmay 的值都可以改变卷积核中的权重比例。如果不知道如何设计这2个参数值,就直接把这 2个参数的值写成 0,该方法就会根据滤波核的大小自动计算合适的权重比例。
borderType:可选参数,边界样式,建议采用默认值
双边滤波器
不管是均值滤波、中值滤波还是高斯滤波,都会使整幅图像变得平滑,图像中的边界会变得模糊不清。双边滤波是一种在平滑处理过程中可以有效保护边界信息的滤波操作方法。
双边滤波器自动判断滤波核处于“平坦”区域还是“边缘”区域: 如果滤波核处于“平坦”区域则会使用类似高斯滤波的算法进行滤波;如果滤波核处于“边缘”区域,则加大“边缘”像素的权重尽可能地让这些像素值保持不变。
bilateralFilter()
dst = cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, borderType)
src:被处理的图像
d:以当前像素为中心的整个滤波区域的直径。如果 d<0,则自动根据 sigmaSpace 参数计算得到。该值与保留的边缘信息数量成正比,与方法运行效率成反比。
sigmaColor: 参与计算的颜色范围,这个值是像素颜色值与周围颜色值的最大差值,只有颜色值之差小于这个值时,周围的像素才进行滤波计算。值为 255 时,表示所有颜色都参与计算.
sigmaSpace:坐标空间的(sigma)值,该值越大,参与计算的像素数量就越多。
borderType:可选参数,边界样式,建议默认。返回值说明:
腐蚀与膨胀
腐蚀
腐蚀操作可以让图像沿着自己的边界向内收缩。OpenCV 通过“核”来实现收缩计算。“核”的英文名为 kernel,在形态学中可以理解为“由n个像素组成的像素块”,像素块包含一个核心(核心通常在中央位置,也可以定义在其他位置) 。像素块在图像的边缘移动,在移动过程中,核会将图像边缘那些与核重合但又没有越过核心的像素点都抹除。
cv2.erode()
cv2.erode(src, kernel, anchor, iterations, borderType, borderValue)
src: 原始图像。
kernel:腐蚀使用的核。
anchor:可选参数,核的锚点位置。
iterations: 可选参数,腐蚀操作的迭代次数,默认值为 1。
borderType: 可选参数,边界样式,建议默认。
borderValue: 可选参数,边界值,建议默认。返回值说明:
图像经过腐蚀操作之后,可以抹除一些外部的细节,如图卡通小蜘蛛
膨胀
膨胀操作与腐蚀操作相反,膨胀操作可以让图像沿着自己的边界向内扩张。同样是通过核来计算当核在图像的边缘移动时,核会将图像边缘填补新的像素。
cv2.dilate()
cv2.dilate(src, kernel, anchor, iterations, borderType, borderValue)
src: 原始图像。
kernel:膨胀使用的核。
anchor:可选参数,核的锚点位置。
iterations:可选参数,腐蚀操作的迭代次数,默认值为 1。
borderType:可选参数,边界样式,建议默认。
borderValue:可选参数,边界值,建议默认。返回值说明:
图像经过膨胀操作之后,可以放大一些外部的细节,如图 卡通小蜘蛛
开运算
开运算是将图像先进行腐蚀操作,再进行膨胀操作。开运算可以用来抹除图像外部的细节(或者噪声)。
闭运算
闭运算是将图像先进行膨胀操作,再进行腐蚀操作。闭运算可以抹除图像内部的细节(或者噪声)。
形态学运算
腐蚀和膨胀是形态学的基础操作,除了开运算和闭运算以外,形态学中还有几种比较有特点的运算。
cv2.morphologyEx()
cv2.morphologyEx(src, op, kernel, anchor, iterations, borderType, borderValue)参数说明:
src:原始图像
op:操作类型,具体值如表所示。
形态学函数的操作类型参数
参数值 | 含义 |
---|---|
CV2.MORPH_ERODE | 腐蚀操作 |
CV2.MORPH_DILATE | 膨胀操作 |
CV2.MORPH_OPEN | 开运算,先腐蚀后膨胀 |
CV2.MORPH_CLOSE | 闭运算,先膨胀后腐蚀 |
CV2.MORPH_GRADIENT | 梯度运算,膨胀图减腐蚀图 |
CV2.MORPH_TOPHAT | 顶帽运算,原始图减开运算图 |
CV2.MORPH_BLACKHAT | 黑帽运算,闭运算图减原始图 |
kernel:操作过程中使用的核。
anchor:可选参数,核的锚点位置。
iterations:可选参数,迭代次数,默认值为 1。
borderType:可选参数,边界样式,建议默认
borderValue:可选参数,边界值,建议默认。
梯度运算
这里的梯度是指图像梯度,可以简单地理解为像素的变化程度。如果几个连续的像素,其像素值跨度越大,则梯度值越大。
梯度运算的运算过程如图所示,让原图的膨胀图减原图的腐蚀图。因为膨胀图比原图大,腐蚀图比原图小,利用腐蚀图将膨胀图掏空,就得到了原图的轮廓图。
顶帽运算
顶帽运算的运算过程如图所示,让原图减原图的开运算图。因为开运算抹除图像的外部细节,“有外部细节”的图像减去“无外部细节”的图像,得到的结果就只剩外部细节了,所以经过顶帽运算之后,小蜘蛛就只剩蜘蛛腿了。
黑帽运算
黑帽运算的运算过程如图所示,让原图的闭运算图减去原图。因为闭运算抹除图像的内部细节,“无内部细节”的图像减去“有内部细节”的图像,得到的结果就只剩内部细节了,所以经过黑帽运算之后,小蜘蛛就只剩下斑点、花纹和眼睛了。
图形检测
图形检测是计算机视觉的一项重要功能。通过图形检测可以分析图像中可能存在的形状,然后对这些形状进行描绘,如搜索并绘制图像的边缘,定位图像的位置,判断图像中有没有直线、圆形等。虽然图形检测涉及非常深奥的数学算法,但 OpenCV 已经将这些算法封装成简单的方法,开发者只要学会如何调用方法、调整参数即可很好地实现检测功能。
图像的轮廓
轮廓是指图像中图形或物体的外边缘线条。简单的几何图形轮廓是由平滑的线构成的,容易识别,但不规则图形的轮廓可能由许多个点构成,识别起来比较困难。
cv2.findContours()
cv2.findContours(image, mode, methode)
image: 被检测的图像,必须是8 位单通道二值图像。如果原始图像是彩色图像,必须转为灰Q度图像,并经过二值化处理。
mode:轮廓的检索模式,如表所示
轮廓的检索模式参数值
参数值 | 含义 |
---|---|
CV2RETR_EXTERNAL | 只检测外轮廓 |
CV2.RETR_LIST | 检测所有轮廓,但不建立层次关系 |
CV2.RETR_CCOMP | 检测所有轮廓,并建立两级层次关系 |
CV2.RETR_TREE | 检测所有轮廓,并建立树状结构的层次关系 |
methode:检测轮廓时使用的方法,具体值如表所示
检测轮廓时使用的方法
参数值 | 含义 |
---|---|
CV2.CHAIN APPROX NONE | 储存轮廓上的所有点 |
CV2.CHAIN APPROX SIMPLE | 只保存水平、垂直或对角线轮廓的端点 |
CV2.CHAIN APPROX TC89 LI | Ten-Chinl近似算法中的一种 |
CY2.CHAIN APPROX TC89 KCOS | Ten-Chinl近似算法中的一种 |
返回值:(contours,hierarchy):
contours:检测出的所有轮廓,list 类型,每一个元素都是某个轮廓的像素坐标数组日 hierarchy:轮廓之间的层次关系。
通过 fndContours()方法找到图像轮廓后,为了方便开发人员观测,最好能把轮廓画出来,于是OpenCV 提供了 drawContours()方法用来绘制这些轮廓。
cv2.drawContours()
cv2.drawContours(image, contours, contourldx, color, thickness, lineTypee, hierarchy, maxLevel, offse)
image: 被绘制轮廓的原始图像,可以是多通道图像
contours; findContours()方法得出的轮廓列表。
contourldx:绘制轮廓的索引,如果为-1 则绘制所有轮廓。
color:绘制颜色,使用 BGR 格式,(B,G,R)。
thickness:可选参数,画笔的粗细程度,如果该值为-1 则绘制实心轮廓。
ClineTypee:可选参数,绘制轮廓的线型。
hierarchy:可选参数,findContours0方法得出的层次关系。
maxLevel:可选参数,绘制轮廓的层次深度,最深绘制第 maxLevel层。
offse: 可选参数,偏移量,可以改变绘制结果的位置返回值说明:
返回值: 执行后原始图中就包含绘制的轮廓。
轮廓拟合
拟合是指将平面上的一系列点,用一条光滑的曲线连接起来。轮廓的拟合就是将凹凸不平的轮廓用平整的几何图形体现出来。
矩形包围框
矩形包围框是指图像轮廓的最小矩形边界。
boundingRect()
cv2.boundingRect (array)
array:轮廓数组
返回值:元组类型,包含 4 个整数值,分别是最小矩形包围框的: 左上角顶点的横坐标、左上角顶点的纵坐标、矩形的宽和高。所以也可以写成x,y,w,h=cv2.boundingRect(array)
的形式
圆形包围框
圆形包围框与矩形包围框一样,是图像轮廓的最小圆形边界。
minEnclosingCircle()
可以自动计算轮廓最小圆形边界的圆心和半径。
cv2.minEnclosingCircle(points)
points:轮廓数组。
返回值:(center, radius):center: 元组类型,包含 2个浮点值,是最小圆形包围框圆心的横坐标和纵坐标
radius:浮点类型,最小圆形包围框的半径。
凸包
矩形包围框和圆形包围框,虽然已经逼近了图形的边缘,但这种包围柜为了保持几何形状,与图形的真实轮廓贴合度较差。如果能找出图形最外层的端点,将这些端点连按起来,就可以围出一个包围图形的最小包围框,这种包围框叫凸包。
凸包是最逼近轮廓的多边形,凸包的每一处都是凸出来的,也就是任意 3 个点组成的内角均小于180°。例如
convexHull()
可以自动找出轮廓的凸包。
cv2.convexHull(points, clockwise, returnPoints)
points:轮廓数组
clockwise: 可选参数,布尔类型。当该值为 True 时,凸包中的点按顺时针排列,为 False 时按逆时针排列。
returnPoints:可选参数,布尔类型。当该值为 True 时返回点坐标,为 False 时返回点索引默认值为 True。
返回值:凸包的点阵数组。
Canny边缘检测
Canny边缘检测算法是John F.Canny于1986年开发的一个多级边缘检测算法,该算法根据像素的梯度变化寻找图像边缘,最终可以绘制十分精细的二值边缘图像。
Canny()
cv2.Canny(image, threshold1, threshold2, apertureSize, L2gradient)
image: 检测的原始图像。
threshold1: 计算过程中使用的第一个阙值,可以是最小阙值,也可以是最大闽值,通常用来设置最小闯值。
threshold2:计算过程中使用的第二个阙值,通常用来设置最大阀值。
apertureSize:可选参数,Sobel 算子的孔径大小。
L2gradient:可选参数,计算图像梯度的标识,默认值为 False。值为 True 时采用更精准的算法进行计算。
返回值说明:计算后得出的边缘图像,是一个二值灰度图像。
在开发过程中可以通过调整最小闽值和最大阙值控制边缘检测的精细程度。当 2个值都较小时检测出较多的细节;当2个闻值都较大时,忽略较多的细节。
霍夫变换
霍夫变换是一种特征检测,通过算法识别图像的特征,从而判断图像中的特殊形状,例如直线和圆。本节将介绍如何检测图像中的直线和圆。
直线检测
霍夫直线变换是通过霍夫坐标系的直线与笛卡儿坐标系的点之间的映射关系来判断图像中的点是否构成直线。OpenCV将此算法封装成两个方法,分别是cv2.HoughLines()和cv2.HoughLinesP(),前者用于检测无限延长的直线,后者用于检测线段。
本节仅介绍比较常用的 HoughLinesP()方法。HoughLinesP()方法名称最后有一个大写的 P,该方法只能检测二值灰度图像,也就是只有两种像素值的黑白图像。该方法最后把找出的所有线段的两个端点坐标保存成一个数组。
HoughLinesP()
cv2.HoughLinesP(image, rho, theta, threshold, minLineLength, maxLineGap)
image:检测的原始图像。
rho: 检测直线使用的半径步长,值为1时,表示检测所有可能的半径步长
theta: 搜索直线的角度,值为T/180°时,表示检测所有角度。
threshold:闽值,该值越小,检测出的直线就越多。
minLineLength: 线段的最小长度,小于该长度的线段不记录到结果中。
maxLineGap:线段之间的最小距离。
返回值:lines: 一个数组,元素为所有检测出的线段,每条线段是一个数组,代表线段两个端点的横纵坐标,格式为[ x1,y1,x2,y2],[x1,y1,x2,y2]。
圆环检测
霍夫圆环变换的原理与霍夫直线变换类似。OpenCV 提供的 HoughCircles()方法用于检测图像中的圆环,该方法在检测过程中进行两轮筛选:第一轮筛选找出可能是圆的圆心坐标,第二轮筛选计算这些圆心坐标可能对应的半径长度。该方法最后将圆心坐标和半径封装成一个浮点型数组。
HoughCircles()
cv2.HoughCircles(image, method, dp, minDist, param1, param2, minRadius, maxRadius)
image: 检测的原始图像。
method: 检测方法,OpenCV4.0.0 及以前版本仅提供了 cv2.HOUGH_GRADIENT 作为唯一可K用方法。
dp: 累加器分辨率与原始图像分辨率之比的倒数。值为 1 时,累加器与原始图像具有相同的分辨率:值为 2 时,累加器的分辨率为原始图像的 1/2。通常使用 1作为参数。
minDist: 圆心之间的最小距离。
param1:可选参数,Canny 边缘检测使用的最大闯值。
param2: 可选参数,检测圆环结果的投票数。第一轮筛选时投票数超过该值的圆环才会进入第二轮筛选。值越大,检测出的圆环越少,但越精准。
minRadius:可选参数,圆环的最小半径
maxRadius:可选参数,圆环的最大半径返回值说明:
返回值:一个数组,元素为所有检测出的圆环,每个圆环也是一个数组,内容为圆心的横、纵y坐标和半径长度,格式为: [x1,y1,r1],[x2,y2,r2]。
注意:使用该方法前应该为原始图像进行降噪处理,否则会影响检测结果。
视屏处理
VideoCapture 类
读取视屏
cv2.VideoCapture()
cv2.VideoCapture(index)
index:摄像头的设备索引
**注意:**摄像头的数量及其设备索引的先后顺序由操作系统决定,因为 OpenCV 没有提供查询摄像头的数量及其设备索引的任何方法。
方法:isOpened(),摄像头初始化成功,返回值Ture,否则是False
方法:read(),返回值:(retval,image):retval: 是否读取到帧。如果读取到帧,retval 的值为 True; 否则,retval 的值为 False。image: 读取到的帧。因为指的是构成视频的图像,所以可以把“读取到的帧”理解为“读取到的图像”。
OpenCV 官网特别强调,在不需要摄像头时,要关闭摄像头。为此,VideoCapture类提供了 releasel方法。
方法:release():cv2.VideoCapture.release() 可以简写为 capture.release()
播放视屏
VideoCapture类的构造方法 VideoCapture()不仅能够完成摄像头的初始化工作,还能够完成视频文件的初始化工作。当VideoCapture0用于初始化视频文件时,其语法格式如下:
cv2.VideoCapture()
“cv2.VideoCapture(filename)`
flename:打开视频的文件名。例如,公司宣传.avi 等
注意:OpenCV中的 VideoCapture 类虽然支持各种格式的视频文件,但是这个类在不同的操作系统中,支持的视频文件格式不同。尽管如此,VideoCapture 类能够在不同的操作系统中支持后缀名为.avi的视频文件。
说明:调整 waitKey0方法中的参数值可以控制视频文件的播放速度。例如,当代码为 cv2.waitKey(1)时,等待用户按下键盘的时间为 lms,视频文件的播放速度非常快: 当代码为 cv2.waitKey(50)时,等待用户按下键盘的时间为 50ms,能够减缓视频文件的播放速度。
获取视屏文件属性
方法:get()
cv2.VideoCapture.get()
cv2.VideoCapture.get(propld)
propId:视频文件的属性值。
VideoCapture类提供视频文件的属性值及含义如下:
视屏文件属性值 | 含义 |
---|---|
CV2.CAP_PROP_POS_MSEC | 视频文件播放时的当前位置(单位:ms) |
CV2.CAP_PROP_POS_FRAMES | 帧的索引,从0开始 |
CV2.CAP_PROP_POS_AVI_RATIO | 视频文件的相对位置(0表示开始播放,1表示结束播放) |
CV2.CAP_PROP_FRAME_WIDTH | 视频文件的帧宽度 |
CV2.CAP_PROP_FRAME_HEIGHT | 视频文件的帧高度 |
CV2.CAP_PROP_FPS | 帧速率 |
CV2.CAP_PROP_FOURCC | 用4个字符表示的视频编码格式 |
CV2.CAP_PROP_FRAME_COUNT | 视频文件的帧数 |
CV2.CAP_PROP_FORMAT | retrieve()方法返回的 Mat 对象的格式 |
CV2.CAP_PROP_MODE | 指示当前捕获模式的后端专用的值 |
CV2.CAP_PROP_CONVERTRGB | 指示是否应将图像转换为 RGB |
说明
(1)视频是由大量的、连续的图像构成的,把其中的每一幅图像称作一倾。
(2)顿数指的是视频文件中含有的图像总数,帧数越多,视频播放时越流畅.
(3)在播放视频的过程中,把每秒显示图像的数量称作慎速率(FPS,单位:倾/s)。
(4)帧宽度指的是图像在水平方向上含有的像素总数
(5)高度指的是图像在垂直方向上含有的像素总数
保存视屏文件
VideoWriter 类中的常用方法包括 VideoWriter 类的构造方法、write()方法和release0方法。其中,VideoWriter 类的构造方法用于创建 VideoWriter 类对象,其语法格式如下:
cv2.VideoWriter()
cv2.VideoWriter(filename, fourcc, fps, frameSize)
flename:保存视频时的路径(含有文件名)。
fourcc:用4个字符表示的视频编码格式
fps: 帧速率。
frameSize:每一帧的大小。
在OpenCV 中,使用 cv2.VideoWriter_fourcc()来确定视频编码格式。表列出了几个常用的视频编码格式。
常用的视频编码格式
fourcc 的值 | 视频编码格式 | 文件扩展名 |
---|---|---|
cv2.VideoWriter_fourcc(‘I’,‘4’,‘2’,‘0’) | 未压缩的YUV颜色编码格式,兼容性好,但文件较大 | .avi |
cv2.VideoWriter fourcc(‘P’, ‘I’,‘M’,‘T’) | MPEG-1编码格式 | .avi |
cv2.VideoWriter fourcc(‘X’, ‘V’,‘T’,‘D’) | MPEG-4 编码格式,视频文件的大小为平均值 | .avi |
cv2.VideoWriter fourcc(‘T’,‘H’,‘E’,‘O’) | Ogg Vorbis 编码格式,容性差 | .ogv |
cv2.VideoWriterfourcc( ‘F’,‘L’,‘V’, ‘T’) | Flash 视频编码格式 | .flv |
人脸检测和人脸识别
人脸检测
级联分类器
将一系列简单的分类器按照一定顺序级联到一起就构成了级联分类器,使用级联分类器的程序可以通过一系列简单的判断来对样本进行识别。例如,依次满足“有 6 条腿”,“有翅膀”,“有头、胸、腹”这3个条件的样本就可以被初步判断为昆虫,但如果任何一个条件不满足,则不会被认为是昆虫。OpenCV 提供了一些已经训练好的级联分类器,这些级联分类器以XML 文件的方式保存在以下路径中:
.\Python\Lib\site-packages\cv2\data\
不同版本的 OpenCV自带的级联分类器 XML 文件可能会有差别,data 文件夹中缺少的XML 文件可以到 OpenCV 的源码托管平台下载,地址为: https://github.com/opencv/opencv/tree/master/data/haarcascades。
每一个XML 文件都对应一种级联分类器,但有些级联分类器的功能是类似的(正面人脸识别分类器就有3个),表是部分XML 文件对应的功能,
部分级联分类器XML的功能
级联分类器XML文件名 | 检测的内容 |
---|---|
haarcascade_eye.xml | 眼睛检测 |
haarcascade_eye_tree_eyeglasses.xml | 眼镜检测 |
haarcascade_frontalcatface.xml | 正面猫脸检测 |
haarcascade_frontalface_default.xml | 正面人脸检测 |
haarcascade_fullbody.xml | 身形检测 |
haarcascade_lefteye_2splits.xml | 左眼检测 |
haarcascade_lowerbody.xml | 下半身检测 |
haarcascade_profleface.xml | 侧面人脸检测 |
haarcascade_righteye_2splits.xml | 右脸检测 |
haarcascade_russian_plate_number.xml | 车牌检测 |
haarcascade_smile.xml | 笑容检测 |
haarcascade_upperbody.xml | 上半身检测 |
想要实现哪种图像检测,就要在程序启动时加载对应的级联分类器。
方法
OpenCV 实现人脸检测需要做两步操作: 加载级联分类器和使用分类器识别图像。这两步操作都有对应的方法。
首先是加载级联分类器,OpenCV 通过 CascadeClassifier()
方法创建了分类器对象
cv2.CascadeClassifier()
cv2.CascadeClassifier(filename)
flename:级联分类器的XML 文件名
返回值:obiect,分类器对象。
然后使用已经创建好的分类器对图像进行识别,这个过程需要调用分类器对象的 detectMultiScale()
方法,其语法如下:
cascade.detectMultiScale()
cascade.detectMultiScale(image, scaleFactor, minNeighbors, flags, minSize, maxSize)
cascade:已有的分类器对象
参数说明:
Kimage:待分析的图像。
scaleFactor:可选参数,扫描图像时的缩放比例。
minNeighbors: 可选参数,每个候选区域至少保留多少个检测结果才可以判定为人脸。该值越<大,分析的误差越小。
flags:可选参数,旧版本 OpenCV 的参数,建议使用默认值么
minSize:可选参数,最小的目标尺寸。
maxSize:可选参数,最大的目标尺寸。
返回值:objects: 捕捉到的目标区域数组,数组中每一个元素都是一个目标区域,每一个目标区域都包含 4 个值,分别是:左上角点横坐标、左上角点纵坐标、区域宽、区域高。object 的格式为:[244 203 111 111] [432 81 133 133]。
例1:在图像的人脸绘制红框
需要将.xml
文件与.py
文件同目录
import cv2img = cv2.imread("model.jpg")# 读取人脸图像# 加载识别人脸的级联分类器faceCascade = cv2.CascadeClassifier("cascades//haarcascade_frontalface_default.xml")faces = faceCascade.detectMultiScale(img,1.15,4)# 识别出所有人脸for (x, y, w, h) in faces:# 遍历所有人脸的区域cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 5)# 在图像中人脸的位置绘制方框cv2.imshow("img", img)# 显示最终处理的效果cv2.waitKey()# 按下任何键盘按键后cv2.destroyAllWindows()# 释放所有窗体
例2:人身检测
import cv2img = cv2.imread("people.jpg")# 读取图像# 加载识别类人体的级联分类器bodyCascade = cv2.CascadeClassifier("haarcascade_fullbody.xml")bodys = bodyCascade.detectMultiScale(img, 1.15, 4)# 识别出所有人体for (x, y, w, h) in bodys:# 遍历所有人体区域cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 5)# 在图像中人体的位置绘制方框cv2.imshow("img", img)# 显示最终处理的效果cv2.waitKey()# 按下任何键盘按键后cv2.destroyAllWindows()# 释放所有窗体
例3:车牌检测
import cv2img = cv2.imread("car.png") #读取车的图像#加载识别车牌的级联分类器plateCascade = cv2.CascadeClassifier("haarcascade_russian_plate_number.xml")plates = plateCascade.detectMultiScale(img,1.15, 4) # 识别出所有车牌for (x, y, w, h) in plates:# 遍历所有车牌区域cv2.rectangle(img,(x, y),(x + w, y + h),(0, 0, 255), 5) #在图像中车牌的位置绘制方框cv2.imshow("img", img)# 显示最终处理的效果cv2.waitKey() #按下任何键盘按键后cv2.destroyAllWindows()#释放所有窗体
人脸识别
OpenCV 提供了3 种人脸识别方法,分别是 Eigenfaces、Fisherfaces 和 LBPH。这3种方法都是通过对比样本的特征最终实现人脸识别。因为这 3 种算法提取特征的方式不一样,侧重点不同,所以不能分出孰优孰劣,只能说每种方法都有各自的识别风格。
Eigenfaces 人脸识别器
Eigenfaces 也叫作“特征脸”。Eigenfaces 通过 PCA (主成分分析)方法将人脸数据转换到另外一个空间维度做相似性计算。在计算过程中,算法可以忽略一些无关紧要的数据,仅识别一些具有代表性的特征数据,最后根据这些特征识别人脸。
开发者需要通过以下3 种方法完成人脸识别操作。
cv2.face.EigenFaceRecognizer_create()
cv2.face.EigenFaceRecognizer_create(num_components,threshold)
创建 Eigenfaces 人脸识别器
num_components:可选参数,PCA方法中保留的分量个数,建议使用默认值。
threshold:可选参数,人脸识别时使用的闯值,建议使用默认值。
返回值:创建的 Eigenfaces 人脸识别器对象。
创建识别器对象后,需要通过对象的 train()方法训练识别器。建议每个人都给出 2 幅以上的人脸图像作为训练样本。
recognizer.train(src, labels)
recognizer: 已有的 Eigenfaces 人脸识别器对象参数说明:
src: 用来训练的人脸图像样本列表,格式为 list。样本图像必须宽、高一致。
labels: 样本对应的标签,格式为数组,元素类型为整数。数组长度必须与样本列表长度相同.样本与标签按照插入顺序一一对应。
训练识别器后可以通过识别器的 predict()方法识别人脸,该方法对比样本的特征,给出最相近的结果和评分,其语法如下:
label, confidence = recognizer.predict(src)
对象说明:
recognizer:已有的 Eigenfaces 人脸识别器对象。
src: 需要识别的人脸图像,该图像宽、高必须与样本一致。
返回值说明:
label:与样本匹配程度最高的标签值。
confidence: 匹配程度最高的信用度评分。评分小于 5000 匹配程度较高,0分表示 2 幅图像完全一样。
例1Eigenfaces 人脸识别
import cv2import numpy as npphotos = list()# 样本图像列表lables = list()# 标签列表photos.append(cv2.imread("face\\Summer1.png", 0))# 记录Summer1人脸图像lables.append(0)# Summer1图像对应的标签photos.append(cv2.imread("face\\Summer2.png", 0))# 记录Summer2 人脸图像lables.append(0)# Summer2图像对应的标签photos.append(cv2.imread("face\\Summer3.png", 0))# 记录Summer3 人脸图像lables.append(0)# Summer3图像对应的标签photos.append(cv2.imread("face\\Elvis1.png", 0))# 记录Elvis1人脸图像lables.append(1)# Elvis1图像对应的标签photos.append(cv2.imread("face\\Elvis2.png", 0))# 记录EIvis2人脸图像lables.append(1)# Elvis2图像对应的标签photos.append(cv2.imread("face\\Elvis3.png", 0))# 记录 Elvis3 人脸图像lables.append(1)# Elvis3图像对应的标签names = {'0': 'Summer', "1": 'Elvis'}# 标签对应的名称字典recognizer = cv2.face.EigenFaceRecognizer_create()# 创建特征脸识别器recognizer.train(photos, np.array(lables))# 识别器开始训练i = cv2.imread("face\\summer4.png", 0)# 待识别的人脸图像label, confidence = recognizer.predict(i)# 识别器开始分析人脸图像print("confidence =" + str(confidence))# 打印评分print(names[str(label)])# 数组字典里标签对应的名字
Fisherfaces 人脸识别器
Fisherfaces 是由 Ronald Fisher 最早提出的,这也是Fisherfaces 名字的由来。Fisherfaces 通过 LDA(线性判别分析技术)方法将人脸数据转换到另外一个空间维度做投影计算,最后根据不同人脸数据的投影距离判断其相似度。
开发者需要通过以下3 种方法完成人脸识别操作。
通过 cv2.face.FisherFaceRecognizer create()方法创建 Fisherfaces 人脸识别器,其语法如下;
cv2.face.FisherFaceRecognizer create()
recognizer = cv2.face.FisherFaceRecognizer create(num components, threshold)
num_components:可选参数,通过 Fisherface 方法进行判断分析时保留的分量个数,建议使用9默认值。
threshold:可选参数,人脸识别时使用的阅值,建议使用默认值。
返回值说明:口recognizer:创建的 Fisherfaces 人脸识别器对象。
创建识别器对象后,需通过对象的 train()方法训练识别器。建议每个人都给出 2 幅以上的人脸图像作为训练样本。train()方法的语法如下:
recognizer.train(src,labels)
recognizer:已有的 Fisherfaces 人脸识别器对象参数说明:
src:用来训练的人脸图像样本列表,格式为 list。样本图像必须宽、高一致
labels: 样本对应的标签,格式为数组,元素类型为整数。数组长度必须与样本列表长度相同.V样本与标签按照插入顺序一一对应。
(3)训练识别器后可以通过识别器的 predict()方法识别人脸,该方法对比样本的特征,给出最相近的结果。
label,confidence = recognizer.predict(src)
recognizer: 已有的 Fisherfaces 人脸识别器对象。
src: 需要识别的人脸图像,该图像宽、高必须与样本一致。
返回值label: 与样本匹配程度最高的标签值。confidence:匹配程度最高的信用度评分。评分小于 5000 程度较高,0分表示2 幅图像完
全一样。
例1Fisherfaces 人脸识别
import cv2import numpy as npphotos = list()# 样本图像列表lables = list()# 标签列表photos.append(cv2.imread("face\\Summer1.png", 0))# 记录Summer1人脸图像lables.append(0)# Summer1图像对应的标签photos.append(cv2.imread("face\\Summer2.png", 0))# 记录Summer2 人脸图像lables.append(0)# Summer2图像对应的标签photos.append(cv2.imread("face\\Summer3.png", 0))# 记录Summer3 人脸图像lables.append(0)# Summer3图像对应的标签photos.append(cv2.imread("face\\Elvis1.png", 0))# 记录Elvis1人脸图像lables.append(1)# Elvis1图像对应的标签photos.append(cv2.imread("face\\Elvis2.png", 0))# 记录EIvis2人脸图像lables.append(1)# Elvis2图像对应的标签photos.append(cv2.imread("face\\Elvis3.png", 0))# 记录 Elvis3 人脸图像lables.append(1)# Elvis3图像对应的标签names = {'0': 'Summer', "1": 'Elvis'}# 标签对应的名称字典recognizer = cv2.face.FisherFaceRecognizer_create()# 创建特征脸识别器recognizer.train(photos, np.array(lables))# 识别器开始训练i = cv2.imread("face\\summer4.png", 0)# 待识别的人脸图像label, confidence = recognizer.predict(i)# 识别器开始分析人脸图像print("confidence =" + str(confidence))# 打印评分print(names[str(label)])# 数组字典里标签对应的名字
Local Binary Pattern Histogram 人脸识别器
Local Binary Patem Histogram 简称 LBPH,即局部二进制模式直方图,这是一种基于局部二进制模式算法,这种算法善于捕获局部纹理特征。开发者需要通过以下3种方法来完成人脸识别操作。(1)通过 cv2.face.LBPHFaceRecognizer create()
方法创建 LBPH 人脸识别器,其语法如下:
cv2.face.LBPHFaceRecognizer create()
recognizer = cv2.face.LBPHFaceRecognizer create(radius, neighbors, grid x, grid y, threshold)
radius:可选参数,圆形局部二进制模式的半径,建议使用默认值。
neighbors:可选参数,圆形局部二进制模式的采样点数目,建议使用默认值。
返回值说明:
grid x:可选参数,水平方向上的单元格数,建议使用默认值口 grid_y:可选参数,垂直方向上的单元格数,建议使用默认值。
threshold:可选参数,人脸识别时使用的阙值,建议使用默认值。
创建识别器对象后,需要通过对象的 rain()
方法训练识别器。建议每个人都给出2 幅以上的人脸图像作为训练样本。
recognizer.train(src, labels)
recognizer:已有的LBPH 人脸识别器对象。
参数说明: src:用来训练的人脸图像本列表,格式为 list。样本图像必须宽、高一致 labels:样本对应的标签,格式为数组,元素类型为整数。数组长度必须与样本列表长度相同样本与标签按照插入顺序一一对应。(3)训练识别器后就可以通过识别器的 predict()方法识别人脸,该方法对比样本的特征,给出最
相近的结果和评分,其语法如下:
label, confidence = recognizer .predict(src)
对象说明:回 recognizer:已有的 LBPH人脸识别器对象。参数说明:口 src:需要识别的人脸图像,该图像宽、高必须与样本一致。
返回值说明:区 label: 与样本匹配程度最高的标签值。