树莓派运行ROS实现face++人脸识别_请简要描述ros中实现人脸识别算法的主要操作流程。-程序员宅基地

技术标签: 机器人  树莓派运行ROS实现face++人脸识别  ros  人脸识别  

摘要


  Face++是北京旷视科技有限公司旗下的新型视觉服务平台,Face++平台通过提供云端API、离线SDK、以及面向用户的自主研发产品形式,将人脸识别技术广泛应用到互联网及移动应用场景中,非常重要的是它对于非商业用户提供免费试用帐号注册。对于开发者来说自己开发高效准确的算法并不是一件容易的事情,所以我们利用face++在线人脸识别平台,结合ros系统,搭建一套性价比比较高的门禁系统。通过这一过程能够更加深刻的理解嵌入式、ros以及云服务的广泛应用,为使用其他的云服务API接口打下良好的基础。
  将树莓派作为硬件载体,编写ros节点实现摄像头自动拍照,拍完后调用opencv进行人脸识别,如果存在人脸,便同时与本地权限人照片(拥有开门权限的人)一起上传至face++云平台,利用face++的API对两张照片进行识别和比较,从而返回消息提示是否为拥有开门权限的人,继电器做出相应动作。

准备工作


1、 在树莓派编译好ros系统。
2、 登入Face++的官方网站https://www.faceplusplus.com.cn/完成注册。
Face++ 注册界面
  创建API Key
创建API Key
  在应用管理-API Key界面就可以看到两个非常关键的参数,API Key和API Secret,在所有的POST调用当中均需要这两个参数。API Key
3、 调试摄像头
  (1) 插入USB摄像头,运行lsusb命令,查看是否被树莓派识别,一般插入第一个USB摄像头,会被加载为/dev/video0
  (2)安装拍照软件fswebcam

sudo apt-get install fswebcam

  (3)试拍一张看看

sudo fswebcam -d /dev/video0 -r 320x240 home/pi/0.jpg

4、 用命令行安装opencv相关库,在此之前请务必更新一下系统。

sudo apt-get update         #更新源
sudo apt-get upgrade         #更新系统
sudo apt-get install libopencv-dev
sudo apt-get install python-opencv

  (1)检查opencv是否安装成功,请尝试以下命令

$ python
>>> from cv2 import cv
>>> quit()

  没有收到导入错误(ImportError: No module named cv2),安装成功
  收到导入错误 ①opencv没有正确安装
           ②Python路径没有设置正确
     (2)OpenCV Python库存储在cv2.so文件中,运行命令验证是否已安装

$ locate cv2.so | grep python

     得到cv2.so的路径:/usr/lib/python2.7/dist-packages/cv2.so
5、 下载Face++的官网API的python的接口SDK,作为参考api调用。
     https://github.com/FacePlusPlus/python-sdk
API接口

实践流程


1、 摄像头拍照并调用opencv进行人脸识别

  (1)在主循环内间隔2秒调用摄像头拍照

import os				#导入python的os模块
import time				#导入python的time模块
command="fswebcam -d /dev/video0 -r 600*600 /home/pi/Desktop/photo.jpeg"
os.system(command)		#执行command所代表的指令,即拍照
time.sleep(2)			#等待2s

  但不能每次拍完照都与本地权限者照片比较一下,那样调用face++的API过于频繁,一来造成累积的网络延时过大,二来正式API应用以调用次数收费(试用API也不能无限次调用,且网络不稳定,容易出问题),因此每次拍完照都要识别一下照片中有没有人脸,如果有人脸再调用face++进行人脸比较。但同样的道理也不能用face++进行人脸识别,综上考虑,用opencv进行识别。

  (2)拍好照片,并调用opencv进行人脸识别

import numpy as np		#导入python的numpy模块并更名为np
import cv2				#导入python的opencv模块
#用opencv进行人脸识别,识别出有人脸才进行下一步人脸比较,否则一直拍照
face_cascade = cv2.CascadeClassifier(haarcascade_frontalface_alt2.xml)	#read image读取图像
img = cv2.imread(photo)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)		#Convert to grayscale转换为灰度图
faces = face_cascade.detectMultiScale(gray, 1.3, 5)

  若faces返回不为空,则识别出了人脸,接下来调用Face++人脸对比API,进行比对。

2、Face++人脸对比

通过参考Face++的官方SDK函数,结合官网的API说明,选定Detect API与Compare API实现所需功能。
API接口选择

#利用face++的detectAPI识别opencv识别到的人脸照片
detectresult=api.detect(api_key=API_KEY,api_secret=API_SECRET,image_file=File(photo))
print_result('Detect result:', detectresult)		#将结果输出到打印到命令行界面上
#调用face++的compareAPI将拍到的照片与两张本地权限者照片做比较,confidence表示拍到的照片与本地权限者照片是同一人的置信度
comparation=api.compare(api_key=API_KEY,api_secret=API_SECRET,image_file1=File(compare_photo),image_file2=File(photo))
confidence=comparation['confidence']

  (1)detectAPI主要是对识别的照片进行处理,并将结果通过调用print_result函数输出到命令行界面
  (2)compareAPI将拍到的照片与本地权限者照片做比较,将结果赋给confidence
  (3)confidence是对比结果置信度”,经过测试,本地权限者去拍照进行比对confidence值一般在90以上,而非本地权限者拍照比对结果在60以下,所以我们将判断的阀值定为70。

3、将Face++官网的SDK修改为ros的节点。

  (1)下面是修改为ros节点,SDK所需要的文件。
SDK需要的文件
  (2)创建face_node功能包。

$ cd ~/catkin_ws/src
$ catkin_create_pkg face_node std_msgs rospy roscpp
$ cd face_node
$ mkdir -p nodes launch photo

face_node包目录
    ①haarcascade_frontalface_alt2.xml下载

  人脸的Haar特征分类器就是一个XML文件,该文件中会描述人脸的Haar特征值。当然Haar特征的用途可不止可以用来描述人脸这一种,用来描述眼睛,嘴唇或是其它物体也是可以的,OpenCV有已经自带了人脸的Haar特征分类器。
下载地址:
在GitHub上找到opencv软件包,并在其中找到haarcascade_frontalface_alt2.xml
https://github.com/opencv/opencv/tree/master/data/haarcascades

    ②在photo的目录下放入本地权限者的照片
    ③ ros下python函数调用

  call.py需要调用到facepp.py文件,ros不能像python一样,直接用from facepp import API, File包含,并把facepp.py和call.py放在同一个目录,.py并不是可编译的脚本文件,为了适应ros统一的编译体系,使ros识别出你写的python node,所以也加入了Python的编译流程,主要目的就是让ros和系统找到你的python程序。

    1. 在face_node/src目录下建立face_node,将facepp.py复制到该目录下,并且创建_init_.py

$ cd ~/catkin_ws/src/face_node/src
$ mkdir face_node
$ touch _init_.py

    2. 在~/catkin_ws/src/face_node下建立setup.py文件, 另外还需要在CMakesLists.txt中加一行catkin_python_setup()来处理setup.py,这一行应该在find_package()之后。

$vim setup.py
#!/usr/bin/env python

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup

d = generate_distutils_setup(
    packages=['face_node'],
    package_dir={'': 'src'},
    )

setup(**d)
$vim CMakesLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(face_node)

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
)
catkin_package(DEPENDS)
catkin_python_setup()

可以参考以下两个博客修改:
https://blog.csdn.net/Cyril__Li/article/details/78979253
https://blog.csdn.net/light_jiang2016/article/details/55505627

  (3)将call.py修改为ros节点,下面将两个代码贴出来,可以参照修改。
call.py:

#-*- coding: utf-8 -*-


# 您需要先注册一个App,并将得到的API key和API secret写在这里。
# You need to register your App first, and enter you API key/secret.
API_KEY = "<YOUR_API_KEY>"
API_SECRET = "<YOUR_API_SECRETַ>"

# 网络图片的URL地址,调用demo前请填上内容
# The url of network picture, please fill in the contents before calling demo
face_one = 'http://bj-mc-prod-asset.oss-cn-beijing.aliyuncs.com/mc-official/images/face/demo-pic11.jpg'
# 本地图片的地址,调用demo前请填上内容
# Local picture location, please fill in the contents before calling demo
face_two = './demo.jpeg'
# 本地图片的地址,调用demo前请填上内容
# Local picture location, please fill in the contents before calling demo
face_search = './demo.jpeg'

#国际版的服务器地址
#the server of international version
api_server_international = 'https://api-us.faceplusplus.com/facepp/v3/'

# Import system libraries and define helper functions
# 导入系统库并定义辅助函数
from pprint import pformat


def print_result(hit, result):
    def encode(obj):
        if type(obj) is unicode:
            return obj.encode('utf-8')
        if type(obj) is dict:
            return {encode(v): encode(k) for (v, k) in obj.iteritems()}
        if type(obj) is list:
            return [encode(i) for i in obj]
        return obj
    print hit
    result = encode(result)
    print '\n'.join("  " + i for i in pformat(result, width=75).split('\n'))


# First import the API class from the SDK
# 首先,导入SDK中的API类
from facepp import API, File


#创建一个API对象,如果你是国际版用户,代码为:api = API(API_KEY, API_SECRET, srv=api_server_international)
#Create a API object, if you are an international user,code: api = API(API_KEY, API_SECRET, srv=api_server_international)
api = API(API_KEY, API_SECRET)

# 创建一个Faceset用来存储FaceToken
# create a Faceset to save FaceToken
ret = api.faceset.create(outer_id='test')
print_result("faceset create", ret)

# 对图片进行检测
# detect image
Face = {}
res = api.detect(image_url=face_one)
print_result("person_one", res)
Face['person_one'] = res["faces"][0]["face_token"]

res = api.detect(image_file=File(face_two))
print_result("person_two", res)
Face['person_two'] = res["faces"][0]["face_token"]

# 将得到的FaceToken存进Faceset里面
# save FaceToken in Faceset
api.faceset.addface(outer_id='test', face_tokens=Face.itervalues())

# 对待比对的图片进行检测,再搜索相似脸
# detect image and search same face
ret = api.detect(image_file=File(face_search))
print_result("detect", ret)
search_result = api.search(face_token=ret["faces"][0]["face_token"], outer_id='test')

# 输出结果
# print result
print_result('search', search_result)
print '=' * 60
for k, v in Face.iteritems():
    if v == search_result['results'][0]['face_token']:
        print 'The person with highest confidence:', k
        break


# 删除无用的人脸库
# delect faceset because it is no longer needed
api.faceset.delete(outer_id='test', check_empty=0)

# 恭喜!您已经完成了本教程,可以继续阅读我们的API文档并利用Face++ API开始写您自
# 己的App了!
# 旅途愉快 :)
# Congratulations! You have finished this tutorial, and you can continue
# reading our API document and start writing your own App using Face++ API!
# Enjoy :)

ros_faceselect.py:

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import rospy
from std_msgs.msg import Int32

import time		#导入python的time模块

import numpy as np  #导入python的numpy模块并更名为np
import cv2  #导入python的opencv模块

import os	#导入python的os模块
command="fswebcam -d /dev/video0 -r 600*600 /home/pi/Desktop/photo.jpeg"
photo = "/home/pi/Desktop/photo.jpeg"
compare_photo =  "/home/pi/catkin_ws/src/face_node/photo/photo_compare.jpeg"
hf_alt2_xml = "/home/pi/catkin_ws/src/face_node/haarcascade_frontalface_alt2.xml"

# 您需要先注册一个App,并将得到的API key和API secret写在这里。
# You need to register your App first, and enter you API key/secret.
API_KEY = "yJL5Mw02ZohjfElqG9BUXVDftC2AS8lw"
API_SECRET = "whXnDdVyiu0V6hL3lgWJfw0nFDiADLRX"
# Import system libraries and define helper functions
# 导入系统库并定义辅助函数
from pprint import pformat

def print_result(hit, result):
    def encode(obj):
        if type(obj) is unicode:
            return obj.encode('utf-8')
        if type(obj) is dict:
            return {encode(v): encode(k) for (v, k) in obj.iteritems()}
        if type(obj) is list:
            return [encode(i) for i in obj]
        return obj
    print hit
    result = encode(result)
    print '\n'.join("  " + i for i in pformat(result, width=75).split('\n'))
	
# First import the API class from the SDK
# 首先,导入SDK中的API类
from face_node.facepp import API, File
#创建一个API对象,如果你是国际版用户,代码为:api = API(API_KEY, API_SECRET, srv=api_server_international)
#Create a API object, if you are an international user,code: api = API(API_KEY, API_SECRET, srv=api_server_international)
api = API(API_KEY, API_SECRET)

rospy.init_node('opencv_face_node')

pub = rospy.Publisher('topic_face', Int32, queue_size=3)

#下面进入拍照循环
while not rospy.is_shutdown():
    os.system(command)#执行command所代表的指令,即拍照
    time.sleep(2)#等待2s
	#下面是用opencv进行人脸识别,识别出有人脸才进行下一步人脸比较,否则一直拍照
    face_cascade = cv2.CascadeClassifier(hf_alt2_xml)
    #read image读取图像
    img = cv2.imread(photo)
    #Convert to grayscale转换为灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    #detect face Multiscale 检测面尺度
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
  
    if faces!=():
        #利用face++的detectAPI识别刚刚拍摄的照片中的人脸,其实这句调试时能看到不少信息,方便些,可以省略
        detectresult=api.detect(api_key=API_KEY,api_secret=API_SECRET,image_file=File(photo))
        print_result('Detect result:', detectresult)		#将结果输出到打印到命令行界面上
		#调用face++的compareAPI将拍到的照片与本地权限者照片做比较,confidence表示拍到的照片与本地权限者照片是同一人的置信度
        comparation=api.compare(api_key=API_KEY,api_secret=API_SECRET,image_file1=File(compare_photo),image_file2=File(photo))
        confidence=comparation['confidence']
        if confidence >= 70:
            pub.publish(1)
        else:
            pub.publish(2)
    else:
        print "No one"

  代码下载地址https://github.com/qmros/ros_facenode

4、将Face++官网的SDK修改为ros的节点。

  (1)将继电器的正、负、in端分别接树莓派GPIO的5V引脚、地引脚与11引脚,在程序中导入python的GPIO库,写入简单的GPIO引脚高低电平控制程序,观察继电器的状态。

import RPi.GPIO as GPIO#导入库
GPIO.setmode(GPIO.BOARD)  # BOARD编号方式,基于插座引脚编号
GPIO.setup(11, GPIO.OUT)#将GPIO的11引脚设为输出
GPIO.output(11, 1)# 让GPIO的11引脚为高电平
GPIO.output(11, 0) # 让GPIO的11引脚为低电平

  (2)通过连接arduino来控制继电器,参考网址创客智造
   https://www.ncnynl.com/archives/201610/917.html

运行结果


$cd ~/catkin_ws/
$catkin_make

编译通过之后,插上USB摄像头,运行

$roslaunch face_node face_node.launch

屏幕输出打印的信息,但识别到有人,它会将结果发布到topic_face的主题,没人的时候打印No one,我们打开另外一个命令窗口运行

$rostopic echo /topic_face

查看/topic_face发布的消息,如果是1,说明拍照的人和本地权限者照片相同,2的话,说明不是本地权限者。

参考文献


[1] 在树莓派上实现face++人脸识别 - oBuZuoPiQi的博客
https://blog.csdn.net/obuzuopiqi/article/details/54428433

[2] 基于opencv与face++人脸识别+树莓派的门禁管理系统设计报告
http://www.51hei.com/bbs/dpj-103117-1.html

[3] ROS Package中的Python使用规范 - Cyril__Li的博客
https://blog.csdn.net/Cyril__Li/article/details/78979253

[4] ros 编译 Python 文件 - 蒋亮亮的博客
https://blog.csdn.net/light_jiang2016/article/details/55505627

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Qm13416479599/article/details/82932753

智能推荐

已知num为无符号十进制整数,请写一非递归算法,该算法输出num对应的r进制的各位数字。要求算法中用到的栈采用线性链表存储结构(1<r<10)。-程序员宅基地

文章浏览阅读74次。思路:num%r得到末位r进制数,num/r得到num去掉末位r进制数后的数字。得到的末位r进制数采用头插法插入链表中,更新num的值,循环计算,直到num为0,最后输出链表。//重置,s指针与头指针指向同一处。//更新num的值,至num为0退出循环。//末位r进制数存入s数据域中。//头插法插入链表中(无头结点)//定义头指针为空,s指针。= NULL) //s不为空,输出链表,栈先入后出。

开始报名!CW32开发者扶持计划正式进行,将助力中国的大学教育及人才培养_cw32开发者扶持计划申请-程序员宅基地

文章浏览阅读176次。武汉芯源半导体积极参与推动中国的大学教育改革以及注重电子行业的人才培养,建立以企业为主体、市场为导向、产学研深度融合的技术创新体系。2023年3月,武汉芯源半导体开发者扶持计划正式开始进行,以打造更为丰富的CW32生态社区。_cw32开发者扶持计划申请

希捷硬盘开机不识别,进入系统后自动扫描硬件以识别显示_st2000dm001不认盘-程序员宅基地

文章浏览阅读5.7k次。2014年底买的一块2TB希捷机械硬盘ST2000DM001-1ER164,用了两年更换了主板、CPU等,后来出现开机不识别的情况,具体表现为:关机后开机,找不到硬盘,就进入BIOS了,只要在BIOS状态下待机半分钟左右再重启,硬盘就会出现。进入系统后,重启(这个过程中主板对硬盘始终处于供电状态),也不会出现不识别硬盘的现象。就好像是硬盘或主板上某个电容坏了一样,刚开始给硬盘通电的N秒钟内电容未能..._st2000dm001不认盘

ADO.NET包含主要对象以及其作用-程序员宅基地

文章浏览阅读1.5k次。ADO.NET的数据源不单单是DB,也可以是XML、ExcelADO.NET连接数据源有两种交互模式:连接模式和断开模式两个对应的组件:数据提供程序(数据提供者)&DataSetSqlConnectionStringBuilder——连接字符串Connection对象用于开启程序和数据库之间的连接public SqlConnection c..._列举ado.net在操作数据库时,常用的对象及作用

Android 自定义对话框不能铺满全屏_android dialog宽度不铺满-程序员宅基地

文章浏览阅读113次。【代码】Android 自定义对话框不能铺满全屏。_android dialog宽度不铺满

Redis的主从集群与哨兵模式_redis的主从和哨兵集群-程序员宅基地

文章浏览阅读331次。Redis的主从集群与哨兵模式Redis的主从模式全量同步增量同步Redis主从同步策略流程redis主从部署环境哨兵模式原理哨兵模式概述哨兵模式的作用哨兵模式项目部署Redis的主从模式1、Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。2、为了分担读压力,Redis支持主从复制,保证主数据库的数据内容和从数据库的内容完全一致。3、Redis的主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。全量同步Redis全量复制一般发_redis的主从和哨兵集群

随便推点

mysql utf-8的作用_为什么不建议在MySQL中使用UTF-8-程序员宅基地

文章浏览阅读116次。作者:brightwang原文:https://www.jianshu.com/p/ab9aa8d4df7d最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后出现了一个离奇的错误:Incorrect string value: ‘😃 我用的是UTF-8编码的客户端,服务器也是UTF-8编码的,数据库也是,就连要保存的这个字符串“????..._mysql utf8的作用

MATLAB中对多张图片进行对比画图操作(包括RGB直方图、高斯+USM锐化后的图、HSV空间分量图及均衡化后的图)_matlab图像比较-程序员宅基地

文章浏览阅读278次。毕业这么久了,最近闲来准备把毕设过程中的代码整理公开一下,所有代码其实都是网上找的,但都是经过调试能跑通的,希望对需要的人有用。PS:里边很多注释不讲什么意思了,能看懂的自然能看懂。_matlab图像比较

16.libgdx根据配置文件生成布局(未完)-程序员宅基地

文章浏览阅读73次。思路:  screen分为普通和复杂两种,普通的功能大部分是页面跳转以及简单的crud数据,复杂的单独弄出来  跳转普通的screen,直接根据配置文件调整设置<layouts> <loyout screenId="0" bg="bg_start" name="start" defaultWinId="" bgm="" remark=""> ..._libgdx ui 布局

playwright-python 处理Text input、Checkboxs 和 radio buttons(三)_playwright checkbox-程序员宅基地

文章浏览阅读3k次,点赞2次,收藏13次。playwright-python 处理Text input和Checkboxs 和 radio buttonsText input输入框输入元素,直接用fill方法即可,支持 ,,[contenteditable] 和<label>这些标签,如下代码:page.fill('#name', 'Peter');# 日期输入page.fill('#date', '2020-02-02')# 时间输入page.fill('#time', '13-15')# 本地日期时间输入p_playwright checkbox

windows10使用Cygwin64安装PHP Swoole扩展_win10 php 安装swoole-程序员宅基地

文章浏览阅读596次,点赞5次,收藏6次。这是我看到最最详细的安装说明文章了,必须要给赞!学习了,也配置了,成功的一批!真不知道还有什么可补充的了,在此做个推广,喜欢的小伙伴,走起!_win10 php 安装swoole

angular2里引入flexible.js(rem的布局)_angular 使用rem-程序员宅基地

文章浏览阅读1k次。今天想实现页面的自适应,本来用的是栅格,但效果不理想,就想起了rem布局。以前使用rem布局,都是在原生html里,还没在框架里使用过,百度没百度出来,就自己琢磨,不知道方法规范不规范,反正成功了,操作如下:1、下载flexible.js2、引入到angular项目里3、根据自己的需要修改细节3.1、在flexible.js里修改每份的像素,3.2、引入cssrem插件,在设置里设..._angular 使用rem

推荐文章

热门文章

相关标签