golang微信公众平台之人脸识别
golang微信公众平台之人脸识别
好吧,其实整个都是建立在face++的基础上的,没有任何技术含量,我只是个勤劳的搬运工。
微信公众平台,怎么说呢,还是传统的一问一答的形式,你发个信息过来,我收到了处理下,再给你回馈一条信息,就是这么简单。
简单的你来我往
先说信息互传的问题,微信公众平台是post过来一个xml,服务器端打包一个xml发回去。
从最简单的,直接把用户信息返回去搞起吧。
文本消息<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>1348831860</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[this is a test]]></Content> <MsgId>1234567890123456</MsgId> </xml>
参数 描述 ToUserName 开发者 微信号 FromUserName 发送方帐号(一个OpenID) CreateTime 消息创建时间 (整型) MsgType text Content 文本消息内容 MsgId 消息id,64位整型
相应的数据结构也就自然出来了:
type Request struct {
ToUserName string
FromUserName string
CreateTime time.Duration
MsgType string
Content string
MsgId int
}
将输入的xml解码:
func decodeRequest(data [] byte )(req * Request,err error){
req =& Request{}
err = xml.Unmarshal(data,req)
return
}
虽然微信服务器是用post方式传递的数据,不过实际还通过url传递过来了三个参数:signature,timestamp,nonce.
这三个参数可以验证消息是否微信服务器发送过来的。
取post过来的数据:
func Action(w http.ResponseWriter,r * http.Request){
postedMsg,err: = ioutil.ReadAll(r.Body)
if err!= nil{
log.Fatal(err)
}
r.Body.Close()
msg,err: = decodeRequest(postedMsg)
...
}
接下来就是回复信息
回复文本消息<xml> <ToUserName><![CDATA[toUser]]></ToUserName> <FromUserName><![CDATA[fromUser]]></FromUserName> <CreateTime>12345678</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[content]]></Content> <FuncFlag>0</FuncFlag> </xml>
参数
描述 ToUserName 接收方帐号(收到的OpenID)FromUserName
开发者微信号 CreateTime 消息创建时间MsgType
text Content 回复的消息内容,长度不超过2048字节 FuncFlag 位0x0001被标志时,星标刚收到的消息简单封装下:
type Response struct {
XMLName xml.Name `xml: " xml " `
ToUserName string
FromUserName string
CreateTime time.Duration
MsgType string
Content string
FuncFlag int
}
func encodeResponse(resp Response)(data [] byte ,err error){
resp.CreateTime = time.Second
data,err = xml.Marshal(resp)
return
}
将数据发送回去的代码:
var resp Response resp.ToUserName = msg.FromUserName resp.FromUserName = msg.ToUserName resp.MsgType = " text " resp.Content = msg.Content resp.FuncFlag = 0 respData,err: = encodeResponse(resp) fmt.Fprintf(w, string (respData))
人脸识别
这个怎么说,就是用户通过微信发送照片,照片是存到微信服务器的,微信给我发一个图片url,我再把这个url转给face++,face++将分析结果给我发回来,我再把这些数据简单处理下,反馈给微信用户(当然,中间还隔了层微信服务器)。
整个过程中,我所做的就是简单的json数据处理,什么高端的图像处理什么的都跟我不沾边,哈哈~
首先当然是到 http://cn.faceplusplus测试数据/ 注册,获取API_SECRET、API_KEY。
而后推荐看文档, http://cn.faceplusplus测试数据/dev/getting-started/api2info/ ,当然直接跟着我来一遍也行。
先来个人脸检测吧,检测出性别、年龄、种族。
看了示例文档后,发现detect调用后返回的json的结构表示出来大概是这样:
type Faceslice struct {
Face [] struct {
Attribute struct {
Age struct {
Range float64
Value float64
}
Gender struct {
Confidence float64
Value string
}
Race struct {
Confidence float64
Vaule string
}
}
Face_id string
Position struct {
Center struct {
X float64
Y float64
}
Eye_left struct {
X float64
Y float64
}
Eye_right struct {
X float64
Y float64
}
Height float64
Mouth_left struct {
X float64
Y float64
}
Mouth_right struct {
X float64
Y float64
}
Nose struct {
X float64
Y float64
}
Width float64
}
Tag string
}
Img_height int
Img_id string
Img_width int
Session_id string
url string
}
解析json数据:
func DecodeDetect(data [] byte ) Faceslice{
var f Faceslice
json.Unmarshal(data, & f)
return f
}
接着还是来写个get函数吧:
func get (url string )(b [] byte ,err error){
res,e: = http.Get(url)
if e!= nil{
err = e
return
}
data,e: = ioutil.ReadAll(res.Body)
if e!= nil{
err = e
return
}
res.Body.Close()
return data,nil
}
调用face++接口并返回相应的数据:
const apiurl= " https://apicn.faceplusplus测试数据 "
func DetectionDetect(picurl string )detection.Faceslice{
url: =apiurl+ " /v2/detection/detect?url= " +picurl+ " &api_secret= " +apisecret+ " &api_key= " + apikey
tmp,_: = get (url)
return detection.DecodeDetect(tmp)
}
刚刚上面的示例只是简单考虑了文本信息,现在要传递的是图片信息,所以做个简单的修改:
type Request struct {
ToUserName string
FromUserName string
CreateTime time.Duration
MsgType string
Content string
PicUrl string
MsgId int
}
Action函数里也该有所修改,判定下msg.MsgType,如果是text,则跟刚才一样处理,如果是image,则有新的处理方法。
我一个就做了两个简单的处理,一个是年龄、性别、种族,还有就是如果照片里是两个人,则给出五官及整体的相似度值。
相似度的代码直接放下面吧:
package recognition
import(
" encoding/json "
)
type Compare struct {
Component_similarity struct {
Eye float64
Mouth float64
Nose float64
Eyebrow float64
}
Session_id string
Similarity float64
}
func DecodeCompare(data [] byte )Compare{
var c Compare
json.Unmarshal(data, & c)
return c
}
func RecognitionCompare(face1id,face2id string )recognition.Compare{
url: =apiurl+ " /v2/recognition/compare?api_secret= " +apisecret+ " &api_key= " + apikey+ " &face_id2= " +face2id+ " &face_id1= " + face1id
tmp,_: = get (url)
return recognition.DecodeCompare(tmp)
}
判定图片里有几个人,一个人输出性别、年龄,两个人输出相似度,三个及以上,暂未判定:
if msg.MsgType== " image " {
var faceslice detection.Faceslice
faceslice = facepp.DetectionDetect(msg.PicUrl)
switch len(faceslice.Face){
case 0 :
resp.Content = " 请上传有脸的人物照片! "
case 1 :
attribute: =faceslice.Face[ 0 ].Attribute
age: = attribute.Age
gender: = attribute.Gender
var faceGender string
if gender.Value== " Male " {
faceGender = " 男 "
} else {
faceGender = " 女 "
}
faceAgeValue: =fmt.Sprintf( " %d " , int (age.Value))
faceAgeRange: =fmt.Sprintf( " %d " , int (age.Range))
resp.Content = " 性别: " +faceGender+ " \n " + " 年龄: " +faceAgeValue+ " (± " +faceAgeRange+ " ) "
case 2 :
face1id: =faceslice.Face[ 0 ].Face_id
face2id: =faceslice.Face[ 1 ].Face_id
var compare recognition.Compare
compare = facepp.RecognitionCompare(face1id,face2id)
resp.Content = " 眼睛相似度: " +fmt.Sprintf( " %f " ,compare.Component_similarity.Eye)+ " \n " + " 嘴巴相似度: " +fmt.Sprintf( " %f " ,compare.Component_similarity.Mouth)+ " \n " + " 鼻子相似度: " +fmt.Sprintf( " %f " ,compare.Component_similarity.Nos e)+ " \n " + " 眉毛相似度: " +fmt.Sprintf( " %f " ,compare.Component_similarity.Eyebrow)+ " \n " + " 整体相似度: " +fmt.Sprintf( " %f " ,compare.Similarity)
default :
resp.Content = " 照片里人物太多了,暂不分析! "
}
}
标签: Golang , 微信
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于golang微信公众平台之人脸识别的详细内容...