当前位置:   article > 正文

人脸识别 - cv2_cv2人脸识别

cv2人脸识别

人脸识别

读取照片

# 导入cv模块
import cv2 as cv

# 读取图片
img = cv.imread('XZQ.jpg')
# 显示照片
cv.imshow('read_img', img)
# 等待
cv.waitKey(0)
# 释放内存
cv.destroyAllWindows()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

def imread(filename, flags=None):

  1. filename:图像的路径
  2. 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):

  1. 参数delay表示等待delay ms,在此期间如果有键按下则立即结束并返回按下的那个按键的ASCII码,否则返回-1.
  2. waitkey(0)表示一直等待下去,直至有键按下才结束。

def destroyAllWindows():

  1. 关闭窗口并取消分配任何相关的内存使用

灰度转换

# 导入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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

def imwrite(filename, img, params=None):

  1. filename:图像的路径
  2. img:可以为图像文件,也可以是摄像头画面中的一帧

def cvtColor(src, code, dst=None, dstCn=None):

  1. 是Opencv里的颜色空间转换函数,可以实现rgb颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像。
  2. 参数 CV_BGR2GRAY 是 RGB 到 gray,
  3. 参数  CV_GRAY2BGR 是 gray 到RGB. 处理结果是彩色的,则转灰色就是了:
  4. src 输入的  8-bit , 16-bit 或  32-bit 单倍精度浮点数影像。
  5. 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

ord(‘q’)

  • 可以返回q的ASCII码

def resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None):

  1. src :输入,原图像,即待改变大小的图像;
  2. dst: 输出,改变后的图像。这个图像和原图像具有相同的内容,只是大小和原图像不一样而已;
  3. dsize:输出图像的大小。
  4. 如果这个参数不为0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为0,那么原图像缩放之后的大小就要通过下面的公式来计算:
    dsize = Size(round(fxsrc.cols), round(fysrc.rows))
  5. fx:width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;
  6. fy:height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算;
  7. 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

def rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None):

  1. img:指定一张图片,在这张图片的基础上进行绘制;(img相当于一个画板)
  2. pt1: 由(x_min,x_max)组成,为绘制的边框的左上角;
  3. pt2: 由(x_max, y_max)坐标,为绘制的边框的右下角,示意如下:
  4. color:指定边框的颜色,由(B,G,R)组成,当为(255,0,0)时为绿色,可以自由设定;
  5. thinkness:线条的粗细值,为正值时代表线条的粗细(以像素为单位),为负值时边框实心;
  6. 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

def detectMultiScale(self, image, scaleFactor=None, minNeighbors=None, flags=None, minSize=None, maxSize=None):

  1. image表示的是要检测的输入图像
  2. scaleFactor表示每次图像尺寸减小的比例
  3. minNeighbors表示每一个目标至少要被检测到3次才算是真的目标(因为周围的像素和不同的窗口大小都可以检测到人脸)
  4. flags 旧版用的一个参数,我们一般用不到设置成零即可
  5. minSize为目标的最小尺寸
  6. 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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

拍照保存

# 导入模块
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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

cv2.VideoCapture(0)

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')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

人脸识别

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()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/822311
推荐阅读
相关标签
  

闽ICP备14008679号