zoukankan      html  css  js  c++  java
  • 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.com/注册,获取API_SECRET、API_KEY。

    而后推荐看文档,http://cn.faceplusplus.com/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.com"
    
    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微信
  • 相关阅读:
    React Native之(支持iOS与Android)自定义单选按钮(RadioGroup,RadioButton)
    React Native之TextInput的介绍与使用(富文本封装与使用实例,常用输入框封装与使用实例)
    drf框架
    drf框架
    drf框架
    drf框架
    drf框架
    drf框架
    drf框架
    drf框架
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3113797.html
Copyright © 2011-2022 走看看