赞
踩
- #下载opencv-python4.6软件包,导入cv模块
- import cv2 as cv
- def face_detect_demo():
- gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 调用cvtcolor(待修改图片名字,修改颜色)
- # face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml') #调用分类器
- face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
- face=face_detect.detectMultiScale(gray_img)
- for x,y,w,h in face:
- cv.rectangle(img,(x,y),(x+w,y+h),color=(255,255,0),thickness=2) #调用rectangle(name,(左上角坐标,右下角坐标),颜色,厚度
- # cv.circle(resize_img,center=(x+w,y+h),radius=100,color=(255,0,0),thickness=1)) #调用circle(name,(圆心坐标,半径),颜色,厚度)
- cv.imshow('result',img) #调用imshow,显示图片
这是一个检测函数,思路是先给读取的图片进行灰度化,cv.cvtColor()是opencv中转换色彩空间的函数,img是待改变的图片像素矩阵,cv.COLOR_BGR2GRAY是opencv3以上中的转换灰度格式,结束后把灰度矩阵存入gray_img。
gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.CascadeClassifier()是调用分类器,里面的地址是opencv安装文件中的人脸分类器路径,该分类是基于haar和lbp的图形识别,调用该分类器并命名为face_detect
face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
接下来从整图的灰度矩阵里获取人脸部分的灰度矩阵,调用分类器中的detectMultiScale(),这个函数里有诸多参数可以调节识别的精度和次数等等,此处默认值,此函数返回的值是图片中人脸的起点坐标和长宽(x,y,w,h),存入face中
face=face_detect.detectMultiScale(gray_img)
遍历face里的(x,y,w,h), 然后调用cv.rectangle()绘制矩形
for x,y,w,h in face:
cv.rectangle(img,(x,y),(x+w,y+h),color=(255,255,0),thickness=2)
cv.imshow('result',img)
思路总结:先转换图片色彩空间,然后调用分类器中的人脸识别函数获取人脸范围坐标,然后按照图片的这个范围上绘制矩形,并imshow图片
- img=cv.imread('pic4.jpg') #读取一张图片命名为img
- while True: #循环
- # flag,frame=cap.read() #读取视频赋值给frame,用flag判断视频是否为空
- # if not flag:
- # break
- face_detect_demo()
- if ord('Q')==cv.waitKey(0):
- break
这里的思路是,先读取图片'pic4.jpg'存入img,此时如果print(img)则会在控制台输出像素矩阵,即每个点的rgb三元组构成的矩阵,注意图片路径,此处是和py项目在同一文件夹下的情况
然后进行图片检测,之所以用while true是为了给一个break条件。
img=cv.imread('pic4.jpg'),
while True:
face_detect_demo()
if ord('Q')==cv.waitKey(0):
break
只有face_detect_demo()和cv.waitKey(0)也可以
face_detect_demo()
cv.waitKey(0)
其中face_detect_demo()即是检测函数,需要另外定义。因GUI中imshow()不能单独使用,需要用cv.waitKey(0)控制图片显示时间:括号里为0表示静止当前帧,其他数字是需要等待的毫秒【此处的imshow()位于函数中的最后一步】。cv.waitKey()会返回等待期间键盘输入的字符的asc码,ord('Q')会返回Q的asc码。if两者值相等就break即按Q结束检测
思路总结:先读取图片,然后定义face_detect_demo()函数在人脸范围上添加矩形,最按Q结束检测
思路设计:与图片检测类似,先读取视频或者摄像头画面中的视频帧,将帧图片传入face_detect_demo()后绘制范围矩形,然后最按s把当前帧保存到指定文件夹并命名,按t结束程序
- def face_detect_demo(img):
- gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 调用cvtcolor(待修改图片名字,修改颜色)
- # face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml') #调用分类器
- face_detect=cv.CascadeClassifier('D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
- face=face_detect.detectMultiScale(gray_img) #重复检测5次 每次缩放倍数为1.1
- for x,y,w,h in face:
- cv.rectangle(img,(x,y),(x+w,y+h),color=(0,255,0),thickness=3) #调用rectangle(name,(左上角坐标,右下角坐标),颜色,厚度
- # cv.circle(resize_img,center=(x+w,y+h),radius=100,color=(255,0,0),thickness=1)) #调用circle(name,(圆心坐标,半径),颜色,厚度)
- cv.imshow('result',img) #调用imshow,显示图片
这是 face_detect_demo()函数,注意此时需要给它传入参数,因为视频帧的获取要在其他函数里进行,不可以是全局变量,而图片读取可以在最外层也即是可以定义为全局变量。
- cap=cv.VideoCapture(0) #调用摄像头
- #cap=cv.VideoCapture('video1.mp4') #这是读取对应视频
- flag=1
- num=1
- #判断摄像头是否为空
- while(cap.isOpened()):
- #读取当前帧frame,并传入函数中
- ret_flag,frame=cap.read()
- face_detect_demo(frame)
- #按s截取视频帧
-
- if ord('s')==cv.waitKey(2):
- #把视频帧写入指定地点并命名
- cv.imwrite("C:/Users/KXing/Desktop/facedetecet2/opencv/data/framepic/fpic2/"+str(num)+".name"+".jpg",frame)
- print("成功保存截图"+str(num)+".jpg")
- print("------------------")
- num+=1
- elif ord('t')==cv.waitKey(2):
- break
- #结束后释放内存
- cap.release()
- cv.destroyAllWindows()
这里是先调用摄像头截取视频帧,然后把当前帧传入face_detect_demo()函数进行人脸识别和标记,并按照指定名字写入指定文件夹。此时cv.waitKey(2)中不能为0,因为0为静止当前帧。
- import hashlib
- import os
- import tkinter.messagebox
- import urllib
- import urllib.request
- from datetime import datetime
-
- import cv2 as cv # 下载opencv-python4.6软件包,导入cv模块
- import numpy as np
- from PIL import Image
定义一个获取图片人脸信息的函数getImageAndLabels(path),imagePaths = [os.path.join(path, listname) for listname in os.listdir(path)]是将文件中图片的完整格式保存到信息数组里。然后再里面即可遍历每一张图片,把灰度矩阵保存在img_numpy 数组中【要是用numpy的convert('L')方法打开则要import numpy】。然后把img_numpy传入人脸识别模块返回图片人脸的坐标【xywh】。最后把该坐标对应的灰度矩阵和id返回
- def getImageAndLabels(path):
- facesSamples = [] # 定义一个数组存放脸部样本
- ids = [] # 这个数组用来存放脸部样本的id
- imagePaths = [os.path.join(path, listname) for listname in
- os.listdir(path)] # 这个数组用来存放图片信息,os.listdir(path)返回path中的文件名按照字母排序
- # os.path.join(path, f),将多个路径组合返回,这一步是把图片名和存放图片的路径组合成图片的路径
-
- # 调用opencv库的分类器检测人脸
- face_detector = cv.CascadeClassifier(
- 'D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
- # 打印数组imagePaths
- print('数据信息:', imagePaths)
- # 遍历列表中的图片
- for imagpath in imagePaths: # 这是在图片信息数组中遍历每一张图片
- # 用l法打开图片,此时每个像素点可表示为一个(0-255)的值,将得到的图片存入PIL_img
- PIL_img = Image.open(imagpath).convert('L')
- img_image = cv.imread(imagpath) # 如果用opencv打开则显示每个像素rgb数值组成的矩阵
- gray_img = cv.cvtColor(img_image, cv.COLOR_BGR2GRAY) # 用opencv调成灰色图,此时得到矩阵和img_numpy相同
- print(PIL_img)
- print('这是impath', imagpath)
- print('这是整图灰度矩阵opencv', gray_img)
- # PIL_img = cv2.resize(PIL_img, dsize=(400, 400))
- img_numpy = np.array(PIL_img, 'uint8') # np.array是一种创建数组的方法,前面是创建对象,后面是元素的类型,将PIL_img创建成为矩阵,存入img_numpy
- # 其中img_numpy即使所选图像的灰度值矩阵
- print('这是整图的灰度矩阵numpy和PIL', img_numpy)
-
- # 接下来从整图的灰度矩阵里获取图片人脸特征, face_detector.detectMultiScale是opencv的一个函数
- # image–待检测图片,一般为灰度图像加快检测速度;objects–被检测物体的矩形框向量组;scaleFactor–表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为1.1即每次搜索窗口依次扩大10%
- # minNeighbors–表示构成检测目标的相邻矩形的最小个数(默认为3个),flags–要么使用默认值,要么使用CV_HAAR_DO_CANNY_PRUNING,如果设置为
- # CV_HAAR_DO_CANNY_PRUNING,那么函数将会使用Canny边缘检测来排除边缘过多或过少的区域,minSize和maxSize用来限制得到的目标区域的范围。
-
- faces = face_detector.detectMultiScale(img_numpy)
- print('这是faces', faces) # 返回的faces为人脸的起点以及人脸矩形的长宽(x,y,w,h)
- # 获取每张图片的id和姓名,os.path.split是分离路径和和文件名函数,
- id = int(os.path.split(imagpath)[1].split('.')[
- 0]) # os.path.split(imagePath)[0],整个路径链表的表头,os.path.split(imagePath)[1]
- # os.path.split(imagePath)[1]split('.')[1],后面是指以’‘内划分链表,0为头,1为表尾
- h = []
- h = os.path.split(imagpath)[0].split('a')[1]
- print('this is path', imagpath)
- print('this is os.path', h)
- # 预防无面容照片
- # 在faces中遍历(x,y,w,h),把id加入数组,把人脸灰度矩阵加入数组
- for x, y, w, h in faces:
- ids.append(id)
- facesSamples.append(img_numpy[y:y + h, x:x + w])
- # 打印脸部特征和id
- print('fs:', facesSamples)
- print('id:', id)
- # print('fs:', facesSamples[id])
- # print('fs:', facesSamples)
- # print('脸部例子:',facesSamples[0])
- # print('身份信息:',ids[0])
- return facesSamples, ids
定义一个train()函数 ,if __name__ == '__main__':内的内容不会被其他py文件import。len(os.listdir(path))即是获取路径内文件名字的长度,若存在图片就调用getImageAndLabels()函数返回文件夹中图片的面部灰度矩阵和id。然后调用cv.face.LBPHFaceRecognizer_create(内有若干参数可选) 生成LBPH识别器实例模型recognizer,然后调用recognizer.train ( )函数训练,并将训练结果存入指定文件的yml文件里。再识别时会读取该文件数据。
- def train():
- #这个if可以让内部内容不被其他文件import
- if __name__ == '__main__':
- path = 'C:/Users/KXing/Desktop/facedetecet2/opencv/data/framepic/fpic/'
- if len(os.listdir(path)) > 0:
- # 调用函数,获取面部灰度矩阵和对应的id,存入faces和ids
- faces, ids = getImageAndLabels(path)
- # 调用cv.face.LBPHFaceRecognizer_create(),这是opencv中基于lbph算法的函数
- recognizer = cv.face.LBPHFaceRecognizer_create()
- print('this is rec', recognizer)
- # # recognizer.train(faces,names)#np.array(ids)
-
- # # 训练函数,传入面部矩阵数组和id数组
- recognizer.train(faces, np.array(ids))
- # 注意此处的faces是函数里的结果之一
- # # 保存文件,写入trainer.yml,此文件用来进行面部对比
- recognizer.write('C:/Users/KXing/Desktop/facedetecet2/opencv/data/trainer.yml')
开始识别:
- def name():
- path = 'C:/Users/KXing/Desktop/facedetecet2/opencv/data/framepic/fpic/'
- imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
- for imagePath in imagePaths:
- name = str(os.path.split(imagePath)[1].split('.', 2)[1])
- # print("aSDF", name)
- inames.append(name)
- def face_detect(img):
- # recogizer = cv.face.LBPHFaceRecognizer_create()
-
- gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) # 转换为灰度
- face_detector = cv.CascadeClassifier(
- 'D:/PCgames/GTA5/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
- face = face_detector.detectMultiScale(gray, 1.1, 5, cv.CASCADE_SCALE_IMAGE, (100, 100), (300, 300))
- # face=face_detector.detectMultiScale(gray)
- for x, y, w, h in face:
- cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 255), thickness=2)
- cv.circle(img, center=(x + w // 2, y + h // 2), radius=w // 2, color=(0, 255, 0), thickness=1)
- # 人脸识别
- ids, confidence = recognizer.predict(gray[y:y + h, x:x + w])
- # recognizer.predict()进行对比,返回id和confidence值,这个值用来衡量相似度
- # print('标签id:',ids,'置信评分:', confidence)
- if confidence > 80:
- global warningtime
- warningtime += 1
- if warningtime > 100:
- warning()
- warningtime = 0
- #这里是给画面矩形框添加识别结果的文本
- cv.putText(img, 'unkonw', (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
-
- else:
- cv.putText(img, str(inames[ids-2]) , (x + 10, y - 10), cv.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
- cv.imshow('detectresult', img)
- def train():
- if __name__ == '__main__':
- path = 'C:/Users/KXing/Desktop/facedetecet2/opencv/data/framepic/fpic/'
- if len(os.listdir(path)) > 0:
- # 调用函数,获取面部灰度矩阵和对应的id,存入faces和ids
- faces, ids = getImageAndLabels(path)
- # 调用cv.face.LBPHFaceRecognizer_create(),这是opencv中基于lbph算法的函数
- recognizer = cv.face.LBPHFaceRecognizer_create()
- print('this is rec', recognizer)
- # # recognizer.train(faces,names)#np.array(ids)
-
- # # 训练函数,传入面部矩阵数组和id数组
- recognizer.train(faces, np.array(ids))
- print('what is it ?', recognizer.train(faces, np.array(ids))) # 注意此处的faces是函数里的结果之一
- # # 保存文件,写入trainer.yml,此文件用来进行面部对比
- recognizer.write('C:/Users/KXing/Desktop/facedetecet2/opencv/data/trainer.yml')
- def detectfin():
- # pathyml = ('C:/Users/KXing/Desktop/facedetecet2/opencv/data/')
- # if len(os.listdir(pathyml)) > 0:
- flag = 1
- cap = cv.VideoCapture(0)
- name()
- while (cap.isOpened()):
- ret_flag, frame = cap.read()
- face_detect(frame)
- if ord(' ') == cv.waitKey(10):
- # flaglo = 0
- break
- cv.destroyAllWindows()
- cap.release()
- train()
- detectfin()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。