Python人脸识别图片视频

人脸识别技术发展现状及未来趋势

当前,随着人工智能、物联网等前沿技术的迅速发展,智能时代已悄然到来,"刷脸"逐渐成为了新的风潮。在人脸识别技术商业化应用领域不断扩张的趋势下,“刷脸”办事正愈发常见。

人脸识别,是基于人的脸部特征信息进行身份识别的一种生物识别技术。用摄像机或摄像头采集含有人脸的图像或视频流,并自动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部识别的一系列相关技术,通常也叫做人像识别、面部识别。

一、人脸识别技术发展背景

人脸识别,是基于人的脸部特征信息进行身份识别的一种生物识别技术。除了安防、金融这两大领域外,人脸识别还在交通、教育、医疗、警务、电子商务等诸多场景实现了广泛应用,且呈现出显著应用价值。为了进一步把握人脸识别技术所带来的重大机遇,我国出台了一系列政策予以支撑。

二、人脸识别技术发展历程

人脸识别最初在20世纪60年代已经有研究人员开始研究,真正进入初级的应用阶段是在90年代后期,发展至今其技术成熟度已经达到较高的程度。整个发展过程可以分为机械识别、半自动化识别、非接触式识别及互联网应用阶段。

与其他生物识别方式相比,人脸识别优势在于自然性、不被察觉性等特点。自然性即该识别方式同人类进行个体识别时所利用的生物特征相同。指纹识别、虹膜识别等均不具有自然性。不被察觉的特点使该识别方法不易使人抵触,而指纹识别或虹膜识别需利用电子压力传感器或红外线采集指纹、虹膜图像,在采集过程中体验感不佳。目前人脸识别需要解决的难题是在不同场景、脸部遮挡等应用时如何保证识别率。此外,隐私性和安全性也是值得考虑的问题。人脸识别优势明显,未来将成为识别主导技术。具体来说,相比指纹识别、虹膜识别等传统的生物识别方式,优点主要还集中在四点:非接触性、非侵扰性、硬件基础完善和采集快捷便利,可拓展性好。在复杂环境下,人脸识别精度问题得到解决后,预计人脸识别有望快速替代指纹识别成为市场大规模应用的主流识别技术。

import argparse
import os
import re
import sys
import urllib
import json
import socket
import urllib.request
import urllib.parse
import urllib.error
# 设置超时
import time

time_sleep = 0.1

def handle_baidu_cookie(original_cookie, cookies):
    """
    :param string original_cookie:
    :param list cookies:
    :return string:
    """
    if not cookies:
        return original_cookie
    result = original_cookie
    for cookie in cookies:
        result += cookie.split(';')[0] + ';'
    result.rstrip(';')
    return result

def get_suffix(name):
    m = re.search(r'\.[^\.]*$', name)
    if m.group(0) and len(m.group(0)) <= 5:
        return m.group(0)
    else:
        return '.jpg'

# 保存图片
def save_image(rsp_data, word, max_count):
    if not os.path.exists("./" + word):
        os.mkdir("./" + word)
    # 判断名字是否重复,获取图片长度
    counter = len(os.listdir('./' + word)) + 1
    for image_info in rsp_data['data']:
        try:
            if 'replaceUrl' not in image_info or len(image_info['replaceUrl']) < 1:
                continue
            obj_url = image_info['replaceUrl'][0]['ObjUrl']
            thumb_url = image_info['thumbURL']
            url = 'https://image.baidu.com/search/down?tn=download&ipn=dwnl&word=download&ie=utf8&fr=result&url=%s&thumburl=%s' % (urllib.parse.quote(obj_url), urllib.parse.quote(thumb_url))
            time.sleep(time_sleep)
            suffix = get_suffix(obj_url)
            # 指定UA和referrer,减少403
            opener = urllib.request.build_opener()
            opener.addheaders = [
                ('User-agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'),
            ]
            urllib.request.install_opener(opener)
            # 保存图片
            filepath = './%s/%s' % (word, str(counter) + str(suffix))
            urllib.request.urlretrieve(url, filepath)
            if os.path.getsize(filepath) < 5:
                print("下载到了空文件,跳过!")
                os.unlink(filepath)
                continue
        except urllib.error.HTTPError as urllib_err:
            print(urllib_err)
            continue
        except Exception as err:
            time.sleep(1)
            print(err)
            print("产生未知错误,放弃保存")
            continue
        else:
            print("图片下载成功,已有" + str(counter) + "张图片")
            if counter == max_count:
                return
            counter += 1
    return

def pic_num(file_path):
    return len(os.listdir(file_path))

def request_json_str(request_url):
    try:
        user_headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0', 'Cookie': ''}
        req = urllib.request.Request(url=request_url, headers=user_headers)
        page = urllib.request.urlopen(req)
        user_headers['Cookie'] = handle_baidu_cookie(user_headers['Cookie'], page.info().get_all('Set-Cookie'))
        rsp = page.read()
        page.close()
    except UnicodeDecodeError as e:
        print(e)
        print('-----UnicodeDecodeErrorurl:', single_page_url)
    except urllib.error.URLError as e:
        print(e)
        print("-----urlErrorurl:", single_page_url)
    except socket.timeout as e:
        print(e)
        print("-----socket timout:", single_page_url)
    else:
        return rsp

def decode_json(json_source):
    try:
        json_data = json.loads(json_source, strict=False)
    except json.decoder.JSONDecodeError:
        try:
            source_replace = str(json_source.decode(encoding='utf8')).replace('\\', '\\\\')
            json_data = json.loads(source_replace, strict=False)
        except json.decoder.JSONDecodeError:
            return None
    return json_data

def download_single_page(word, page_url, max_pic_num):
    print("开始下载" + page_url + "中的数据")
    max_err_num = 5
    err_count = 0
    rsp = request_json_str(page_url)
    rsp_data = decode_json(rsp)
    while(rsp_data == None or 'data' not in rsp_data):
        if rsp_data == None:
            print("JSON字符串错误,尝试重试")
            err_count += 1
        else:
            print("触发反爬机制,正在重试\r", end='')
        if err_count > max_err_num:
            print("JSON错误次数超过", max_err_num, "次,跳过该页")
            return
        rsp = request_json_str(page_url)
        rsp_data = decode_json(rsp)
    save_image(rsp_data, word, max_pic_num)
    print("该页下载完成")

def get_image(word, max_pic_num):
    os.mkdir('./' + word)
    start_page = 1
    per_page = 30
    start_amount = (start_page - 1) * per_page
    search = urllib.parse.quote(word)
    pn = start_amount

    while pic_num('./' + word) < max_pic_num:
        single_page_url = 'https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord=%s&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=&latest=©right=&word=%s&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&pn=%s&rn=%d&gsm=1e&1594447993172=' % (search, search, str(pn), per_page)
        time.sleep(time_sleep)
        download_single_page(word, single_page_url, max_pic_num)
        pn += per_page
    print("下载任务结束")
    return

#删除原文件夹
def del_file(path):
    list1 = os.listdir(path)
    for i in list1:
        c_path = os.path.join(path, i)
        if os.path.isdir(c_path):
            del_file(c_path)
        else:
            os.remove(c_path)
    # print(path,"已被删除")

#爬图片
import os
image_name="美女"
image_count=10
if(os.path.exists(r'/home/aistudio/%s'%(image_name))):
    del_file(r'/home/aistudio/%s'%(image_name))
    os.rmdir(r'/home/aistudio/%s'%(image_name))

if(os.path.exists(r'/home/aistudio/output')):
    del_file(r'/home/aistudio/output')
    os.rmdir(r'/home/aistudio/output')
    os.mkdir("output")
    print("已创建文件夹output")
else:
    os.mkdir("output")
    print("已创建文件夹output")
    
get_image(image_name,image_count)

# 安装PaddleHub

!pip install paddlehub==1.8.0

检测人脸 

​
%matplotlib inline
# 导入所需要使用的包
import cv2 
import paddlehub as hub
from  matplotlib import pyplot as plt

# 加载Paddlehub人脸检测模型
face_detector = hub.Module(name="pyramidbox_lite_mobile")

def renlian(path1,path2,image_count_i): #原始图片 检测后的图片 图片数量

    # 使用模型进行图片预测
    result = face_detector.face_detection(paths=[r'%s/%s.jpg'%(path1,image_count_i)], 
                                        use_gpu=False, 
                                        visualization=True, 
                                        output_dir='/home/aistudio/output',
                                        confs_threshold=0.5)

    # 打印检测结果
    # print(result)

    # 显示可视化图片
    output = cv2.imread(r'%s/%s.jpg'%(path2,image_count_i))
    output = output[:,:,::-1]
    plt.imshow(output)
    plt.show()

​

显示图片

path1 = r'/home/aistudio/%s'%(image_name)
path2 = r'/home/aistudio/output'

list1 = os.listdir(path1)
list2 = os.listdir(path2)

for i in range(1,image_count+1):
    renlian(path1,path2,i)

结果展示(一)共10例(由于太长,这里只展示两例)

Python人脸识别图片视频_第1张图片

Python人脸识别图片视频_第2张图片

 修改部分代码

#爬图片
import os
image_name="鞠婧祎"
image_count=10

get_image(image_name,image_count)

path1 = r'/home/aistudio/%s'%(image_name)
path2 = r'/home/aistudio/output'

list1 = os.listdir(path1)
list2 = os.listdir(path2)

for i in range(1,image_count+1):
    renlian(path1,path2,i)

结果展示2(由于太长,这里只展示三例)

Python人脸识别图片视频_第3张图片

Python人脸识别图片视频_第4张图片 Python人脸识别图片视频_第5张图片

 更换原图片

 Python人脸识别图片视频_第6张图片

 Python人脸识别图片视频_第7张图片

缺陷

  1. 部分人脸无法识别出来
  2. 动物的脸也会被识别出来
  3. 多人无法识别出来

更换算法

代码

import matplotlib.pyplot as plt
import matplotlib.image as mpimg 

# 展示待预测图片

path = '/home/aistudio/picture'
test_img_path = os.listdir(path)
print(test_img_path)
for i in test_img_path:
    if i[0] =='.': test_img_path.remove(i)

test_img_path.sort()#排序
print('test_img_path:',test_img_path)

# 待预测图片
test_img_path_s = ["/home/aistudio/picture/01.jpg",
        "/home/aistudio/picture/02.jpg",
        "/home/aistudio/picture/03.jpg",
        ]

test_img_path_s=[]
for i in test_img_path:
    test_img_path_s.append(path+'/'+i)

print('test_img_path_s:',test_img_path_s)

for i in test_img_path_s:
    img = mpimg.imread(i) 

    plt.figure(figsize=(10,10))
    plt.imshow(img) 
    plt.axis('off') 
    plt.show()

Python人脸识别图片视频_第8张图片

说明:

利用Ultra-Light-Fast-Generic-Face-Detector-1MB完成对该文件的人脸检测,只需读入该文件,将文件内容存成listlist中每个元素是待预测图片的存放路径。

ultra_light_fast_generic_face_detector_1mb_320,在预测时会将图片输入缩放为320 * 240,预测速度更快。

ultra_light_fast_generic_face_detector_1mb_640,在预测时会将图片输入缩放为640 * 480,预测精度更高。

准备

import paddlehub as hub

module = hub.Module(name="ultra_light_fast_generic_face_detector_1mb_640")
#module = hub.Moudle(name="ultra_light_fast_generic_face_detector_1mb_320")

接下来

def cpdd(img_name):

    img=[r'/home/aistudio/picture/%s'%(img_name)]

    print(img)

    # 多张脸单图片处理
    input_dict = {"image": img}
    
    # 预测结果展示
    results = module.face_detection(data=input_dict)

    for result in results:
        res1 = result['data']
    # print(res1)
    
    #绘制矩形并显示
    img = mpimg.imread(img[0]) 

    for i in range(len(res1)):
        img = cv2.rectangle(img,(int(res1[i]['left']),int(res1[i]['top'])),(int(res1[i]['right']),int(res1[i]['bottom'])),(0,255,0),3)

    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    cv2.imwrite(r"/home/aistudio/output2/%s"%(img_name),img)

    plt.figure(figsize=(10,10))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    plt.imshow(img)
    plt.axis('off') 
    plt.show()

def cpdds(test_img_path):

    if(os.path.exists(r'/home/aistudio/output2')):
        del_file(r'/home/aistudio/output2')
        os.rmdir(r'/home/aistudio/output2')
        os.mkdir("output2")
        print("已创建文件夹 output2")
    else:
        os.mkdir("output2")
        print("已创建文件夹 output2")

    for i in test_img_path:
        cpdd(i)

cpdds(test_img_path)

输出:

已创建文件夹 output2

['/home/aistudio/picture/01.jpg']

Python人脸识别图片视频_第9张图片

['/home/aistudio/picture/02.jpg']

Python人脸识别图片视频_第10张图片

  ['/home/aistudio/picture/03.jpg']

 Python人脸识别图片视频_第11张图片

应用1(以人脸替换为例)

检测到人脸可以戴上口罩、戴上眼镜、打马赛克等,以下为人脸替换示例

替换使用图片:

Python人脸识别图片视频_第12张图片

代码

对之前的代码进行小幅度修改

def cpdd(img_name,TF=False): #TF表示是否遮挡

    img=[r'/home/aistudio/picture/%s'%(img_name)]
    
    print(img)

    img_0=img

    # 多张脸单图片处理
    input_dict = {"image": img}
    
    # 预测结果展示
    results = module.face_detection(data=input_dict)

    for result in results:
        res = result['data']
    # print('res=',res)
    # print(type(res))
    
    #绘制矩形并显示
    img = mpimg.imread(img[0]) 

    for i in range(len(res)):
        img = cv2.rectangle(img,(int(res[i]['left']),int(res[i]['top'])),(int(res[i]['right']),int(res[i]['bottom'])),(0,255,0),3)

    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    cv2.imwrite(r"/home/aistudio/output2/%s"%(img_name),img)

    plt.figure(figsize=(10,10))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    plt.imshow(img)
    plt.axis('off') 
    plt.show()

    if(TF):
        z_cpdds(img_0,'/home/aistudio/mask.jpg',res)

def cpdds(test_img_path,TF=False):

    if(os.path.exists(r'/home/aistudio/output2')):
        del_file(r'/home/aistudio/output2')
        os.rmdir(r'/home/aistudio/output2')
        os.mkdir("output2")
        print("已创建文件夹 output2")
    else:
        os.mkdir("output2")
        print("已创建文件夹 output2")

    for i in test_img_path:
        cpdd(i,TF)

 增加一个新的函数

def z_cpdds(cpNB,cpTNB,res_list):

    print('cpNB,cpTNB=',cpNB,cpTNB)

    #被遮挡的图片路径(列表) #用来遮挡的图片路径
    #遮挡
    from PIL import Image
    import numpy as np 

    #img = mpimg.imread(cpNB[0])
    img = cv2.imread(cpNB[0])

    for res in res_list:

        shape = (int(res['right']-res['left']),int(res['bottom']-res['top']))#人脸区域大小
        image = Image.open(cpTNB).resize(shape) #用来遮挡的图片
        face = img[int(res['top'])+10:int(res['top'])+image.size[1]+10, int(res['left'])+5:int(res['left'])+image.size[0]+5]#整体右下移动
        #print(image.size)#宽高
        #print(face.shape)#高宽

        # 图片加权合成
        scope_map = np.array(image)[:,:,-1] / 255
        scope_map = scope_map[:,:,np.newaxis]
        scope_map = np.repeat(scope_map, repeats=3, axis=2)
        res_image = np.multiply(scope_map, np.array(image)[:,:,:3]) + np.multiply((1-scope_map), np.array(face))

        img[int(res['top']):int(res['top'])+image.size[1], 
            int(res['left']):int(res['left'])+image.size[0]] = np.uint8(image)[:, : , ::-1]

    plt.figure(figsize=(10,10))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    plt.imshow(img)
    plt.axis('off') 
    plt.show()

运行代码展示结果:

['01.jpg', '02.jpg', '03.jpg']

已创建文件夹 output2

['/home/aistudio/picture/01.jpg']

Python人脸识别图片视频_第13张图片

cpNB,cpTNB=

['/home/aistudio/picture/01.jpg']

/home/aistudio/mask.jpg

Python人脸识别图片视频_第14张图片

['/home/aistudio/picture/02.jpg']

Python人脸识别图片视频_第15张图片

cpNB,cpTNB=

['/home/aistudio/picture/02.jpg']

/home/aistudio/mask.jpg

Python人脸识别图片视频_第16张图片

['/home/aistudio/picture/03.jpg']

Python人脸识别图片视频_第17张图片

cpNB,cpTNB=

['/home/aistudio/picture/03.jpg']

/home/aistudio/mask.jpg

Python人脸识别图片视频_第18张图片

应用2(统计视频中人脸数)

使用的视频

视频1

代码

首先

!pip install paddlehub==1.8.0

import cv2
import os
import numpy as np
import paddlehub as hub

函数(视频输出为图片->人脸检测->图片合成为视频)

def CutVideo2Image(video_path, img_path):
    #将视频输出为图像
    print('将视频输出为图像中')
    #video_path为输入视频文件路径
    #img_path为输出图像文件夹路径
    cap = cv2.VideoCapture(video_path)
    index = 0
    while(True):
        ret,frame = cap.read() 
        if ret:
            cv2.imwrite(img_path+'/%d.jpg'%index, frame)
            index += 1
            
        else:
            break
        
    cap.release()
    print('输出图像%d张'%(index))
    print('视频输出为图像完毕')

def Iou(bbox1,bbox2):
    #计算Iou
    #bbox1,bbox为xyxy数据
    area1 = (bbox1[2]-bbox1[0])*(bbox1[3]-bbox1[1])
    area2 = (bbox2[2]-bbox2[0])*(bbox2[3]-bbox2[1])
    w = min(bbox1[3],bbox2[3])-max(bbox1[1],bbox2[1])
    h = min(bbox1[2],bbox2[2])-max(bbox1[0],bbox2[0])
    if w<=0 or h<=0:
        return 0
    area_mid = w*h
    return area_mid/(area1+area2-area_mid)

    
def GetFace(in_path, out_path):
    #人脸检测,并计算通过的人数
    print('人脸检测中')
    #in_path为输入图像文件夹的路径
    #out_path为输出图像文件夹的路径,并为人脸标注检测框和进行计数
    files = os.listdir(in_path)
    face_detector = hub.Module(name="pyramidbox_lite_server")
    
    bbox_buffer = []
    count = 0  #统计人数
    for i in range(len(files)):
        #文件中的每张图片
        img = cv2.imread(in_path+'/%d.jpg' % i)
        result = face_detector.face_detection(images=[img])
        data = result[0]['data']
        
        bbox_upgrade = []
        index = []
        for j in range(len(data)):
            #图片中的每个bbox
            left, right = int(data[j]['left']), int(data[j]['right'])
            top, bottom  = int(data[j]['top']), int(data[j]['bottom'])
            bbox = (left, top, right, bottom)
            
            if right>1600 and left<1600:
                count = count+1
                for k in range(len(bbox_buffer)):
                    if Iou(bbox, bbox_buffer[k])>0.1 and k not in index:
                        count = count-1
                        index.append(k)
                        break
                bbox_upgrade.append(bbox)
                cv2.rectangle(img, (left, top), (right, bottom), (0, 0, 255), 3)
            else:                    
                cv2.rectangle(img, (left, top), (right, bottom), (0, 255, 0), 3)
        bbox_buffer = bbox_upgrade.copy()
        cv2.putText(img,'count=%d'%count,(50,900),cv2.FONT_HERSHEY_COMPLEX,6,(0,0,255),10)
        cv2.imwrite(out_path+'/%d.jpg'%i, img)
    print('人脸检测完毕,共%d张'%(count))
    
    
def CombVideo(in_path, out_path, size):
    #将图片合成视频
    print('将图片合成视频中')
    #in_path为输入图像文件夹路径
    #out_path为输出视频文件路径
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(out_path,fourcc, 30.0, size)
    files = os.listdir(in_path)
    
    for i in range(len(files)):
        img = cv2.imread(in_path + '/%d.jpg' % i)
        #img = cv2.resize(img, size)
        out.write(img)

    out.release()
    print('图片合成视频完毕')

其它函数

#删除文件夹内的文件和文件夹
def del_file(path):
    list1 = os.listdir(path)
    for i in list1:
        c_path = os.path.join(path, i)
        if os.path.isdir(c_path):
            del_file(c_path)
        else:
            os.remove(c_path)
    print(path,"已被删除")

#清空文件夹(不存在则创建)
def clear_path(out_path):
    if(os.path.exists(out_path)): #如果该文件夹存在
        del_file(out_path) #删除文件夹内的文件和文件夹
        os.rmdir(out_path) #删除文件夹
        os.mkdir(out_path) #创建文件夹
    else:
        os.mkdir(out_path)
    print("已清空文件夹",out_path)
    

main函数

clear_path('/home/aistudio/images_initial')
clear_path('/home/aistudio/images_face')


if __name__ == '__main__':
    video_initial = '/home/aistudio/抖音素材.mp4'
    video_finish = '/home/aistudio/视频.mp4'
    images_initial = '/home/aistudio/images_initial'
    images_face = '/home/aistudio/images_face'

    CutVideo2Image(video_initial, images_initial)
    GetFace(images_initial, images_face)
    CombVideo(images_face, video_finish,(1920,1080))

不足之处

  1. 在人流过大时,会出现部分人群挡住另一部分的人群,导致一些图片小部分人未被检测到
  2. 当人流中若有小部分人移动速度过快(如慢跑)会导致计算的IOU过小,以致于让模型误判该图像的人与下一帧图像的人不是同一人
  3. 人脸检测后的视频丢失了音频

改进方案

  1. 在人脸检测的基础上再增加人脸识别的功能,则视频中出现的人则可以记录下来
  2. 采用多角度拍摄,可以避免拍摄的死角

解决丢失音频的问题

代码1(从原视频中提取音频)

会生成一个“抖音素材.mp4.mp3”的文件

!pip install ffmpeg moviepy

import moviepy.editor as mp
def extract_audio(videos_file_path):
    my_clip = mp.VideoFileClip(videos_file_path)
    my_clip.audio.write_audiofile(f'{videos_file_path}.mp3')

extract_audio(r'/home/aistudio/抖音素材.mp4')

代码2(从原视频中提取音频并)

from moviepy import *
from moviepy.editor import *
import glob

video_dirs = glob.glob('/home/aistudio/视频.mp4')
audio = AudioFileClip("/home/aistudio/抖音素材.mp4.mp3")# 提取音轨
for video_dir in video_dirs:
    video = VideoFileClip(video_dir)# 读入视频
    video = video.set_audio(audio)# 将音轨合成到视频中 
    video.write_videofile("/home/aistudio/将音轨合成到视频中/" + video_dir.split("/")[-1])# 输出

最终结果(代码2生成的视频)

视频3

你可能感兴趣的:(python,人工智能,计算机视觉)