牛!Python 也能实现图像姿态识别溺水行为了!
作者 | 李秋键
责编 | Carol
封图 | CSDN 下载自视觉中国
众所周知随着人工智能智能的发展,人工智能的落地项目也在变得越来越多,尤其是计算机视觉方面。
所以今天我们也是做一个计算机视觉方面的训练,用python来判断用户溺水行为,结合姿态识别和图像识别得到结果。其中包括姿态识别和图像分类。
首先图像分类是根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法。它是利用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,以代替人的视觉判读。
人体姿态是被主要分为基于计算机视角的识别和基于运动捕获技术的识别。基于计算机视觉的识别主要通过各种特征信息来对人体姿态动作进行识别, 比如视频图像序列、人体轮廓、多视角等。
这里整体程序的流程如下:
百度姿态识别图片并标注
CNN网络实现图像分类
根据分类结果可视化输出结果
最终输出的程序效果如下图:
一、实验前的准备
首先我们使用的python版本是3.6.5所用到的模块如下:
OpenCV:用来调用姿态识别接口绘制姿态识别结果
Baidu-aip:用来加载人体分析模块实现人体姿态识别
configparser :配置文件模块 读写配置文件
keras:用来训练和调用神经网络模型
素材准备
首先我们准备不同的图片放到一个特定文件夹下。图片分为三个类别,一个是溺水图片文件夹,一个是正常游泳图片文件夹,另一个是疑似溺水无法判定的图片文件夹。在这里我们把它放到data文件夹下,
其中疑似图片文件夹,如下图可见:
人体姿态识别搭建
1、姿态配置文件设定:
在这里为了足够的精度和方便调用,我们使用百度提供的人体分析接口。按照官方的规定设定了配置文件。主要就是设定人体各个肢体零件连接配置。
其对应的代码如下:
def draw_line(self, img):# nose ---> neckcv2.line(img, (int(self.dic['nose']['x']), int(self.dic['nose']['y'])),(int(self.dic['neck']['x']), int(self.dic['neck']['y'])), (0, 255, 0), 2)# neck --> left_shouldercv2.line(img, (int(self.dic['neck']['x']), int(self.dic['neck']['y'])),(int(self.dic['left_shoulder']['x']), int(self.dic['left_shoulder']['y'])), (0, 255, 0), 2)# neck --> right_shouldercv2.line(img, (int(self.dic['neck']['x']), int(self.dic['neck']['y'])),(int(self.dic['right_shoulder']['x']), int(self.dic['right_shoulder']['y'])), (0, 255, 0), 2)# left_shoulder --> left_elbowcv2.line(img, (int(self.dic['left_shoulder']['x']), int(self.dic['left_shoulder']['y'])),(int(self.dic['left_elbow']['x']), int(self.dic['left_elbow']['y'])), (0, 255, 0), 2)# left_elbow --> left_wristcv2.line(img, (int(self.dic['left_elbow']['x']), int(self.dic['left_elbow']['y'])),(int(self.dic['left_wrist']['x']), int(self.dic['left_wrist']['y'])), (0, 255, 0), 2)# right_shoulder --> right_elbowcv2.line(img, (int(self.dic['right_shoulder']['x']), int(self.dic['right_shoulder']['y'])),(int(self.dic['right_elbow']['x']), int(self.dic['right_elbow']['y'])), (0, 255, 0), 2)# right_elbow --> right_wristcv2.line(img, (int(self.dic['right_elbow']['x']), int(self.dic['right_elbow']['y'])),(int(self.dic['right_wrist']['x']), int(self.dic['right_wrist']['y'])), (0, 255, 0), 2)# neck --> left_hipcv2.line(img, (int(self.dic['neck']['x']), int(self.dic['neck']['y'])),(int(self.dic['left_hip']['x']), int(self.dic['left_hip']['y'])), (0, 255, 0), 2)# neck --> right_hipcv2.line(img, (int(self.dic['neck']['x']), int(self.dic['neck']['y'])),(int(self.dic['right_hip']['x']), int(self.dic['right_hip']['y'])), (0, 255, 0), 2)# left_hip --> left_kneecv2.line(img, (int(self.dic['left_hip']['x']), int(self.dic['left_hip']['y'])),(int(self.dic['left_knee']['x']), int(self.dic['left_knee']['y'])), (0, 255, 0), 2)# right_hip --> right_kneecv2.line(img, (int(self.dic['right_hip']['x']), int(self.dic['right_hip']['y'])),(int(self.dic['right_knee']['x']), int(self.dic['right_knee']['y'])), (0, 255, 0), 2)# left_knee --> left_anklecv2.line(img, (int(self.dic['left_knee']['x']), int(self.dic['left_knee']['y'])),(int(self.dic['left_ankle']['x']), int(self.dic['left_ankle']['y'])), (0, 255, 0), 2)# right_knee --> right_anklecv2.line(img, (int(self.dic['right_knee']['x']), int(self.dic['right_knee']['y'])),(int(self.dic['right_ankle']['x']), int(self.dic['right_ankle']['y'])), (0, 255, 0), 2)
2、姿态识别调用:
在设置好基本的配置文件后,我们通过百度申请的账号密匙等等调用接口即可。这里实现的效果如下:
对应代码如下:
class BaiDuAPI(object):# 特殊 构造函数 初始化函数def __init__(self):app_id ="20038443"api_key = "LhtctcN7hf6VtkHHcUGwXKfw"secret_key = "wzWACH340kE0FGhvA9CqWsiRwltf5wFE"self.client = AipBodyAnalysis(app_id, api_key, secret_key)""" 读取图片 """def get_file_content(self, photoPath):with open(photoPath, 'rb') as fp:return fp.read()""" 主函数 """def file_main(self, photoPath):img = self.get_file_content('{}'.format(photoPath))""" 调用人体关键点识别 """# 此处只能对一个人进行关键点识别# 也就是说一个图片如果有好多人的话,只能标出一个人的关节特征# 此处可以做修改,即进行把一张图所有人的关节特征都表达出来# ------# print(self.client.bodyAnalysis(img))result = self.client.bodyAnalysis(img)['person_info'][0]['body_parts']jo = joint.Joint(result)jo.xunhun(photoPath)# print(result )
CNN识别模型的建立
1、神经网络的搭建:
这里设定的CNN模型挺常见的模型相似,通过设定卷积核、步长、训练批次等等搭建网络。
代码如下:
model = Sequential() #创建一个神经网络对象
#添加一个卷积层,传入固定宽高三通道的图片,以32种不同的卷积核构建32张特征图,
# 卷积核大小为3*3,构建特征图比例和原图相同,激活函数为relu函数。
model.add(Conv2D(input_shape=(IMG_W,IMG_H,3),filters=32,kernel_size=3,padding='same',activation='relu'))
#再次构建一个卷积层
model.add(Conv2D(filters=32,kernel_size=3,padding='same',activation='relu'))
#构建一个池化层,提取特征,池化层的池化窗口为2*2,步长为2。
model.add(MaxPool2D(pool_size=2,strides=2))
#继续构建卷积层和池化层,区别是卷积核数量为64。
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=64,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2,strides=2))
#继续构建卷积层和池化层,区别是卷积核数量为128。
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(Conv2D(filters=128,kernel_size=3,padding='same',activation='relu'))
model.add(MaxPool2D(pool_size=2, strides=2))
model.add(Flatten()) #数据扁平化
model.add(Dense(128,activation='relu')) #构建一个具有128个神经元的全连接层
model.add(Dense(64,activation='relu')) #构建一个具有64个神经元的全连接层
model.add(Dropout(DROPOUT_RATE)) #加入dropout,防止过拟合。
model.add(Dense(CLASS,activation='softmax')) #输出层,一共3个神经元,对应3个分类
adam = Adam(lr=LEARNING_RATE) #创建Adam优化器
model.compile(optimizer=adam,loss='categorical_crossentropy',metrics=['accuracy']) #使用交叉熵代价函数,adam优化器优化模型,并提取准确率
train_generator = train_datagen.flow_from_directory( #设置训练集迭代器TRAIN_PATH, #训练集存放路径target_size=(IMG_W,IMG_H), #训练集图片尺寸batch_size=BATCH_SIZE #训练集批次)
test_generator = test_datagen.flow_from_directory( #设置测试集迭代器TEST_PATH, #测试集存放路径target_size=(IMG_W,IMG_H), #测试集图片尺寸batch_size=BATCH_SIZE, #测试集批次)
print(train_generator.class_indices) #打印迭代器分类
try:model = load_model('{}.h5'.format(SAVE_PATH)) #尝试读取训练好的模型,再次训练print('model upload,start training!')
except:print('not find model,start training') #如果没有训练过的模型,则从头开始训练
model.fit_generator( #模型拟合train_generator, #训练集迭代器steps_per_epoch=len(train_generator), #每个周期需要迭代多少步epochs=EPOCHS, #迭代周期validation_data=test_generator, #测试集迭代器validation_steps=len(test_generator) #测试集迭代多少步)
model.save('{}.h5'.format(SAVE_PATH)) #保存模型
print('finish {} epochs!'.format(EPOCHS))
2、模型的调用:
同训练的步骤相似,这里我们首先也是是通过调用百度姿态识别进行图片人体分析,然后分类预测结果。
代码如下:
# 载入模型
model = load_model('model_selector.h5')
label = np.array(['正常','疑似','溺水'])
def image_change(image):image = image.resize((224, 224))image = img_to_array(image)image = image / 255image = np.expand_dims(image, 0)return image
class BaiDuAPI(object):# 特殊 构造函数 初始化函数def __init__(self):app_id ="20038443"api_key = "LhtctcN7hf6VtkHHcUGwXKfw"secret_key = "wzWACH340kE0FGhvA9CqWsiRwltf5wFE"self.client = AipBodyAnalysis(app_id, api_key, secret_key)""" 读取图片 """def get_file_content(self, photoPath):with open(photoPath, 'rb') as fp:return fp.read()""" 主函数 """def file_main(self, photoPath):img = self.get_file_content('{}'.format(photoPath))""" 调用人体关键点识别 """# 此处只能对一个人进行关键点识别# 也就是说一个图片如果有好多人的话,只能标出一个人的关节特征# 此处可以做修改,即进行把一张图所有人的关节特征都表达出来# ------# print(self.client.bodyAnalysis(img))result = self.client.bodyAnalysis(img)['person_info'][0]['body_parts']jo = joint.Joint(result)jo.xunhun(photoPath)# print(result )
#预测2.jpg的结果
try:image = load_img("2.jpg")#plt.imshow(image)image = image_change(image)baiduapi = BaiDuAPI()baiduapi.file_main('2.jpg')img=cv2.imread("temp.jpg")img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))myfont = ImageFont.truetype(r'C:/Windows/Fonts/simfang.ttf', 40)draw = ImageDraw.Draw(img_PIL)draw.text((300, 10), label[model.predict_classes(image)][0], font=myfont, fill=(200, 100, 0))img_OpenCV = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)cv2.imshow('frame', img_OpenCV)cv2.waitKey(0)
except:pass
#预测1.jpg的结果
try:image = load_img("1.jpg")#plt.imshow(image)image = image_change(image)baiduapi = BaiDuAPI()baiduapi.file_main('1.jpg')img=cv2.imread("temp.jpg")img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))myfont = ImageFont.truetype(r'C:/Windows/Fonts/simfang.ttf', 40)draw = ImageDraw.Draw(img_PIL)draw.text((300, 10), label[model.predict_classes(image)][0], font=myfont, fill=(200, 100, 0))img_OpenCV = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)cv2.imshow('frame', img_OpenCV)cv2.waitKey(0)
except:pass
#预测3.jpg的结果
try:image = load_img("3.jpg")#plt.imshow(image)image = image_change(image)baiduapi = BaiDuAPI()baiduapi.file_main('3.jpg')img=cv2.imread("temp.jpg")img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))myfont = ImageFont.truetype(r'C:/Windows/Fonts/simfang.ttf', 40)draw = ImageDraw.Draw(img_PIL)draw.text((300, 10), label[model.predict_classes(image)][0], font=myfont, fill=(200, 100, 0))img_OpenCV = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)cv2.imshow('frame', img_OpenCV)cv2.waitKey(0)
except:pass
最终运行程序结果如下:
源码地址:
https://pan.baidu.com/s/1qMwPCTTyqDWPXoPj1XnKgA
提取码:us2k
作者简介:
李秋键,CSDN博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等等。
推荐阅读
高文、张钹、杨强隔空论道:AI精度与隐私的博弈
90行Python代码,让张小龙的微信地球转起来
独家揭秘!抖音爆款漫画变身特效的背后技术
字节跳动 8 年,抖音、头条的技术能力开发者都可以用起来了!
从微信「拍一拍」,我想到了那些神奇的一行代码功能
4 张图读懂比特币矿商8年兴衰与变迁
你点的每个“在看”,我都认真当成了AI
相关文章:

Asp.net中多项目共享Session
1. 建立一个空白解决方案blank solution,如:d:/MyProject/MyProject.sln 2. 在d:/MyProject下建一个Web Application的根目录d:/MyProject/WebMis并设为http://localhost/WebMis的虚拟目录 3. 在WebMis目录下根据模块分别新建目录,如…

JQuery模板插件jquery.tmpl-动态ajax扩展
在上一篇JQuery模板插件-jquery.tmpl中介绍了这款插件。有时我们需要去动态的ajax去加载模板,或者数据,根据url参数或者其他信息加载不同的模板,数据。在我的某个项目中有这个需求,所以特地写成jquery工具函数,加入了本…

《JAVA-枚举》
2019独角兽企业重金招聘Python工程师标准>>> 枚举:枚举在C/C/c#/java中,是一个被命名的整型常数的集合,枚举在日常生活中很常见。 表示星期的SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,就是一个简单的例子 既然讲了枚…

在ASP.NET中使用WINDOWS模式登录SQL数据库
作者:未知 请作者速与本人联系经常发现有用户使用WINDOWS模式登录SQL SERVER,结果失败,提示: 用户 KEKC/ASPNET 登录失败。 说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有…

时髦而精巧的Iphone墙纸收集
Iphone5如此的流行,我觉得我们有必要为我们的读者收集一套时尚的iphone墙纸。 知道设计和开发社区是多么喜欢装饰他们的移动设备,我们收集了各大社区最好的iphone墙纸,帮助你更好的装饰你的iphone设备。 因为有如此多的墙纸设计,我…
谷歌排名第一的编程语言,死磕它这两点,小白也能学的会!不信你看!
谷歌排名第一的编程语言时什么?毫无疑问:肯定是 Python。也难怪,作为大数据时代和人工智能时代的必备语言,Python 的优点太多了,语言简洁、易学、开发效率高、可移植性强......另外,更牛的地方是目前最热门…

UVA11059 Maximum Product
问题链接:UVA11059 Maximum Product。基础级练习题,用C语言编写程序。 题意简述:输入n个整数序列,有正有负,求这个序列中最大连续累乘的子序列,其最大的值为多少。如果结果为负数,则输出0。 问题…

.NET代码的保护
1没有绝对的保护 加密和破解都相对的 2用vs2002/2003/开发的代码 删除.cs/.vb文件只留 .dll和.aspx可以达到加密若要加密.aspx 可以把.aspx代码写入.csvs2005 beta1可以连.aspx都打包 3但是 dll还可以被反编译 所以高级的是加入混淆器不过这样也不是绝对的还是可以反编译混淆…

走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串
对大量数据进行查询时,可以应用到索引技术。索引是一种特殊类型的数据库对象,它保存着数据表中一列或者多列的排序结果,有效地使用索引可以提高数据的查询效率。大家面试初级、中级或者高级程序员的时候应该大部分都会被问到这样一些问题,你了…
“编程能力差的程序员,90%会输在这点上”谷歌AI专家:其实都是瞎努力
最近几年,我看过市面上很多 Python和人工智能的教程和书籍,它们大都这样讲:先从 Python 人工智能的历史讲起开始,再介绍的基本语法规则,Python 的 list, dict, tuple 等数据结构,最后学习机器学习、深度学习…

查询表空间使用情况
2019独角兽企业重金招聘Python工程师标准>>> SELECT a.tablespace_name "表空间名", total "表空间大小", free "表空间剩余大小", (total - free) "表空间使用大小", total / (1024 * 1024 * 1024) "表空间大小(…
一只端午节鸭蛋粽子的背后:AI 与农业
作者 | 硬核云顶宫责编 | Carol封图 | CSDN 下载自视觉中国今年的端午节,食品界的营销鬼才五芳斋又发了最新广告——《朋友们蘸起来》,这则视频通过一种科幻大片的风格展示了农业与科技的完美结合,可以说在一只端午节粽子背后有AI的养猪、种的…

一些实用的 Javascript 代码
οncοntextmenu"window.event.returnvaluefalse" 将彻底屏蔽鼠标右键<table border οncοntextmenureturn(false)><td>no</table> 可用于Table <body onselectstart"return false"> 取消选取、防止复制 οnpaste"return fa…

围观文件穿越操作
1. 打开文件用IoCreateFile,其他比较好发irp的(比如删除操作)走FSD irp 删除文件部分处理了删除正在运行的exe镜像部分,做法是方法是IAT Hook MmFlushImageSection 但是这样对于独占文件依旧不能处理,只好等到关机…

图论 - 欧拉回路
Description 欧拉回路是指不令笔离开纸面,可画过图中每条边仅一次,且可以回到起点的一条回路。现给定一个图,问是否存在欧拉回路?Input 测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是节点数N (…

学习 Linux,101: 引导系统
2019独角兽企业重金招聘Python工程师标准>>> 系列文章: http://www.ibm.com/developerworks/cn/views/linux/libraryview.jsp?search_by%E5%AD%A6%E4%B9%A0linux101 从 BIOS 到运行 Linux 系统 引导顺序 在我们深入了解启动加载程序(比如 LI…

用Enter键取代tab键
1. this.TextBox1.Attributes.Add("OnKeyPress","<script>if keycode13 keycode9; return false;</script>");2. <input typetext οnkeydοwn"if (event.keyCode 13) event.keyCode 9;">
程序员:我受够了!不想再在小厂里干Java了!
你是否熟悉这样的情形:每天10点到公司,打开电脑:10个小时的增删改查,搬砖写代码的一天就这样开始了。刚毕业时候的你踌躇满志,按照自己的原定计划,这时候应该混到了阿里P6。可现在在小厂苦苦挣扎࿰…

iOS中UISearchBar(搜索框)使用总结
2019独角兽企业重金招聘Python工程师标准>>> iOS中UISearchBar(搜索框)使用总结 初始化:UISearchBar继承于UIView,我们可以像创建View那样创建searchBar UISearchBar * bar [[UISearchBar alloc]initWithFrame:CGRectMake(20, 100, 250, 40)…

Linux常用性能检测命令
一、uptime Uptime命令的显示结果包括服务器已经运行了多长时间,有多少登陆用户和对服务器性能的总体评估(load average)。load average值分别记录了上个1分钟,5分钟和15分钟间隔的负载情况,load average不是一个百…

怎样把DataGrid存放在ViewState中的无用数据卡掉
作者:无间道的博客http://www.cnblogs.com/wangsaokui/articles/10031.html 怎样把 DataGrid 存放在 ViewState 中的无用数据(有时候确实如此)卡掉,大家知道,一般而言DataGrid在ViewState中会存放表格中的所有数据,这样会导致View…
深度学习先驱 Yann LeCun 被骂到封推!AI 偏见真该甩锅数据集?
整理 | 夕颜出品 | CSDN(ID:CSDNnews)最近,人工智能领域又发生了一次热热闹闹的争论,随后演变成一场偏离轨道的争吵,目前以 Yann 道歉封推暂告一段落......争论来龙去脉这次争论的主角是图灵奖得主、人工智能标杆性人物…

JS加强学习-DOM学习01
JavaScript由三个部分组成:ECMAScript、DOM、BOM。前面已经学习了ECMAScript中的基础内容,现在可以开始学习DOM部分了,在DOM中更多的是实际效果的展现。 1. DOM定义 DOM:document object model 文档对象模型 它是将整个页面文档封…

android 游戏引擎libgdx demo cuboc分析
开始学习android游戏开发也有一段时间了,挑选libgdx这个游戏引擎来进行学习和开发。Libgdx是一款支持2D与3D游戏开发的游戏类库,并且它是夸平台的。例如你可以在windos下开发,同样的代码也可以运行在android上。 刚开始学习这个游戏引擎可能会感觉无从下手&#…
倒计时1天 | 张钹院士领衔,AI开发者大会20大论坛全攻略!
2020年7月3—4日,由 CSDN 主办的第三届 AI 开发者大会(AI ProCon 2020)(大会官网:https://aiprocon.csdn.net/)将以线上直播的形式与大家相见。本次大会历时2天,一次性设立6大主题、20大精彩分论…

在页面中导入文件
1. <% Response.WriteFile ("Yourfile.inc") %> 2. Server.Execute("Yourfile.inc")

How Tomcat works — 四、tomcat启动(3)
上一节说到StandardService负责启动其子组件:container和connector,不过注意,是有先后顺序的,先启动container,再启动connector,这一节先来看看container。 目录 Pipeline和VavleStandardEngine类和Standar…

DataList分页
<% Page Language"C#" %> <% Import Namespace"System.Data" %> <% Import Namespace"System.Data.OleDb" %> <Script Language"C#" Runat"Server"> /* Create By 飞刀 http://www.aspcn.com 20…

【中文】Joomla1.7扩展介绍之Googlemaps Plugin
Googlemaps Plugin 插件分类:Maps 支持版本:1.5 /1.6 /1.7 关注程度:【最流行的】 所属类型:插件、多语种 可以在 Joomla 1.5.x (native), 1.6.x and 1.7.x. 的内容条目、模块或者组件中显示一个(或多个)…
一文读懂:GoogleNet的Inception从v1到v4的演变
来源 | 机器学习炼丹术GoogleNet和VGG是ImageNet挑战赛中的第一名和第二名。共同特点就是两个网络的层次都更深了。但是:VGG继承了LeNet和AlexNet的一些框架结构而GoogleNet则做了更大胆的尝试,虽然深度有22层,但是参数却是Alexnet的1/12.而V…