基于明日科技的《Python OpenCV从入门到实践》的学习笔记
import cv2
image = cv2.imread(filename, flags)
filename
为待读取图片的路径(相对路径或绝对路径均可,不允许有中文)flags
为读取图像颜色类型的标记。默认为1,表示读取彩色图像;如为0,表示读取灰度图像cv2.imshow(winname, mat)
winname
:显示图像的窗口名称,不能是中文,否则有乱码mat
:要显示的图像retval = cv2.waitKey(delay)
retval
:被按下的按键的ASCII码;如果没有按键被按下,waitKey()方法返回-1delay
:等待用户按下按键的时间,单位为ms;当为负数、0或者空时,表示无限等待cv2.destoryAllWindows()
import cv2
image = cv2.imread("1.1.jpg")
cv2.imshow("flower", image)
cv2.waitKey() # 按下任意键后放行
cv2.destoryAllWindows()
cv2.imwrite(filename, img)
shape
:
(图像像素行数,图像像素列数,通道数)
数组,即(H,W,C)
(图像像素行数,图像像素列数)
数组,即(H,W)
size
:dtype
:计算机把像素值处理为256个灰度级别,用[0, 255]中的数值表示,0表示纯黑色,255表示纯白色
px = image[像素点所在的行号, 像素点所在的列号]
px
为(B,G,R)
像素值blue = image[291, 218, 0]
green = image[291, 218, 1]
red = image[291, 218, 2]
image[291, 218] = [255, 255, 255]
[255, 255, 255]
为纯白[0, 0, 0]
为纯黑cv2.imshow()
显示的结果差异不大,需使用cv2.imwrite()
保存为.png
后,才能显示最终结果,因为PNG图像是一种典型的四通道格式。dst = cv2.cvtColor(src, code)
dst
:转换后的图像src
:转换前的图像code
:色彩空间的转换码:
cv2.COLOR_BGR2RGB
, cv2.COLOR_RGB2BGR
cv2.COLOR_BGR2GRAY
, cv2.COLOR_RGB2GRAY
cv2.COLOR_BGR2HSV
, cv2.COLOR_RGB2HSV
cv2.COLOR_BGR2BGRA
b, g, r = cv2.split(bgr_image)
h, s, v = cv2.split(hsv_image)
cv2.imshow('h', h)
输出H通道的拆分结果的话,输出的结果为[H, H, H]bgr = cv2.merge([b, g, r])
rgb = cv2.merge([r, g, b])
hsv = cv2.merge([h, s, v])
import numpy as np
常见的numpy数据类型:
np.bool_
, np.int_
, np.float_
, np.complex_
, np.int8
, np.int16
, np.uint8
等
np.array(object, dtype, copy, order, subok, ndmin)
object
:任何具有数组接口方法的对象copy
:可选参数,布尔值,默认为True,表示object对象被复制;否则,只有当__array__返回副本,object参数为嵌套序列,或者需要副本满足数据类型和顺序要求时,才会生成副本order
:元素在内存中的出现顺序,值为K、A、C、F。如果object参数不是数组,则新创建的数组将按行排列(C),如果值为F,则按列排列;如果object参数是一个数组,则以下成立:C(按行)、F(按列)、A(原顺序)、K(元素在内存中的出现顺序)subok
:布尔值,如果为True,则传递子类;否则,返回的数组将强制为基类数组(默认为False)ndmin
:指定生成数组的最小维数import numpy as np
list = [1, 2, 3]
n1 = np.array(list, dtype=np.float_)
n1 = np.array(list, dtype=float) # 同上一行
# 创建三维数组
nd2 = np.array(list, ndmin=3) # 创建了[[[1, 2, 3]]]
np.empty(size, dtype)
np.empty([2, 3])
np.zeros(size, dtype)
np.ones(size, dtype)
np.random.randint(low, high, size)
low
:随机数最小取值范围high
:可选参数,随机数最大取值范围;如果high为空,则取值范围为(0, low); 否则,为(low, high)size
:可选参数,数组维度import numpy as np
n1 = np.array([1, 2])
n2 = np.array([3, 4])
print(n1 + n2) # 加法
print(n1 - n2) # 减法
print(n1 * n2) # 乘法
print(n1 / n2) # 除法
print(n1 ** n2) # 幂运算
print(n1 >= n2) # 比较运算,输出同尺寸的bool数组,==, >, <, <=
# 复制
n2 = np.array(n1, copy=True) # 复制得到副本
n2 = n1.copy() # 复制得到副本
arr[idx]
arr[start: stop: step]
start
:索引起始位置;若省略,表示从0开始stop
:索引终止位置,不包括该位置,即arr[0:2],表示[arr[0], arr[1]];若省略,表示到末尾step
:步长arr[::-1]
,表示arr的逆序arr[:-3:-1]
,表示[arr[-1], arr[-2]]二维数组arr
arr[0, 0]
,表示第0行第0列处的元素arr[:2, 1:]
img = np.zeros((100, 200), dtype=np.uint8)
创建全黑图片img = np.ones((100, 200), dtype=np.uint8) * 255
创建全白图片arr = np.hstack((arr1, arr2))
水平拼接arr = np.vstack((arr1, arr2))
垂直拼接img = cv2.line(img, pt1, pt2, color, thickness)
img
:画布pt1
:线段的起点坐标,(x, y)表示(横坐标,纵坐标),而表达像素位置时是(y, x)pt2
:线段的终点坐标color
:线段的颜色,为BGR元组,例如红色:color=(0, 0, 255)
thickness
:线段的宽度img = cv2.rectangle(img, pt1, pt2, color, thickness)
img
:画布pt1
:矩形的起点坐标pt2
:矩形的终点坐标color
:矩形的线条颜色,为BGR元组,例如红色:color=(0, 0, 255)
thickness
:矩形的线条宽度,如果为-1,则表示实心矩形img = cv2.circle(img, center, radius, color, thickness)
img
:画布center
:圆心坐标radius
:半径,当半径为0时,绘制一个点color
:线条颜色,为BGR元组,例如红色:color=(0, 0, 255)
thickness
:线条宽度,如果为-1,则表示实心矩形color = np.random.randint(255, size=(3,)).tolist()
img = cv2.polylines(img, [pts], isClosed, color, thickness)
img
:画布pts
:列表,指各顶点的坐标值,必须是Numpy类型isClosed
:布尔值,表示多边形是否封闭color
:线条颜色,为BGR元组,例如红色:color=(0, 0, 255)
thickness
:线条宽度,如果为-1,则表示实心矩形import cv2
import numpy as np
canvas = np.zeros((300, 300, 3), np.uint8)
pts = np.array([[100, 50], [200, 50], [250, 250], [50, 250]], np.int32)
canvas = cv2.polylines(canvas, [pts], True, (0, 0, 255), 5)
cv2.imshow("polylines", canvas)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.putText(img, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin)
img
:画布text
:文字内容,不能有中文org
:文字在画布中的左下角坐标fontFace
:文字样式,即cv2.FONT_******, 其中,cv2.FONT_ITALIC表示斜体,可以与其他样式一起使用,用“+”联合fontScale
:字体大小color
:线条颜色thickness
:线条宽度lineType
:线型(指线的产生算法,4或8,默认为8)bottomLeftOrigin
:布尔值,绘制文字时的方向;默认为Falseretval, dst = cv2.threshold(src, thresh, maxval, type)
src
:被处理的图像thresh
:阈值,在125~150范围内取值的效果最好maxval
:阈值处理采用的最大值type
:阈值处理类型:
cv2.THRESH_BINARY
:二值化阈值处理:将大于阈值的像素值变为最大值(一般为设为255),小于或等于阈值的像素值变为0cv2.THRESH_BINARY_INV
:反二值化阈值处理:将大于阈值的像素值变为0,小于或等于阈值的像素值变为最大值cv2.THRESH_TOZERO
:低于阈值零处理:将低于或等于阈值的像素值变为0,其他像素值不变;彩色图像会让深色区域颜色更深,甚至变黑cv2.THRESH_TOZERO_INV
:超出阈值零处理:将大于阈值的像素值变为0,其他像素值不变;彩色图像会让浅色区域彻底变黑cv2.THRESH_TRUNC
:截断阈值处理:将大于阈值的像素值变为和阈值一样的值,其他像素值不变;彩色图像会降低亮度,且浅色区域颜色更浅retval
:处理时所采用的阈值dst
:经过阈值处理后的图像自适应阈值处理能够保留图像中更多的细节信息,更明显的保留图像主体的轮廓
dst = cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
src
:被处理的图像,必须是灰度图maxValue
:阈值处理采用的最大值adaptiveMethod
:自适应阈值的计算方法:
cv2.ADAPTIVE_THRESH_MEAN_C
:对一个正方形区域内的所有像素平均加权cv2.ADAPTIVE_THRESH_GAUSSIAN_C
:根据高斯函数按照像素与中心点的距离对一个正方形区域内的所有像素进行加权计算thresholdType
:阈值处理类型,只能是下面的两者之一:
cv2.THRESH_BINARY
cv2.THRESH_BINARY_INV
block_size
:一个正方形区域的大小C
:常量,阈值等于均值或者加权值减去这个常量dst
:经过阈值处理后的图像人为指定阈值往往不能找到最合适的阈值,可以使用Otsu方法,其会遍历所有可能的阈值,从中找到最合适的阈值。使用时,仍基于(1)中的阈值处理函数,需在参数type
上多加一个cv2.THRESH_OTSU
;例如:
retval, dst = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
dst = cv2.resize(src, dsize, fx, fy, interpolation)
src
:原始图像dsize
:输出图像的大小,格式为(宽,高),单位为像素fx
:可选参数,水平方向的缩放比例fy
:可选参数,竖直方向的缩放比例interpolation
:可选参数,缩放的插值方式,建议使用默认值dst
:缩放后的图像import cv2
img = cv2.imread('demo.png')
dst1 = cv2.resize(img, (100, 100))
dst2 = cv2.resize(img, (400, 400))
cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()
使用fx, fy控制缩放时,参数dsize必须设置为None,否则fx,fy会失效
fx,fy:小于1表示缩小,大于1表示放大。计算公式为:
新图像宽度 = round(fx * 原图像宽度)
新图像高度 = round(fy * 原图像高度)
import cv2
img = cv2.imread('demo.png')
dst1 = cv2.resize(img, dsize=None, fx=1/3, fy=1/3)
dst2 = cv2.resize(img, dsize=None, fx=2, fy=2)
cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()
dst = cv2.flip(src, flipCode)
src
:原始图像flipCode
:翻转类型:
dst
:翻转之后的图像仿射变换是仅在二维平面中发生的几何变换;变换后,原来的直线仍然是直线,原来的平行线仍然保持平行。
dst = cv2.warpAffine(src, M, dsize, flags, borderMode, borderValue)
src
:原始图像M
:仿射矩阵,一个2行3列矩阵(np矩阵,值为float32类型),根据此矩阵的值变换原图中的像素未知
dsize
:输出图像的尺寸flags
:可选参数,插值方式,建议使用默认值borderMode
:可选参数,边界类型,建议使用默认值borderValue
:可选参数,边界值,默认为0,建议使用默认值dst
:变换后的图像同时沿着水平、或垂直方向移动
M = [[1, 0, 水平移动的距离], [0, 1, 垂直移动的距离]]
,结果为:
新x = 原x * 1 + 原y * 0 + 水平移动的距离 = 原x + 水平移动的距离
新y = 原x * 0 + 原y * 1 + 垂直移动的距离 = 原y + 垂直移动的距离
若水平移动的距离为正,则图像向右移动;垂直移动的距离为正,则图像向下移动
import cv2
import numpy as np
img = cv2.imread('demo.png')
dsize = img.shape[:-1]
M = np.float32([[1, 0, 50],
[0, 1, 100]])
dst = cv2.warpAffine(img, M, dsize)
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
M = cv2.getRotationMatrix2D(center, angle, scale)
center
:旋转的中心点坐标angle
:旋转的角度(不是弧度);正数表示逆时针旋转scale
:缩放比例import cv2
img = cv2.imread('demo.png')
center = (img.shape[0]/2 , img.shape[1] / 2)
M = cv2.getRotationMatrix2D(center, 30, 0.8)
dst = cv2.warpAffine(img, M, img.shape[:-1])
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
倾斜,是给定原图上一个矩形的三个顶点:左上点A、右上点B、左下点C,再给定倾斜后A、B、C三点的新坐标,实现倾斜效果。
倾斜后,原A、B、C所在的矩形,变为平行四边形,而且原直线依然是直线,原平行线依然保持平行。
M = cv2.getAffineTransform(src, dst)
src
:原图A、B、C三个点坐标,浮点数列表,形如:[[0, 1], [1, 0], [1, 1]]dst
:倾斜后A、B、C三点的新坐标透视是让图像在三维空间中变形。从不同角度观察物体,离观察点越近的边宽度与原宽度越接近,离观察点越远的边,就会越缩小。
给定原图上一个矩形的四个顶点:左上点A、右上点B、左下点C、右下点D,再给定透视后的A、B、C、D的新坐标,实现透视效果。
dst = cv2.warpPerspective(src, M, dsize, flags, borderMode, borderValue)
src
:原始图像M
:透视矩阵,三行三列,用M = cv2.getPerspectiveTransform(src_points, dst_points)
计算
src_points
:原图像上一个矩形的四个顶点坐标,必须是numpy类型dst_points
:四个顶点的新坐标dsize
:输出图像的尺寸flags
:可选参数,插值方式,建议使用默认值borderMode
:可选参数,边界类型,建议使用默认值borderValue
:可选参数,边界值,默认为0,建议使用默认值dst
:变换后的图像import cv2
import numpy as np
img = cv2.imread('demo.png')
rows = len(img)
cols = len(img[0])
p1 = np.zeros((4, 2), np.float32)
p1[0] = [0, 0]
p1[1] = [cols - 1, 0]
p1[2] = [0, rows - 1]
p1[3] = [cols - 1, rows - 1]
p2 = np.zeros((4, 2), np.float32)
p2[0] = [90, 0]
p2[1] = [cols - 90, 0]
p2[2] = [0, rows - 1]
p2[3] = [cols - 1, rows - 1]
M = cv2.getPerspectiveTransform(p1, p2)
print(M) # 3行3列
dst = cv2.warpPerspective(img, M, (cols, rows))
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
掩模,也叫掩码(mask),在程序用二值图像来表示:0值(纯黑)区域表示被遮盖的部分,255值(纯白)区域表示暴露的部分。
通常使用Numpy库提供的方法来创建掩模图像。
mask = np.zeros((150, 150, 3), np.uint8)
mask[50:100, 20:80, :] = 255
dst = cv2.add(src1, src2, mask, dtype)
src1
:第一幅图像src2
:第二幅图像mask
:可选参数,掩模,建议使用默认值dtype
:可选参数,图像深度,建议使用默认值dst
:相加之后的结果图像,如相加后值大于255,则取255+
将两幅图相加,即src1 + src2
,相加后值大于255的,会进行取模运算(除以255的余数),像素值会变得更小;图像会由浅色变成深色。而add()
方法的计算结果超过255,就取值255,图像中很多浅色像素会变成纯白色。 import cv2
img = cv2.imread('beach.jpg')
sum1 = img + img
sum2 = cv2.add(img, img)
利用掩模遮盖相加结果:(将img1
和img2
相加后,再通过掩模遮盖结果,将掩模为1的区域通过,为0的区域遮挡)
import cv2
import numpy as np
img1 = np.zeros((150, 150, 3), np.uint8)
img1[:, :, 0] = 255
img2 = np.zeros((150, 150, 3), np.uint8)
img2[:, :, 2] = 255
img = cv2.add(img1, img2)
cv2.imshow('no mask', img)
m = np.zeros((150, 150, 1), np.uint8) # 掩模使用1通道
m[50:100, 50:100, :] = 255
cv2.imshow('m', m)
img = cv2.add(img1, img2, mask=m)
cv2.imshow('use mask', img)
cv2.waitKey()
cv2.destroyAllWindows()
dst = cv2.bitwise_and(src1, src2, mask)
src1
:第一幅图像src2
:第二幅图像mask
:可选参数,掩模dst
:与运算之后的结果图像dst = cv2.bitwise_or(src1, src2, mask)
src1
:第一幅图像src2
:第二幅图像mask
:可选参数,掩模dst
:或运算之后的结果图像dst = cv2.bitwise_not(src, mask)
src
:参与运算的图像mask
:可选参数,掩模dst
:取反运算之后的结果图像dst = cv2.bitwise_or(src1, src2, mask)
src1
:第一幅图像src2
:第二幅图像mask
:可选参数,掩模dst
:异或运算之后的结果图像import cv2
import numpy as np
def encode(img, img_key):
result = cv2.bitwise_xor(img, img_key)
return result
flower = cv2.imread('amygdalus triloba.png')
img_key = np.random.randint(0, 256, flower.shape, np.uint8)
cv2.imshow('flower', flower)
cv2.imshow('img_key', img_key)
result = encode(flower, img_key)
cv2.imshow('encode', result)
result2 = encode(result, img_key)
cv2.imshow('decode', result2)
cv2.waitKey()
cv2.destroyAllWindows()
目的:将两幅图像融合到一起,类似摄影上的多次曝光。
加权和,按照不同的权重取两幅图像的像素之和,最后组合成新图像。加权和不会像纯加法运算那样丢失信息,而是尽可能保留原图像信息的基础上把两幅图像融合到一起。
dst = cv2.addWeighted(src1, alpha, src2, beta, gamma)
src1
:第一幅图像alpha
:第一幅图像的权重src2
:第二幅图像beta
:第二幅图像的权重gamma
:在结果上添加的标量,相当于偏置量;该值越大,结果图像越亮,相反则越暗,可以是负数dst
:叠加之后的结果目的:每幅图像提供一部分内容,将这些内容拼接成一幅图像
覆盖,是直接把前景图像显示在背景图像中,前景图像会遮挡注背景图像。
操作:从A图像中取像素值,直接赋值给B图像的像素
import cv2
beach = cv2.imread('beach.jpg')
cat = cv2.imread('cat.jpg')
cat = cat[75:400, 120:260, :]
cat = cv2.resize(cat, (70, 160))
cv2.imshow('cat', cat)
cv2.imshow('beach', beach)
beach[100:100 + cat.shape[0], 260:260 + cat.shape[1], :] = cat
cv2.imshow('beach2', beach)
cv2.waitKey()
cv2.destroyAllWindows()
注意:
如前景图像是4通道(含alpha通道)图像,则不能按上述操作直接替换。因为前景中有透明像素,理应不能挡住背景,因此赋值时应排除所有透明的前景图像像素
滤波器用于进行图像平滑处理,或者叫图像模糊处理(去除图像内噪声、降低细节层次信息等,并且尽量保留原图像信息)
也称为低通滤波器,将核心像素值修改为滤波核内所有像素的平均值
dst = cv2.blur(src, ksize, anchor, borderType)
src
:被处理的图像ksize
:滤波核大小,格式为(高度,宽度),建议使用等高宽的奇数边长,如(3, 3), (5, 5);滤波核越大,处理后的图像越模糊anchor
:可选参数,滤波核的锚点,建议使用默认值borderType
:可选参数,边界样式,建议使用默认值dst
:经过滤波后的图像将核心像素值修改为滤波核内所有像素值的中值(滤波核内所有像素值升序排列,取中间的值)
dst = cv2.medianBlur(src, ksize)
src
:被处理的图像ksize
:滤波核边长,必须是大于1的奇数,如3,5,7;滤波核边长越长,处理后的图像就越模糊dst
:经过滤波后的图像 dst1 = cv2.medianBlur(img, 3)
中值滤波处理的图像比均值滤波丢失更多细节
也称为高斯模糊、高斯平滑,是目前应用最广泛的平滑处理算法;可有效降低图片噪声、细节层次,并保留更多的图像信息,处理后的图片呈”磨砂玻璃“的滤镜效果。
高斯滤波中,给定滤波核的尺寸,会自动生成滤波核,指代对应未知像素的权重,越靠近滤波核心的像素权重越大,滤波过程是在做卷积操作。
dst = cv2.GaussianBlur(src, ksize, sigmaX, dst, sigmaY, borderType)
src
:被处理的图像ksize
:滤波核大小,格式为(高度,宽度),宽高必须是奇数边长,如(3, 3), (5, 5);滤波核越大,图像越模糊sigmaX
:卷积核水平方向上的标准差sigmaY
:卷积核垂直方向上的标准差;修改sigmaX
和sigmaY
均可改变卷积核中的权重比例。如不知道如何设置,可直接设置为0,会自动根据滤波核大小计算出合适的权重比例borderType
:可选参数,边界样式,建议使用默认值dst
:经过滤波后的图像一种可有效保护边界信息的滤波操作:
dst = cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, borderType)
src
:被处理的图像d
:以当前像素为中心的整个滤波区域的直径;如果d<0,则自动根据sigmaSpace
参数计算得到;该值与保留的边缘信息数量成正比,与方法运行效率成反比sigmaColor
:参与计算的颜色范围;是像素颜色值与周围颜色值的最大差值,只有颜色值之差小于这个值时,周围的像素才会进行滤波计算;值为255时,表示所有颜色都参与计算sigmaSpace
:空间坐标的 σ ( s i g m a ) \sigma(sigma) σ(sigma)值,越大,参与计算的像素数量越多borderType
:可选参数,边界样式,建议使用默认值dst
:经过滤波后的图像import cv2
img = cv2.imread('amygdalus triloba.png')
dst2 = cv2.bilateralFilter(img, 15, 120, 100)
cv2.imshow('img', img)
cv2.imshow('bilateral', dst2)
cv2.waitKey()
cv2.destroyAllWindows()
可让图像沿着自己的边界向内收缩;给定核,核会在图像的边缘移动,移动时核会将图像边缘那些与核重合但又没有越过核心的像素点都抹除,类似于削土豆的过程;图像经过腐蚀后,可抹除一些外部信息
dst = cv2.erode(src, kernel, anchor, iterations, borderType, borderValue)
src
:被处理的图像kernel
:腐蚀使用的核;一般核大小为3*3
、5*5
、9*9
、11*11
,行列数越大,计算出的效果越粗糙anchor
:可选参数,核的锚点位置iterations
:可选参数,腐蚀操作的迭代次数,默认值为1borderType
:可选参数,边界样式,建议使用默认值borderValue
:可选参数,边界值,建议使用默认值dst
:经过腐蚀后的图像import cv2
import numpy as np
img = cv2.imread('cactus.jpg')
k = np.ones((3, 3), np.uint8)
cv2.imshow('img', img)
dst = cv2.erode(img, k)
cv2.imshow('erode', dst)
cv2.waitKey()
cv2.destroyAllWindows()
可让图像沿着自己的边界向外扩张;给定核,核会在图像的边缘移动,移动时核会向图像边缘填充新的像素;图像经过膨胀后,可放大一些外部信息;膨胀后,会将图像加工成“近视眼”效果,图像会变得模糊
dst = cv2.dilate(src, kernel, anchor, iterations, borderType, borderValue)
src
:被处理的图像kernel
:膨胀使用的核anchor
:可选参数,核的锚点位置iterations
:可选参数,膨胀操作的迭代次数,默认值为1borderType
:可选参数,边界样式,建议使用默认值borderValue
:可选参数,边界值,建议使用默认值dst
:经过膨胀后的图像import cv2
import numpy as np
img = cv2.imread('sunset.jpg')
cv2.imshow('img', img)
k = np.ones((3, 3), np.uint8)
dst = cv2.dilate(img, k)
cv2.imshow('dilate', dst)
cv2.waitKey()
cv2.destroyAllWindows()
开运算,即先腐蚀后膨胀;可用来抹除图像外部的细节(或者噪声)
import cv2
import numpy as np
img = cv2.imread('nigella.png')
cv2.imshow('img', img)
k = np.ones((5, 5), np.uint8)
dst = cv2.erode(img, k)
cv2.imshow('erode', dst)
dst = cv2.dilate(dst, k)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()
闭运算,即先膨胀后腐蚀;可用来抹除图像内部的细节(或噪声)
dst = 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
:可选参数,膨胀操作的迭代次数,默认值为1borderType
:可选参数,边界样式,建议使用默认值borderValue
:可选参数,边界值,建议使用默认值dst
:操作后的图像通过计算图像梯度来判断出图像的边缘,然后将边缘的点封装成数组返回
contours, hierarchy = cv2.findContours(image, mode, method, contours, hierachy)
image
:被检测的图像,必须是8位单通道二值图像,即如果是彩色图像,必须转为灰度图,在进行二值化阈值处理mode
:轮廓检索的模式:
cv2.RETR_EXTERNAL
:只检测外轮廓cv2.RETR_LIST
:检测所有轮廓,但不建立层次关系cv2.RETR_CCOMP
:检测所有轮廓,并建立两级层次关系cv2.RETR_TREE
:检测所有轮廓,并建立树状结构的层次关系method
:检测轮廓时使用的方法:
cv2.CHAIN_APPROX_NONE
:存储轮廓上的所有点cv2.CHAIN_APPROX_SIMPLE
:只保存水平、垂直或对角线轮廓的端点cv2.CHAIN_APPROX_TC89_L1
:Ten-Chinl
近似算法的一种cv2.CHAIN_APPROX_TC89_KCOS
:Ten-Chinl
近似算法的一种contours
:检测出的所有轮廓,list
类型,每一个元素都是某个轮廓的像素坐标值hierarchy
:轮廓之间的层次关系检测出轮廓之后,可通过drawContours()
方法绘制出轮廓
image = cv2.drawContours(image, contours, contourIdx, color, thickness, lineType, hierachy, maxLevel, offset)
image
:被绘制轮廓的原始图像contours
:findContours()
方法得到的轮廓列表contoursIdx
:绘制轮廓的索引,如果为-1则绘制所有轮廓color
:绘制颜色,BGR格式thickness
:可选参数,画笔的粗细程度,如果为-1,则绘制实心轮廓lineType
:可选参数,绘制轮廓的线型hierachy
:可选参数,findContours()
方法获得的层次关系maxLevel
:可选参数,绘制轮廓的层次深度,最深绘制到第maxLevel层offset
:可选参数,偏移量,可改变绘制结果的位置import cv2
img = cv2.imread("shape1.png") # 读取原图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 彩色图像转为变成单通道灰度图像
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 灰度图像转为二值图像
# 检测图像中出现的所有轮廓,记录轮廓的每一个点
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
# 绘制所有轮廓,宽度为5,颜色为红色
cv2.drawContours(img, contours, -1, (0, 0, 255), 5)
cv2.imshow("img", img) # 显示绘制结果
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
使用cv2.findContours()
计算出的轮廓,可以计算出拟合曲线,即轮廓的包围框,包围框可以使矩形、圆形
x, y, w, h = cv2.boundingRect(array)
x, y, w, h
:包围框左上角坐标(x, y)
,包围框的宽w
,高h
array
:轮廓数组import cv2
img = cv2.imread('shape2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierachy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
x, y, w, h = cv2.boundingRect(contours[0])
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()
center, radius = cv2.minEnclosingCircle(points)
points
:轮廓数组center
:圆形包围框的中心点坐标radius
:圆形包围框的半径# 注意:使用cv2.circle()绘制时,要确保center, radius参数必须是整形
import cv2
img = cv2.imread('shape2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
t, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
center, radius = cv2.minEnclosingCircle(contours[0])
x = int(round(center[0]))
y = int(round(center[1]))
radius = int(round(radius))
cv2.circle(img, (x, y), radius, (0, 0, 255), 2)
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()
凸包是最逼近轮廓的多边形,凸包的每一处都是凸出来的,即任意三点所组成的内角均小于180度
hull = cv2.convexHull(points, clockwise, returnPoints)
points
:轮廓数组clockwise
:可选参数,布尔值;为True时,凸包中的点按顺时针排列returnPoints
:可选参数,布尔值;为True时,返回点坐标hull
:凸包的点阵数组根据像素的梯度变化寻找图像边缘,最终绘制出十分精细的而之边缘图像
edges = cv2.Canny(image, threshold1, threshold2, apertureSize, L2gradients)
image
:原始图像threshold1
:计算过程中使用的第一个阈值,可以是最小阈值,也可以是最大阈值;通常用来设置最小阈值threshold2
:计算过程中使用的第二个阈值,最大阈值apertureSize
:可选参数,Sobel算子的孔径大小L2gradient
:可选参数,计算梯度的标识,默认为False;为True时采用更精准的算法进行计算edges
:计算结果,二值灰度图import cv2
img = cv2.imread('flower.png')
r1 = cv2.Canny(img, 10, 50)
r2 = cv2.Canny(img, 100, 200)
r3 = cv2.Canny(img, 400, 600)
cv2.imshow('img', img)
cv2.imshow('r1', r1)
cv2.imshow('r2', r2)
cv2.imshow('r3', r3)
cv2.waitKey()
cv2.destroyAllWindows()
通过算法识别图像特征,从而判断出图像的特殊形状,如直线和圆
lines = cv2.HoughLines(image, rho, theta, threshold)
lines = cv2.HoughLinesP(image, rho, theta, threshold, minLineLength, maxLineGap)
image
:原始图像,可以是cv2.Canny()
检测出的边缘图像rho
:检测直线使用的半径步长,值为1时,表示检测所有可能的半径步长theta
:搜索直线的角度,值为 π / 180 \pi/180 π/180时,表示检测所有角度threshold
:阈值,该值越小,表示检测出的直线就越多minLineLength
:线段的最小长度,小于该长度的直线不会记录到结果中maxLineGap
:线段之间的最大距离lines
:格式为:[[[x1, y1, x2, y2], [x1, y1, x2, y2], ...]]
import cv2
import numpy as np
img = cv2.imread('pen.jpg')
o = img.copy()
o = cv2.medianBlur(o, 5)
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
binary = cv2.Canny(o, 50, 150)
lines = cv2.HoughLinesP(binary, 1, np.pi / 180, 15, minLineLength=100, maxLineGap=18)
for line in lines:
x1, y1, x2, y2 = line[0]
cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow('canny', binary)
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()
circles = cv2.HoughCircles(image, method, dp, minDist, param1, param2, minRadius, maxRadius)
image
:原始图像method
:检测方法:cv2.HOUGN_GRADIENT
dp
:累加器分辨率与原始图像分辨率之比的倒数;为1时,累加器分辨率=原始图像分辨率;为2时,累加器分辨率=0.5 * 原始图像分辨率;通常设为1minDist
:圆心之间的最小距离param1
:可选参数,Canny边缘检测使用的最大阈值param2
:可选参数,检测圆环结果的投票数;第一轮筛选时,投票数超过该阈值的圆才能进入第二轮筛选;值越大,检出的圆越少,越精准minRadius
:可选参数,圆的最小半径maxRadius
:可选参数,圆的最大半径circles
:格式为:[[[x1, y1, r1], [x2, y2, r2], ...]]
import cv2
import numpy as np
img = cv2.imread('coin.jpg')
o = img.copy()
o = cv2.medianBlur(o, 5)
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 70, param1=100, param2=25, minRadius=10, maxRadius=50)
circles = np.uint(np.round(circles))
for c in circles[0]:
x, y, r = c
cv2.circle(img, (x, y), r, (0, 0, 255), 3)
cv2.circle(img, (x, y), 2, (0, 0, 255), 3) # 绘制圆心
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()
result = cv2.matchTemplete(image, templ, method, mask)
image
:原始图像templ
:模板图像,尺寸小于等于原始图像method
:匹配方法:
cv2.TM_SQDIFF
:或0
,差值平方和匹配,也叫平方差匹配;可以理解为差异程度;匹配程度越高,计算结果越小,完全匹配的结果为0cv2.TM_SQDIFF_NORMED
:或1
,标准差值平方和匹配,也较标准差匹配cv2.TM_CCORR
:或2
,相关匹配;可以理解为相似程度,匹配程度越高,计算结果越大cv2.TM_CCORR_NORMED
:或3
,标准相关匹配cv2.TM_CCOEFF
:或4
,相关系数匹配,也属于相似程度,计算结果为-1~1之间的浮点数,1表示完全匹配,0表示毫无关系,-1表示两张图片亮度刚好相反cv2,TM_CCOEFF_NORMED
:或5
,标准相关系数匹配mask
:可选参数,掩模,建议使用默认值;cv2.TM_SQDIFF
和cv2.TM_CCORR_NORMED
支持此参数result
:匹配结果;记原始图像宽高为W
、H
,模板图像宽、高为w
、h
,result
即为W-w+1
、H-h+1
;其中每一个浮点数都是原始图像中对应像素位置的匹配结果匹配中只用到一个模板
最终只获得匹配程度最高那一个结果
minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(src, mask)
src
:matchTemplete()
方法计算得出的数组mask
:可选参数,掩模,建议使用默认值minValue
:数组中的最小值maxValue
:数组中的最大值minLoc
:最小值的坐标,(x, y)
maxLoc
:最大值的坐标,(x, y)
# 示例一: 从background 中 匹配出 template
import cv2
img = cv2.imread('background.jpg')
templ = cv2.imread('template.png')
height, width, _ = templ.shape
results = cv2.matchTemplate(img, templ, cv2.TM_SQDIFF_NORMED)
minValue, maxValue, minLoc, maxLoc = cv2.minMaxLoc(results)
resultPoint1 = minLoc
resultPoint2 = (minLoc[0] + width, minLoc[1] + height)
cv2.rectangle(img, resultPoint1, resultPoint2, (0, 0, 255), 2)
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()
# 示例二:从多个图片中匹配templ,找到最佳的匹配的那个原始图片
import cv2
images = []
images.append(cv2.imread('image_221.png'))
images.append(cv2.imread('image_222.png'))
templ = cv2.imread('templ.png')
index = -1
minValue = 1
for i in range(len(images)):
results = cv2.matchTemplate(images[i], templ, cv2.TM_SQDIFF_NORMED)
if results.any() < minValue:
index = i
minValue = min(results)
cv2.imshow('result', images[index])
cv2.waitKey()
cv2.destroyAllWindows()
需同时获得所有匹配程度较高的结果
注意: 数组的列数在图像坐标系中为横坐标,数组的行数在图像坐标系中为纵坐标
import cv2
img = cv2.imread('background2.jpg')
templ = cv2.imread('template.png')
height, width, _ = templ.shape
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)
for y in range(len(results)):
for x in range(len(results[y])):
if results[y][x] > 0.99:
cv2.rectangle(img, (x, y), (x+width, y+height), (0,0,255), 2)
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()
同时查找多个模板的操作,实际上进行了n次(n为模板总数)单模板多目标匹配
import cv2
def myMatchTemplate(img, templ):
height, width, _ = templ.shape
results = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)
location = []
for y in range(len(results)):
for x in range(len(results[y])):
if results[y][x] > 0.99:
location.append((x, y, x + width, y + height))
return location
img = cv2.imread('background2.jpg')
templs = list()
templs.append(cv2.imread('template.png'))
templs.append(cv2.imread('template2.png'))
templs.append(cv2.imread('template3.png'))
locations = []
for t in templs:
locations += myMatchTemplate(img, t)
for l in locations:
cv2.rectangle(img, (l[0], l[1]), (l[2], l[3]), (0, 0, 255), 2)
cv2.imshow('result', img)
cv2.waitKey()
cv2.destroyAllWindows()
capture = cv2.VideoCapture(index)
capture
:要打开的摄像头index
:摄像头的设备索引,如使用笔记本,当index=0
时,表示笔记本的内置摄像头;当index=1
时,表示外置摄像头retval = cv2.VideoCapture.isOpen()
retval
:摄像头是否初始化成功,如果为True,表示初始化成功retval = capture.isOpen()
retval, image = capture.read()
retval
:是否读取到帧,布尔值image
:读取到的帧capture.release()
打开摄像头操作示例:
import cv2
capture = cv2.VideoCapture(0)
while capture.isOpened():
retval, image = capture.read()
cv2.imshow('Video', image)
key = cv2.waitKey(1) # 等待1ms
if key == 32: # 按下空格后
break
capture.release()
cv2.destroyAllWindows()
把摄像头采集到的图片转换为灰度图显示:
import cv2
capture = cv2.VideoCapture(0)
while capture.isOpened():
retval, image = capture.read()
cv2.imshow('rgb', image)
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', image_gray)
if cv2.waitKey(1) == 32:
break
capture.release()
cv2.destroyAllWindows()
按下空格键,保存当前帧:
import cv2
cap = cv2.VideoCapture(0)
while cap.isOpened():
retval, image = cap.read()
cv2.imshow('Video', image)
if cv2.waitKey(1) == 32:
cap.release()
cv2.destroyWindow('Video')
cv2.imwrite('copy.png', image)
break
cv2.destroyAllWindows()
video = cv2.VideoCapture(filename)
video
:要打开的视频filename
:视频文件的文件名import cv2
video = cv2.VideoCapture('公司宣传.avi')
while video.isOpened():
retval, image = video.read()
if not retval:
break
cv2.imshow('video', image)
if cv2.waitKey(1) == 27: # Esc
break
video.release()
cv2.destroyAllWindows()
当cv2.waitKey(1)
时,视频播放速度非常快,可设置为cv2.waitKey(50)
减缓播放速度
import cv2
video = cv2.VideoCapture('公司宣传.avi')
while video.isOpened():
retval, image = video.read()
if not retval:
break
cv2.imshow('video', image)
key = cv2.waitKey(1)
if key == 32: # 按下空格键,暂停
key = cv2.waitKey(0) # 无限等待用户按下任意键
continue # 按下任意键后继续
if key == 27:
break
video.release()
cv2.destroyAllWindows()
retval = cv2.VideoCapture.get(propId)
retval
:获取到与propId
对应的属性值propId
:属性ID:
cv2.CAP_PROP_POS_MSEC
:视频文件播放时的当前位置(单位:ms)cv2.CAP_PROP_POS_FRAMES
:帧的索引,从0开始cv2.CAP_PROP_POS_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_CONVERT_RGB
:指示是否应将图像转换为RGBimport cv2
video = cv2.VideoCapture("公司宣传.avi") # 打开视频文件
fps = video.get(cv2.CAP_PROP_FPS) # 获取视频文件的帧速率
frame_Num = 1 # 用于记录第几幅图像(即第几帧),初始值为1(即第1幅图像)
while (video.isOpened()): # 视频文件被打开后
retval, frame = video.read() # 读取视频文件
# 设置“Video”窗口的宽为420,高为300
cv2.namedWindow("Video", 0)
cv2.resizeWindow("Video", 420, 300)
if retval == True: # 读取到视频文件后
# 当前视频播放到第几帧
cv2.putText(frame, "frame: " + str(frame_Num), (0, 100),
cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 5)
# 该帧对应着视频的第几秒
cv2.putText(frame, "second: " + str(round(frame_Num / fps, 2)) + "s",
(0, 200), cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 0, 255), 5)
cv2.imshow("Video", frame) # 在窗口中显示读取到的视频文件
else: # 没有读取到视频文件
break
key = cv2.waitKey(50) # 窗口的图像刷新时间为50毫秒
frame_Num += 1 #
if key == 27: # 如果按下Esc键
break
video.release() # 关闭视频文件
cv2.destroyAllWindows() # 销毁显示视频文件的窗口
:创建的VideoWriter
类对象filename
:保存视频的路径fourcc
:用四个字符表示的视频编码格式:
cv2.VideoWriter_fourcc()
来确定编码格式:cv2.VideoWriter_fourcc('I', '4', '2', '0')
,表示未压缩的YUV颜色编码格式,兼容性好,但文件较大,扩展名为.avi
cv2.VideoWriter_fourcc('P', 'I', 'M', 'I')
,MPEG-1编码格式,扩展名为.avi
cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
,MPEG-4编码格式,视频文件的大小为平均值,扩展名为.avi
cv2.VideoWriter_fourcc('T', 'H', 'E', 'O')
,Ogg Vorbis编码格式,兼容性差,扩展名为.ogv
cv2.VideoWriter_fourcc('F', 'L', 'V', 'I')
,Flash视频编码格式,扩展名为.flv
fps
:帧速率frameSize
:每一帧的大小,格式为(宽,高)
fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D') # 或 cv2.VideoWriter_fourcc(* 'XVID')
output = cv2.VideoWriter('output.avi', fourcc, 20, (640, 480))
output.write(frame)
frame
:读取到的帧frame
的宽高必须和创建VideoWriter
时指定的宽高frameSize
尺寸相同,否则写不进去output.release()
import cv2
cap = cv2.VideoCapture(0)
size = (640, 480)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, size[0]) # 设定摄像头读取的宽、高
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, size[1])
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('demo11-11.avi', fourcc, 20.0, size)
while cap.isOpened():
ret, frame = cap.read()
out.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1) == 27:
break
cap.release()
out.release()
cv2.destroyAllWindows()
OpenCV依靠级联分类器(.../Python/Lib/site-package/cv2/data/*.xml
)对样本进行识别,分两步进行:
= cv2.CascadeClassifier(filename)
filename
:级联分类器的XML文件名object
:分类器对象objects = cascade.detectMultiScale(image, scaleFactor, minNeighbors, flags, minSize, maxSize)
cascade
:第一步创建的分类器对象image
:待识别的图像scaleFactor
:可选参数,扫描图像时的缩放比例minNeighbors
:可选参数,每个候选区域至少保留多少个检测结果才可以判定为人脸;值越大,分析的误差越小flags
:可选参数,旧版本OpenCV参数,建议使用默认值minSize
:可选参数,最小的目标尺寸maxSize
:可选参数,最大的目标尺寸objects
:捕捉到的目标区域的数组,每个元素都是一个目标区域,每个区域包含[左上角点横坐标,左上角点纵坐标,区域宽,区域高]
;objects格式形如:[[244 203 111 111] [432 81 133 133]]
import cv2
img = cv2.imread('IMG_1286.JPG')
faceCascade = cv2.CascadeClassifier('cascades/haarcascade_frontalface_default.xml') # 该级联分类器存放在当前目录下
faces = faceCascade.detectMultiScale(img, 1.15)
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()
三种人脸识别方法,三种方法识别过程均分为三步:创建识别器、训练识别器、识别
通过PCA
将人脸数据转换至另一个空间维度进行相似度计算
recognizer = cv2.face.EigenFaceRecognizer_create(num_components, threshold)
num_components
:可选参数,PCA
方法中保留的分量个数,建议使用默认值threshold
:可选参数,人脸识别时使用的阈值,建议使用默认值recognizer
:创建的人脸识别器对象recoginzer.train(src, labels)
src
:训练用的人脸图像样本,为list
类型,样本的尺寸必须一致labels
:训练用的人脸标签,必须和src
一一对应label, confidence = recognizer.predict(src)
src
:测试用例,尺寸必须和训练样本一致label
:与样本匹配度最高的标签confidence
:匹配度最高的信用度评分,评分小于5000即可认为匹配度较高,0表示完全匹配
import cv2
import numpy as np
photos = list() # 样本图像列表
lables = list() # 标签列表
photos.append(cv2.imread("face/summer1.png", 0)) # 记录第1张人脸图像
lables.append(0) # 第1张图像对应的标签
photos.append(cv2.imread("face/summer2.png", 0)) # 记录第2张人脸图像
lables.append(0) # 第2张图像对应的标签
photos.append(cv2.imread("face/summer3.png", 0)) # 记录第3张人脸图像
lables.append(0) # 第3张图像对应的标签
photos.append(cv2.imread("face/Elvis1.png", 0)) # 记录第4张人脸图像
lables.append(1) # 第4张图像对应的标签
photos.append(cv2.imread("face/Elvis2.png", 0)) # 记录第5张人脸图像
lables.append(1) # 第5张图像对应的标签
photos.append(cv2.imread("face/Elvis3.png", 0)) # 记录第6张人脸图像
lables.append(1) # 第6张图像对应的标签
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)]) # 数组字典里标签对应的名字
cv2.waitKey() # 按下任何键盘按键后
cv2.destroyAllWindows() # 释放所有窗体
通过LDA
(线性判别分析)方法将人脸数据转换到其他空间去做投影计算
recoginzer = cv2.face.FisherRecognizer_create(num_components, threshold)
简称LBPH
,即局部二值模式直方图,是一种基于局部二值模式算法,善于捕获局部纹理特征
recognizer = cv2.face.LBPHFaceRecognizer_create(radius, neighbors, grid_x, grid_y, threshold)
radius
:可选参数,圆形局部二值模式的半径,建议默认neighbors
:可选参数,圆形局部二值模式的采样点数目,建议默认grid_x
:可选参数,水平方向上的单元格数目,建议默认grid_y
:可选参数,垂直方向上的单元格数目,建议默认threshold
:可选参数,人脸识别使用的阈值,建议默认