前言
在现代科技的推动下,人工智能(AI)和机器学习(ML)逐渐成为各行各业的重要工具。百度AI开放平台作为全球领先的人工智能服务平台,为开发者提供了包括语音、图像、自然语言处理(NLP)等多项技术支持。本篇博客笔记旨在分享如何利用Python调用百度AI获取人体关键点数据,并使用OpenCV对结果进行可视化和简单分析。这不仅是对AI技术的实际应用,也是对机器学习领域的一次有益探索。
百度AI开放平台-全球领先的人工智能服务平台百度AI开放平台提供全球领先的语音、图像、NLP等多项人工智能技术,开放对话式人工智能系统、智能驾驶系统两大行业生态,共享AI领域最新的应用场景和解决方案,帮您提升竞争力,开创未来。https://ai.baidu.com/登陆成功后打开“开放能力”中的“人脸与人体”找到右边的“人体关键点识别”点击进入,
点击“立即使用”
点击应用列表”——创建应用:
安装好Python环境后打开IDLE(如果友友们有用过其他Python环境的编辑器并且熟练的话也是可以的)小北就以IDLE为例子,首先点击File,新建一个文件,然后保存到一个专门的文件
(举个栗子:2024复旦科创)
(.py文件命名为“try1")
测试一下:
print(“hello”)
在不管去使用哪一个网络服务的时候我们可以学习看一下它的技术文档:
下拉”技术文档“找到(如果遇到任何技术问题可以参考)Access Token获取https://ai.baidu.com/ai-doc/REFERENCE/Ck3dwjhhu
一、获取Access Token
在开始使用百度AI的API之前,需要先获取Access Token
,这是一种用于验证和授权的凭证。
获取Token的步骤
-
创建应用:首先需要登录百度AI开放平台,导航到“人脸与人体”板块,选择“人体关键点识别”并创建一个新应用。获取API Key和Secret Key。
-
获取Access Token:利用API Key和Secret Key,通过百度提供的认证接口获取Access Token。
复制代码进行调试:
import requests
import json
API_KEY = 'xxx'
SECRET_KEY = 'xxx'
def main():
url =f"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={API_KEY}&client_secret={SECRET_KEY}"
payload = ""
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
print(response.text)
if __name__ == '__main__':
main()
找自己刚刚创建的应用并输入自己的: PI_KEY ='xxx' 和SECRET_KEY ='xxx',
如果显示没有安装requests库:ModuleNotFoundError: No module named 'requests'
方法一:要使用清华大学的pip镜像源,你需要修改pip的配置文件或者在命令行中指定使用该镜像。
命令行临时使用:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple XXX
将xxx
替换为你想要安装的包名(requests)。
若出现CMD安装不成功,可以尝试:
方法二:打开IDLE安装文件夹的Scripts的终端再进行安装
成功会返还许多字典:
learn1.py(IDLE)
learn1.py(Pycharm)
其中最重要的是:(access_token)之后会用到验证我们的账户登录、凭证等等,友友们可以把它打印出来:(改写一下代码)
import requests
API_KEY = 'xxx'
SECRET_KEY = 'xxx'
def login():
url =(f"https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials"
f"&client_id={API_KEY}&client_secret={SECRET_KEY}")
payload = ""
headers = {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
response = requests.request("POST", url, headers=headers, data=payload)
result =response.json()
print(result)
token =result['access_token']
print('登录成功:', token)
return token
if __name__ == '__main__':
login()
结果显示:登录成功以及我们的access_token码
learn2.py(IDLE)
learn2.py(Pycharm)
代码解释:最后这一个If是程序的入口。来解释一下这个login(),这个login()也没有的话其实这个整个代码是不会执行的,因为小北是创建了一个登录功能的函数,但是我们并没有使用它,然后所以说我们需要去使用它的话,我们就是通过加小括号去执行这个函数内部的功能,然后至于小北为什么要使用这个If呢因为这个是他在设计出考虑的一个点,就是他考虑可能会有非常多的Python文件在我们单个文件中如果没有这一行,并不影响到于执行Python文件中的所有代码,出现如果是一个项目之后多个排线文件,那我只需要执行其中这一个文件的name它是那个就是说我执行的这个文件,那它才会去执行这个功能。如果说它是被其他文件影响到,所以友友们可以和小北一样习惯性地把Python程序作为入口的时候,都需要判断一下是否是就是主程序~
还有就是友友们在学习的时候可以多多参考————技术文档:人体分析 - 人体关键点识别 | 百度AI开放平台 (baidu.com)https://ai.baidu.com/ai-doc/BODY/0k3cpyxme?tn=39042058_34_oem_dg&ie=utf-8
二、调用百度AI获取人体关键点数据
使用获得的Access Token
,我们可以调用百度AI的“人体关键点识别”接口,对图像中的人体进行分析,提取人体的各个关键点信息。
找到技术文档:往下拉,找到Python请求代码示例复制粘贴,
新建一个learn3.py文件:
# encoding:utf-8
import requests
import base64
'''
人体关键点识别
'''
request_url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_analysis"
# 二进制方式打开图片文件
f = open('[本地文件]', 'rb')
img = base64.b64encode(f.read())
params = {"image":img}
access_token = '[调用鉴权接口获取的token]'
request_url = request_url + "?access_token=" + access_token
headers = {'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
if response:
print (response.json())
我们现在需要一张”全身照“,(此处引用一下杰哥帅照,如有侵权请及时与小北联系~)调用鉴权接口获取的token和打开图片地址(在同文件夹就可以直接用图片名称)
learn3.py(IDLE)
====== RESTART: D:\桌面\Python\人工智能和机器学习复旦大学计算机科学与技术实践工作站\2024复旦科创\learn3.py =====
{'person_num': 1, 'person_info': [{'body_parts': {'nose': {'score': 0.911842942237854, 'x': 396.302734375, 'y': 160.353515625}, 'right_knee': {'score': 0.8574072122573853, 'x': 305.091796875, 'y': 725.861328125}, 'left_hip': {'score': 0.8353385925292969, 'x': 451.029296875, 'y': 534.318359375}, 'right_ankle': {'score': 0.8325769901275635, 'x': 277.728515625, 'y': 908.283203125}, 'right_wrist': {'score': 0.8704789876937866, 'x': 305.091796875, 'y': 497.833984375}, 'left_eye': {'score': 0.8941200971603394, 'x': 414.544921875, 'y': 151.232421875}, 'left_mouth_corner': {'score': 0.9020979404449463, 'x': 405.423828125, 'y': 187.716796875}, 'right_elbow': {'score': 0.8880144953727722, 'x': 295.970703125, 'y': 397.501953125}, 'left_knee': {'score': 0.8518943190574646, 'x': 478.392578125, 'y': 734.982421875}, 'neck': {'score': 0.8677067160606384, 'x': 396.302734375, 'y': 233.322265625}, 'top_head': {'score': 0.8829088807106018, 'x': 396.302734375, 'y': 105.626953125}, 'right_ear': {'score': 0.8775261640548706, 'x': 359.818359375, 'y': 160.353515625}, 'left_ear': {'score': 0.8890771269798279, 'x': 441.908203125, 'y': 169.474609375}, 'left_elbow': {'score': 0.8575105667114258, 'x': 505.755859375, 'y': 397.501953125}, 'right_shoulder': {'score': 0.8700956702232361, 'x': 314.212890625, 'y': 278.927734375}, 'right_eye': {'score': 0.8894573450088501, 'x': 378.060546875, 'y': 151.232421875}, 'right_mouth_corner': {'score': 0.8865164518356323, 'x': 387.181640625, 'y': 187.716796875}, 'left_ankle': {'score': 0.8733648061752319, 'x': 505.755859375, 'y': 917.404296875}, 'right_hip': {'score': 0.8567600846290588, 'x': 350.697265625, 'y': 534.318359375}, 'left_wrist': {'score': 0.8995563387870789, 'x': 496.634765625, 'y': 497.833984375}, 'left_shoulder': {'score': 0.8760096430778503, 'x': 478.392578125, 'y': 278.927734375}}, 'location': {'score': 0.999074399471283, 'top': 81.2220458984375, 'left': 191.5921630859375, 'width': 364.416015625, 'height': 934.3431396484375}}], 'log_id': 1818249803046925474}
learn3.py(Pycharm)
D:\桌面\Python\code\pythonProject\venv\Scripts\python.exe D:\桌面\Python\人工智能和机器学习复旦大学计算机科学与技术实践工作站\2024复旦科创\learn3.py
{'person_num': 1, 'person_info': [{'body_parts': {'nose': {'score': 0.911842942237854, 'x': 396.302734375, 'y': 160.353515625}, 'right_knee': {'score': 0.8574072122573853, 'x': 305.091796875, 'y': 725.861328125}, 'left_hip': {'score': 0.8353385925292969, 'x': 451.029296875, 'y': 534.318359375}, 'right_ankle': {'score': 0.8325769901275635, 'x': 277.728515625, 'y': 908.283203125}, 'right_wrist': {'score': 0.8704789876937866, 'x': 305.091796875, 'y': 497.833984375}, 'left_eye': {'score': 0.8941200971603394, 'x': 414.544921875, 'y': 151.232421875}, 'left_mouth_corner': {'score': 0.9020979404449463, 'x': 405.423828125, 'y': 187.716796875}, 'right_elbow': {'score': 0.8880144953727722, 'x': 295.970703125, 'y': 397.501953125}, 'left_knee': {'score': 0.8518943190574646, 'x': 478.392578125, 'y': 734.982421875}, 'neck': {'score': 0.8677067160606384, 'x': 396.302734375, 'y': 233.322265625}, 'top_head': {'score': 0.8829088807106018, 'x': 396.302734375, 'y': 105.626953125}, 'right_ear': {'score': 0.8775261640548706, 'x': 359.818359375, 'y': 160.353515625}, 'left_ear': {'score': 0.8890771269798279, 'x': 441.908203125, 'y': 169.474609375}, 'left_elbow': {'score': 0.8575105667114258, 'x': 505.755859375, 'y': 397.501953125}, 'right_shoulder': {'score': 0.8700956702232361, 'x': 314.212890625, 'y': 278.927734375}, 'right_eye': {'score': 0.8894573450088501, 'x': 378.060546875, 'y': 151.232421875}, 'right_mouth_corner': {'score': 0.8865164518356323, 'x': 387.181640625, 'y': 187.716796875}, 'left_ankle': {'score': 0.8733648061752319, 'x': 505.755859375, 'y': 917.404296875}, 'right_hip': {'score': 0.8567600846290588, 'x': 350.697265625, 'y': 534.318359375}, 'left_wrist': {'score': 0.8995563387870789, 'x': 496.634765625, 'y': 497.833984375}, 'left_shoulder': {'score': 0.8760096430778503, 'x': 478.392578125, 'y': 278.927734375}}, 'location': {'score': 0.999074399471283, 'top': 81.2220458984375, 'left': 191.5921630859375, 'width': 364.416015625, 'height': 934.3431396484375}}], 'log_id': 1818248771820865185}
Process finished with exit code 0
如果出现错误码可以参考技术文档:
接下来修改代码,让代码输出的结果列表里有很多字典变得有格式:
learn3.py(Pycharm)
learn3.py(IDLE)
继续修改代码:(假如友友们要拿到nosed的x坐标参数)
if response: result = response.json() print(json.dumps(result, indent=4)) nose_x = result['person_info'][0]['body_parts']['nose']['x'] print('nose_x:', nose_x)
learn3.py(Pycharm)
learn3.py(IDLE)
三、使用OpenCV绘制人体关键点分析图
通过百度AI接口获取到的关键点信息,我们可以使用OpenCV库在原图上绘制这些关键点和它们之间的连接线。
安装opencv:
pip install opencv-python
注:若已经成功安装了Python 3.12.4,但是pip(Python的包管理工具)没有正确安装或配置导致无法使用pip来安装任何Python包,包括opencv-python,这时候
Python 3.4及以上版本提供了一个内置的模块ensurepip
,可以用来安装pip。
- 在命令提示符中,运行:
python -m ensurepip
- 安装完成后,再次尝试运行
pip --version
成功安装opencv:
继续改代码:(利用opencv绘制分析图)
# encoding:utf-8
import requests
import base64
import json
import cv2
access_token = 'xxx'
request_url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_analysis"
request_url += "?access_token=" + access_token
# Open image and encode it
with open('Jason.png', 'rb') as f:
img = base64.b64encode(f.read())
params = {"image": img}
headers = {'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
result = response.json()
print(json.dumps(result, indent=4))
body_parts = result['person_info'][0]['body_parts']
def draw_person(image, json_data):
ss = 0.4
lines = [
'left_ear,left_eye,nose,right_eye,right_ear',
'left_wrist,left_elbow,left_shoulder,neck,right_shoulder,right_elbow,right_wrist',
'nose,neck',
'left_hip,right_hip',
'left_shoulder,left_hip,left_knee,left_ankle',
'right_shoulder,right_hip,right_knee,right_ankle',
]
for info in json_data['person_info']:
bp = info['body_parts']
for line in lines:
ks = line.split(',')
for i in range(len(ks) - 1):
v1, v2 = bp[ks[i]], bp[ks[i + 1]]
c1, c2 = (int(v1['x']), int(v1['y'])), (int(v2['x']), int(v2['y']))
if v1['score'] > ss and v2['score'] > ss:
cv2.line(image, c1, c2, color=(255, 120, 120), thickness=3)
for k in bp:
v = bp[k]
if v['score'] > ss:
c = (int(v['x']), int(v['y']))
cv2.circle(image, c, radius=5, color=(255, 120, 120), thickness=-1)
return image
# Load the original image
image = cv2.imread('Jason.png')
image_plot = draw_person(image, result)
cv2.imwrite('image_plot.png', image_plot)
代码结果:
图片结果:
四、简单的头部姿态判断
通过对检测到的关键点进行分析,可以判断人物是否存在头部转向。例如,通过比较耳朵与肩膀之间的距离来判断头部是否有明显转向。
进一步改代码:(做简单判断——”转没转头“)
# encoding:utf-8
import requests
import base64
import json
import cv2
access_token = 'xxx'
request_url = "https://aip.baidubce.com/rest/2.0/image-classify/v1/body_analysis"
request_url += "?access_token=" + access_token
# Open image and encode it
with open('Jason.png', 'rb') as f:
img = base64.b64encode(f.read())
params = {"image": img}
headers = {'content-type': 'application/x-www-form-urlencoded'}
response = requests.post(request_url, data=params, headers=headers)
result = response.json()
print(json.dumps(result, indent=4))
body_parts = result['person_info'][0]['body_parts']
def draw_person(image, json_data):
ss = 0.4
lines = [
'left_ear,left_eye,nose,right_eye,right_ear',
'left_wrist,left_elbow,left_shoulder,neck,right_shoulder,right_elbow,right_wrist',
'nose,neck',
'left_hip,right_hip',
'left_shoulder,left_hip,left_knee,left_ankle',
'right_shoulder,right_hip,right_knee,right_ankle',
]
for info in json_data['person_info']:
bp = info['body_parts']
for line in lines:
ks = line.split(',')
for i in range(len(ks) - 1):
v1, v2 = bp[ks[i]], bp[ks[i + 1]]
c1, c2 = (int(v1['x']), int(v1['y'])), (int(v2['x']), int(v2['y']))
if v1['score'] > ss and v2['score'] > ss:
cv2.line(image, c1, c2, color=(255, 120, 120), thickness=3)
for k in bp:
v = bp[k]
if v['score'] > ss:
c = (int(v['x']), int(v['y']))
cv2.circle(image, c, radius=5, color=(255, 120, 120), thickness=-1)
return image
# Load the original image
image = cv2.imread('Jason.png')
image_plot = draw_person(image, result)
cv2.imwrite('image_plot.png', image_plot)
body_parts = result['person_info'][0]['body_parts']
left_ear_x = body_parts['left_ear']['x']
right_ear_x = body_parts['right_ear']['x']
left_shoulder_x= body_parts['left_shoulder' ]['x']
right_shoulder_x= body_parts['right_shoulder']['x']
print(left_ear_x,right_ear_x,left_shoulder_x, right_shoulder_x)
left_ear_score = body_parts['left_ear']['score' ]
right_ear_score = body_parts['right_ear']['score' ]
print(left_ear_score,right_ear_score)
if left_ear_score <0.3 or right_ear_score < 0.3:
print('关键点检测不全')
ear_distance =abs(left_ear_x-right_ear_x)
shoulder_distance = abs(left_shoulder_x - right_shoulder_x)
print(ear_distance,shoulder_distance)
if ear_distance < shoulder_distance / 3:
print('检测到转头了')
else:
print('检测到没有转头')
结果:(没有转头)
总结
本次实践小北展示了如何使用Python结合百度AI开放平台和OpenCV进行图像分析。通过获取Access Token
,调用百度的API,我们能够方便地获取到人体的关键点数据。进一步的,使用OpenCV可以将这些数据可视化,并通过简单的计算进行基本的姿态分析。这种应用不仅有助于理解计算机视觉技术,还为实际问题提供了一个有效的解决方案。
希望这篇博客笔记能对友友们在人工智能和机器学习方面的学习有所帮助~
步骤小结:
(1)
0. 复制代码并填入自己的百度AI应用的apikey和secretkey
1. 运行代码后 返回的字典中包含 'access_token' 表示成功了
2. 提示 No Modules Name 'requests' 则说明需要先安装 requests库 在cmd中执行 pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple 注意完整复制路径,-i后面内容不要遗漏
3. 如果执行 pip install 时提示,pip不是内部或外部命令 或 其他找不到pip的提示,则需要找到python安装路径 默认路径 通常为 C:\Users\用户名\AppData\Local\Programs\Python\Python3xx 打开后,进一步打开Scripts目录。右键或shift+右键,选择 在终端中打开 或 打开power shell窗口 然后执行 ./pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
4. 人体关键点的链接:https://ai.baidu.com/tech/body/pose 鉴权文档链接:https://ai.baidu.com/tech/body/pose
5. 如果出现 unknown client id,检查第0步,apikey是否正确
(2)
1. 查看人体关键点的接口文档 https://ai.baidu.com/ai-doc/BODY/0k3cpyxme#%E8%AF%B7%E6%B1%82%E8%AF%B4%E6%98%8E 复制其中的python示例代码。填入自己的access_token 和 图片路径。 完成后运行代码。
2. 看到输出了一个比较长的字典表示成功了。
3. 看到 {'error_code': 18, 'error_msg': 'Open api qps request limit reached'} 表示人体关键点接口没有领取免费次数 https://console.bce.baidu.com/ai/?fromai=1#/ai/body/overview/index 在这个链接点击 领取免费资源
4. 看到 {'error_code': 6, 'error_msg': 'No permission to access data'} 说明创建应用时没有勾选人体关键点,重新创建一个应用,勾选上人体关键点相关的功能
5. 看到 Invalid argument: 【图片路径】 说明图片路径填写有误,检查左右侧引号,斜杠用/不是\