一、事件描述
事件目的是为了在实时监控中发现、追踪目标人物。在进行具体项目实验前利用百度智能平台进行测试。
版本信息:python3.7 、opencv-python 4.1
二、过程解析
总览
整体结构包括:1.视频读入、2.人脸检测、3.人脸对比、4目标标注
1.视频读入
cap=cv.VideoCapture(0)#0为调用本机摄像头,调用其他摄像头序号应该对应。如果读取视频,改为视频地址
while(1):
ret, frame = cap.read()
if not ret:
print("打开摄像头失败")
break
"""对每一帧的其他操作..."""
c=cv.waitKey(20)
if c==27:#esc键的键盘输入值为27,该段意为当按下esc键时退出
cap.release()
cv.destroyAllWindows()
break
2.人脸检测
人脸检测利用的是opencv包中已经训练好的分类器haarcascade_frontalface_default,该分类器是保存在opencv包目录下的.xml文件,调用过程如下:
def face_detect_demo(image):
"""脸部检测"""
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
face_detector = cv.CascadeClassifier(r"C:\ProgramData\Anaconda3\Lib\site-packages\cv2\data\haarcascade_frontalface_default.xml")#haarcascade_frontalface_default.xml
faces = face_detector.detectMultiScale(gray, 1.1, 2)
return(faces)
输入:待检测的图片(已通过cv2.imread读取为数组格式)
输出:检测到的人脸位置
调用示例:
待测图片(C:\Users\Administrator\Desktop\lyf.jpg)
src=cv2.imread('C:\\Users\\Administrator\\Desktop\\lyf.jpg')
id_face=face_detect_demo(src)

输出结果:
array([[ 43, 88, 334, 334]], dtype=int32)
结果解释:43,88 为检测到的人脸左上角位置,334,334是检测到的人脸范围(宽度和高度),因此可以构造出人脸的四个顶点位置为:
| (43,88) | (43+334,88) |
|---|---|
| (43,88+334) | (43+334,88+334) |
显示结果
src=cv2.imread('C:\\Users\\Administrator\\Desktop\\刘亦菲.jpg')
cv2.rectangle(src, (43, 88,334,334), (0, 0, 255), 1)
#cv2.rectangle绘制矩形cv2.rectangle(原图,矩形位置大小,颜色,宽度)
cv2.imwrite('C:\\Users\\Administrator\\Desktop\\lyf_face.jpg',src)
cv2.waitKey(0)

3.人脸对比与目标标注
这里使用的是百度智能平台的人脸对比API,使用规则如下:
注意事项:
请求体格式化:Content-Type为application/json,通过json格式化请求体。
Base64编码:请求的图片需经过Base64编码,图片的base64编码指将图片数据编码成一串字符串,使用该字符串代替图像地址。您可以首先得到图片的二进制,然后用Base64格式编码即可。需要注意的是,图片的base64编码是不包含图片头的,如data:image/jpg;base64,
图片格式:现支持PNG、JPG、JPEG、BMP,不支持GIF图片
3.1图片转码
因为后期需要对两张图片对比,因此同时将两张图片转码
输入:
img1:待对比图片ID
img2:目标图片ID
import base64
import json
def get_img(img1,img2):
"""读取图片并转码"""
with open(img1, "rb") as f:
pic1 = f.read()
with open(img2, "rb") as f:
pic2 = f.read()
params = json.dumps([
{"image": str(base64.b64encode(pic1), "utf-8"), "image_type": "BASE64", "face_type": "LIVE", "quality_control": "LOW"},
{"image": str(base64.b64encode(pic2), "utf-8"), "image_type": "BASE64", "face_type": "LIVE", "quality_control": "LOW"}
])
return params
3.2获取token值,拼接api
import requests
api1 = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=lVfov6E1oaWZR9f4qIhd9Hjy&client_secret=Gubrc6RnMTdA3Eb8WumHIGrz4vHgCTdy"
api2 = "https://aip.baidubce.com/rest/2.0/face/v3/match?access_token="
def get_token():
response = requests.get(api1)
access_token = eval(response.text)['access_token']
api_url = api2 + access_token
return api_url
3.3请求API结果
输入:
img1: 待对比图片ID
img2:目标图片ID,命名方式为目标名称
输出:相似度大于80%,判定待测图片为目标人物,返回目标名称,否则返回’’
def than_img(img1, img2):
name=''
api_url = token
params = get_img(img1, img2)
try:
content = requests.post(api_url, params).text#获得原始
print('content:\n',content)
score = eval(content)['result']['score']#原始结果中提取相似度值
print('score:\n',score)
if score > 80:
name=img2.split('\\')[-1][:-4]
except:
Exception
return name
示例:
目标图片:C:\Users\Administrator\Desktop\刘亦菲.jpg
待测图片1:C:\Users\Administrator\Desktop\l_2.jpg
待测图片2:C:\Users\Administrator\Desktop\h_2.jpg

#对比图片'l_2'与图片'刘亦菲'
than_img('C:\\Users\\Administrator\\Desktop\\l_2.jpg','C:\\Users\\Administrator\\Desktop\\刘亦菲.jpg')
content:
{"error_code":0,
"error_msg":"SUCCESS",
"log_id":8984156510115,
"timestamp":1573535665,
"cached":0,
"result":{"score":94.68978119,
"face_list":[{"face_token":"9ab23808650d8bcf1a5a4bb143e16e7c"},
{"face_token":"4223d599df69a544553536a777b6f301"}
]
}
}
score:
94.68978119
Out[76]: '刘亦菲'
#对比图片'h_2'与图片'刘亦菲'
than_img('C:\\Users\\Administrator\\Desktop\\h_2.jpg','C:\\Users\\Administrator\\Desktop\\刘亦菲.jpg')
content:
{"error_code":0,
"error_msg":"SUCCESS",
"log_id":9945940012012,
"timestamp":1573535858,
"cached":0,
"result":{"score":11.75086212,
"face_list":[{"face_token":"ca6fd4e1f1ea82c0ad21962c6392ff3e"},
{"face_token":"4223d599df69a544553536a777b6f301"}
]
}
}
score:
11.75086212
Out[77]: ''
3.4 目标标注
opencv中图片指定位置直接标注中文会显示为‘?’如下:
src=cv.imread(r'C:\Users\Administrator\Desktop\fff\lyf_face.jpg')
cv.putText(src, '刘亦菲', (45,90), cv.FONT_HERSHEY_COMPLEX, 1, (0,255,0), 1, 4, 1)
cv.imwrite(r'C:\Users\Administrator\Desktop\fff\lyf_chinese.jpg',src)

利用PIL 模块构建图像中文显示函数
from PIL import Image, ImageDraw, ImageFont
def add_chinese(img, text, left, top, textColor, textSize):
"""图片中的中文显示"""
if (isinstance(img, np.ndarray)):
img = Image.fromarray(cv.cvtColor(img, cv.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img)
fontText = ImageFont.truetype(
"font/simsun.ttc", textSize, encoding="utf-8")
draw.text((left, top), text, textColor, font=fontText)
return cv.cvtColor(np.asarray(img), cv.COLOR_RGB2BGR)
示例:
src=cv.imread(r'C:\Users\Administrator\Desktop\fff\lyf_face.jpg')
res=add_chinese(src, '刘亦菲', 45, 90, (0,255,0), 20)
cv.imshow('l_4_face',res)
cv.waitKey(0)

三、 结束语
到这里,我们已经完成了对单一目标人物的识别和标记,通过调用摄像头或者读入视频文件,可以对目标人物进行实时标记跟踪,对于多目标的情况,仅仅需要添加多个目标人模即可,详细的介绍下一篇会补充。
本文介绍了如何使用Python3结合百度智能平台进行目标人物跟踪标记。通过视频读入、人脸检测、人脸对比和目标标注四个步骤,详细阐述了从图片Base64编码到调用人脸对比API,再到结果标注的全过程。

905

被折叠的 条评论
为什么被折叠?



