人脸识别
读取照片
# 导入cv模块
import cv2 as cv
# 读取图片
img = cv.imread('XZQ.jpg')
# 显示照片
cv.imshow('read_img', img)
# 等待
cv.waitKey(0)
# 释放内存
cv.destroyAllWindows()
def imread(filename, flags=None):
- filename:图像的路径
- flags=None:表示如何读取这幅图片,下面介绍介绍一下有哪些方法,这些方法既可以使用前面的值,也可以使用后面的数字代替。
| flags | 含义 |
| — | — |
| cv.IMREAD_ANYCOLOR=4 | 原图读取 |
| cv.IMREAD_ANYDEPTH = 2 | 不论什么位深度。如果载入的图像是16-bit位图或者32-bit位图。则转化为8-bit位图。 |
| cv.IMREAD_COLOR=1 | 读入一副彩色图像。图像的透明度会被忽略,这是默认参数。 |
| cv.IMREAD_GRAYSCALE=0 | 以灰度模式读入图像 |
| cv.IMREAD_LOAD_GDAL=8 | 使用gdal驱动程序加载图像。 |
| cv.IMREAD_UNCHANGED=-1 | 不改变读取的是原图。读入一幅图像,并且包括图像的 alpha 通道 |
def waitKey(delay=None):
- 参数delay表示等待delay ms,在此期间如果有键按下则立即结束并返回按下的那个按键的ASCII码,否则返回-1.
- waitkey(0)表示一直等待下去,直至有键按下才结束。
def destroyAllWindows():
- 关闭窗口并取消分配任何相关的内存使用
灰度转换
# 导入cv模块
import cv2 as cv
# 读取图片
img = cv.imread('XZQ.jpg')
# 灰度转换
gray_img = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
# 显示灰度
cv.imshow('gray', gray_img)
# 保存灰度照片
cv.imwrite('grat_XZQ.jpg', gray_img)
# 显示照片
cv.imshow('read_img', img)
# 等待
cv.waitKey(0)
# 释放内存
cv.destroyAllWindows()
def imwrite(filename, img, params=None):
- filename:图像的路径
- img:可以为图像文件,也可以是摄像头画面中的一帧
def cvtColor(src, code, dst=None, dstCn=None):
- 是Opencv里的颜色空间转换函数,可以实现rgb颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像。
- 参数 CV_BGR2GRAY 是 RGB 到 gray,
- 参数 CV_GRAY2BGR 是 gray 到RGB. 处理结果是彩色的,则转灰色就是了:
- src 输入的 8-bit , 16-bit 或 32-bit 单倍精度浮点数影像。
- code 色彩空间转换的模式,该code来实现不同类型的颜色空间转换。
比如 CV_BGR2GRAY表示转换为灰度图,CV_BGR2HSV将图片从RGB空间转换为HSV空间。其中当code选用CV_BGR2GRAY时,dst需要是单通道图片。当code选用CV_BGR2HSV时,对于8位图,需要将rgb值归一化到0-1之间。这样得到HSV图中的H范围才是0-360,S和V的范围是0-1。
修改尺寸
# 导入cv模块
import cv2 as cv
# 读取图片
img = cv.imread('XZQ.jpg')
# 修改尺寸
resize_img = cv.resize(img, dsize=(200, 200))
# 显示原图
cv.imshow('img', img)
# 显示修改后的
cv.imshow('resize_img', resize_img)
# 打印原图尺寸大侠
print('未修改:', img.shape)
# 打印修改后的大小
print('修改后:', resize_img.shape)
# 等待
while True:
if ord('q') == cv.waitKey(0):
break
# 释放内存
cv.destroyAllWindows()
ord(‘q’)
- 可以返回q的ASCII码
def resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None):
- src :输入,原图像,即待改变大小的图像;
- dst: 输出,改变后的图像。这个图像和原图像具有相同的内容,只是大小和原图像不一样而已;
- dsize:输出图像的大小。
- 如果这个参数不为0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为0,那么原图像缩放之后的大小就要通过下面的公式来计算:
dsize = Size(round(fxsrc.cols), round(fysrc.rows)) - fx:width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;
- fy:height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算;
- interpolation:这个是指定插值的方式,图像缩放之后,肯定像素要进行重新计算的,就靠这个参数来指定重新计算像素的方式,有以下几种:
| interpolation | 含义 |
| — | — |
| INTER_NEAREST | 最邻近插值 |
| INTER_LINEAR | 双线性插值,如果最后一个参数你不指定,默认使用这种方法 |
| INTER_AREA | resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method. |
| INTER_CUBIC | 4x4像素邻域内的双立方插值 |
| INTER_LANCZOS4 | 8x8像素邻域内的Lanczos插值 |
- 使用注意事项:
- dsize和fx/fy不能同时为0,
要么你就指定好dsize的值,让fx和fy空置直接使用默认值,就像resize(img, imgDst, Size(30,30));
要么你就让dsize为0,指定好fx和fy的值,比如fx=fy=0.5,那么就相当于把原图两个方向缩小一倍!
至于最后的插值方法,正常情况下使用默认的双线性插值就够用了。
几种常用方法的效率是:最邻近插值>双线性插值>双立方插值>Lanczos插值;
但是效率和效果成反比,所以根据自己的情况酌情使用。
正常情况下,在使用之前dst图像的大小和类型都是不知道的,类型从src图像继承而来,大小也是从原图像根据参数计算出来。但是如果你事先已经指定好dst图像的大小,那么你可以通过下面这种方式来调用函数:
绘制矩形
# 导入cv模块
import cv2 as cv
# 读取图片
img = cv.imread('XZQ.jpg')
# 坐标
x, y, w, h = 100, 100, 200, 200
# 绘制矩形
cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 255, 0), thickness=1)
# 绘制圆形
cv.circle(img, center=(x + w//2, y + h//2), radius=100, color=(255, 0, 0), thickness=2)
# 显示
cv.imshow('re_img', img)
# 等待
while True:
if ord('q') == cv.waitKey(0):
break
# 释放内存
cv.destroyAllWindows()
def rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):
- img:指定一张图片,在这张图片的基础上进行绘制;(img相当于一个画板)
- pt1: 由(x_min,x_max)组成,为绘制的边框的左上角;
- pt2: 由(x_max, y_max)坐标,为绘制的边框的右下角,示意如下:
- color:指定边框的颜色,由(B,G,R)组成,当为(255,0,0)时为绿色,可以自由设定;
- thinkness:线条的粗细值,为正值时代表线条的粗细(以像素为单位),为负值时边框实心;
- lineType 和 shift yi一般不做考虑;
人脸检测
# 导入cv模块
# 导入cv模块
import cv2 as cv
def face_detect_demo():
gary = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
face_detect = cv.CascadeClassifier('D:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
face = face_detect.detectMultiScale(gary, 1.01, 5, 0, (100, 100), (300, 300))
for x, y, w, h in face:
cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 225), thickness=2)
cv.imshow('result', img)
# 读取图片
img = cv.imread('XZQ.jpg')
# 检测函数
face_detect_demo()
# 等待
while True:
if ord('q') == cv.waitKey(0):
break
# 释放内存
cv.destroyAllWindows()
def detectMultiScale(self, image, scaleFactor=None, minNeighbors=None, flags=None, minSize=None, maxSize=None):
- image表示的是要检测的输入图像
- scaleFactor表示每次图像尺寸减小的比例
- minNeighbors表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大小都可以检测到人脸)
- flags 旧版用的一个参数,我们一般用不到设置成零即可
- minSize为目标的最小尺寸
- maxSize为目标的最大尺寸
cv.CascadeClassifier
视频检测
# 导入cv模块
import cv2 as cv
def face_detect_demo(img):
gary = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
face_detect = cv.CascadeClassifier('D:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
face = face_detect.detectMultiScale(gary)
for x, y, w, h in face:
cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 225), thickness=2)
cv.imshow('result', img)
# 读取摄像头
cap = cv.VideoCapture('XZQTianWaiLaiWu.mp4')
# 循环
while True:
flag, frame = cap.read()
if not flag:
break
# 修改尺寸
resize_img = cv.resize(frame, dsize=(700, 500))
face_detect_demo(resize_img)
if ord('q') == cv.waitKey(1):
break
# 释放内存
cv.destroyAllWindows()
# 释放摄像头
cap.release()
拍照保存
# 导入模块
import cv2
cap = cv2.VideoCapture('XZQTianWaiLaiWu.mp4')
num = 1
while (cap.isOpened()): # 检测是否在开启状态
ret_flag, Vshow = cap.read() # 得到每帧图像
cv2.imshow("Capture_Test", Vshow) # 显示图像
k = cv2.waitKey(1) & 0xFF # 按键判断
if k == ord('s'): # 保存
cv2.imwrite("data/" + str(num) + ".name" + ".jpg", Vshow)
print('success to sava' + str(num) + '.jpg')
print('----------------------')
num += 1
elif k == ord(' '): # 推出
break
# 释放摄像头
cap.release()
# 释放内存
cv2.destroyAllWindows()
cv2.VideoCapture(0)
- https://blog.csdn.net/weixin_40922285/article/details/102967331?ops_request_misc=%7B%22request%5Fid%22%3A%22164442086116780255258154%22%2C%22scm%22%3A%2220140713.130102334…%22%7D&request_id=164442086116780255258154&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_positive~default-1-102967331.first_rank_v2_pc_rank_v29&utm_term=cv2.videocapture&spm=1018.2226.3001.4187
release()
- 释放摄像头
数据训练
import os
import cv2
from PIL import Image
import numpy as np
def getImageAndLabels(path):
# 存在人脸数据
facesSamples = []
# 储存姓名数据
ids = []
# 存储图片信息
imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
# 加载分类器
face_detector = cv2.CascadeClassifier('D:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
# 便利列表中的图片
for imagePath in imagePaths:
# 打开图片,灰度化 PIL 有九种不同模式:1,L,P,RGB,RGBA,CMYK,YCbCr,I,F
PIL_img = Image.open(imagePath).convert('L')
# 将图片转换为数组,以黑白深浅
img_numpy = np.array(PIL_img, 'uint8')
# 获取图像人脸特征
faces = face_detector.detectMultiScale(img_numpy)
# 获取每张图片的id和姓名
id = int(os.path.split(imagePath)[1].split('.')[0])
# 预防无面容照片
for x, y, w, h in faces:
ids.append(id)
facesSamples.append(img_numpy[y:y + h, x:x + w])
# 打印面部特征和id
print('id:', id)
print('fs:', facesSamples)
return facesSamples, ids
if __name__ == '__main__':
# 图片路径
path = 'data/'
# 获取图像数组和id标签数组和姓名
faces, ids = getImageAndLabels(path)
# 加载识别器
recognizer = cv2.face.LBPHFaceRecognizer_create()
# 训练
recognizer.train(faces, np.array(ids))
# 保存文件
recognizer.write('trainer/trainer.yml')
人脸识别
import cv
import cv2
import os
import urllib
import urllib.request
import numpy
from PIL import Image, ImageDraw, ImageFont
# 加载训练用数据文件
recogizer = cv2.face.LBPHFaceRecognizer_create()
# 加载数据
recogizer.read('trainer/trainer.yml')
# 名称
names = ['薛之谦']*10
# 警报全局变量
warningtime = 0
# md5加密
def md5(str):
import hashlib
m = hashlib.md5()
m.update(str.encode('utf8'))
return m.hexdigest()
# 短信反馈
statuStr = {
'0': '短信发送成功',
'-1': '参数不全',
'-2': '服务器空间不支持,请确认支持curl或者fsocket,联系您的空间商解决或者更换空间',
'30': '密码错误',
'40': '账号不存在',
'41': '余额不足',
'42': '账户已过期',
'43': 'IP地址限制',
'50': '内容含有敏感词'
}
# 报警模块
def warning():
print('陌生人')
# 下面注释的是一种短信警告方式
'''
smsapi = 'http://api.smsbao.com/'
#短信平台账号
user = '176****9967'
#短信平台密码
password = md5('*********')
# 要发送的短信内容
content = '【警报】 \n原因:xxx\n地点:xxx\n时间:xxx'
# 要发送短信的手机号码
phone = '176****9967'
data = urllib.parse.urlencode({'u':user,'p':password,'m':phone,'c':content})
send_url = smsapi + 'sms?' + data
response = urllib.request.urlopen(send_url)
the_page = response.read().decode('utf-8')
print(statuStr[the_page])
'''
# 转中文
def cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20):
if (isinstance(img, numpy.ndarray)): # 判断是否OpenCV图片类型
img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
# 创建一个可以在给定图像上绘图的对象
draw = ImageDraw.Draw(img)
# 字体的格式
fontStyle = ImageFont.truetype("font/simsun.ttc", textSize, encoding="utf-8")
# 绘制文本
draw.text((left, top), text, textColor, font=fontStyle)
# 转换回OpenCV格式
return cv2.cvtColor(numpy.asarray(img), cv2.COLOR_RGB2BGR)
# 准备识别的图片
def face_detect_demo(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为灰度
# 加载数据库
face_detector = cv2.CascadeClassifier('D:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
# 从数据库查询
# face = face_detector.detectMultiScale(gray, 1.1, 5, cv2.CASCADE_SCALE_IMAGE, (100, 100), (300, 300))
face = face_detector.detectMultiScale(gray)
for x, y, w, h in face:
cv2.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=1)
cv2.circle(img, center=(x + w // 2, y + h // 2), radius=w // 2, color=(0, 255, 0), thickness=1)
# 人脸识别
ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])
# print('标签id:',ids,'置信评分:',confidence)
if confidence > 80:
global warningtime
warningtime += 1
if warningtime > 100:
warning()
warningtime = 0
cv2.putText(img, 'unkonw', (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
else:
# cv2.putText(img, str(names[ids - 1]), (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
# cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20)
img = cv2ImgAddText(img, names[ids - 1], x + 10, y - 20)
print('薛之谦!!')
cv2.imshow('result', img)
# print('bug:',ids)
if __name__ == '__main__':
# 读取摄像头
cap = cv2.VideoCapture('XZQTianWaiLaiWu.mp4') # 视频来源
# 循环
while True:
flag, frame = cap.read()
if not flag:
break
resize_img = cv2.resize(frame, dsize=(700, 500))
face_detect_demo(resize_img)
if ord('q') == cv2.waitKey(1):
break
# 释放内存
cv2.destroyAllWindows()
# 释放摄像头
cap.release()
版权声明:本文为qq_62678867原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。