好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

golang微信公众平台之人脸识别

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微信公众平台之人脸识别的详细内容...

  阅读:34次