dd

基于TP3.2版人脸识别函数

jerry thinkphp 2015年11月19日 收藏
获取人的脸部特征信息,得到一组特征数组
第一步,在百度开发者中心申请人脸识别接口,具体步骤查询百度
第二步,申请成功后记下API Key和Secret Key
第三步,在框架/Library/Org/Util/目录下建立Baidu.class.php代码如下
<?php

/**********************************************************
*Author:    dtnet(presdecoeur@gmail.com)
*Time:      2014-6-5下午5:35:13
*File:      Bdauth.class.php
**********************************************************/
namespace Org\Util;

class Baidu {
    public static $BD_OAUTH2_ENDPOINTS = array (
            'authorize' => 'https://openapi.baidu.com/oauth/2.0/authorize',
            'token' => 'https://openapi.baidu.com/oauth/2.0/token',
            'logout' => 'https://openapi.baidu.com/connect/2.0/logout',
            'face'=>'https://openapi.baidu.com/rest/2.0/media/v1/face/detect' 
    );
    protected $clientId;
    protected $clientSecret;
    protected $redirectUri;
    public function __construct($clientId, $clientSecret) {
        $this->clientId = $clientId;
        $this->clientSecret = $clientSecret;
    }
    public function setRedirectUri($redirectUri) {
        if (empty ( $redirectUri )) {
            $redirectUri = $this->getCurrentUrl ();
        }
        $this->redirectUri = $redirectUri;
        return $this;
    }
    public function getRedirectUri() {
        return $this->redirectUri;
    }
    public function getLogoutUrl($accessToken, $next = '') {
        $params = array ('access_token' => $accessToken,'next' => $next ? $next : $this->getCurrentUrl () 
        );
        return self::$BD_OAUTH2_ENDPOINTS ['logout'] . '?' . http_build_query ( $params, '', '&' );
    }
    public function getAuthorizeUrl($responseType = 'code', $scope = '', $state = '', $display = 'popup') {
        $params = array ('client_id' => $this->clientId,'response_type' => $responseType,'redirect_uri' => $this->redirectUri,'scope' => $scope,'state' => $state,'display' => $display 
        );
        return self::$BD_OAUTH2_ENDPOINTS ['authorize'] . '?' . http_build_query ( $params, '', '&' );
    }
    public function getAccessTokenByAuthorizationCode($code)
    {
        $params = array(
                'grant_type'    => 'authorization_code',
                'code'            => $code,
                'client_id'        => $this->clientId,
                'client_secret'    => $this->clientSecret,
                'redirect_uri'    => $this->redirectUri,
        );
        return $this->makeAccessTokenRequest($params);
    }
    public function getAccessTokenByClientCredentials($scope = '')
    {
        $params = array(
                'grant_type'    => 'client_credentials',
                'client_id'        => $this->clientId,
                'client_secret'    => $this->clientSecret,
                'scope'            => $scope,
        );
        return $this->makeAccessTokenRequest($params);
    }
    public function getAccessTokenByDeveloperCredentials($accessKey, $secretKey)
    {
        $params = array(
                'grant_type'    => 'developer_credentials',
                'client_id'        => $accessKey,
                'client_secret'    => $secretKey,
        );
        return $this->makeAccessTokenRequest($params);
    }
    public function getAccessTokenByRefreshToken($refreshToken, $scope = '')
    {
        $params = array(
                'grant_type'    => 'refresh_token',
                'refresh_token'    => $refreshToken,
                'client_id'        => $this->clientId,
                'client_secret'    => $this->clientSecret,
                'scope'            => $scope,
        );
        return $this->makeAccessTokenRequest($params);
    }
    public function makeAccessTokenRequest($params)
    {
        $result = $this->request(self::$BD_OAUTH2_ENDPOINTS['token'], $params, 'POST');
        if ($result) {
            $result = json_decode($result, true);
            if (isset($result['error_description'])) {
                $this->setError($result['error'], $result['error_description']);
                return false;
            }
            return $result;
        }
    
        return false;
    }
    
    public function getAccessFace($imgurl)    {
        
        $retoken=$this->getAccessTokenByClientCredentials();
        $imgurl=urlencode($imgurl);
        $params = array(
                'access_token'    => $retoken['access_token'],
                'url'    => $imgurl,
        );

        return $this->makeAccessFaceRequest($params);
    }
    
    public function makeAccessFaceRequest($params){
        $result = $this->request(self::$BD_OAUTH2_ENDPOINTS['face'], $params, 'POST');
        if ($result) {
            $result = json_decode($result, true);
            if (isset($result['error_description'])) {
                $this->setError($result['error'], $result['error_description']);
                return false;
            }
            return $result;
        }        
        return false;                
    }
    
    
    public static function setError($errno, $errmsg)
    {
        self::$errno = $errno;
        self::$errmsg = $errmsg;
        self::errorLog($errmsg);
    }
    
    /**
     * Get the gloable errno.
     *
     * @return int
     */
    public static function errno()
    {
        return self::$errno;
    }
    
    /**
     * Get the gloable error message.
     *
     * @return string
     */
    public static function errmsg()
    {
        return self::$errmsg;
    }
    
    /**
     * Whether to set the debug mode of the Baidu OpenAPI SDK or not.
     *
     * @param bool $on true or false
     * @return void
     */
    public static function setDebugMode($on = true)
    {
        self::$isDebug = $on;
    }
    
    /**
     * Whether the debug mode of the Baidu OpenAPI SDK is on or off.
     *
     * @return bool
     */
    public static function isDebugMode()
    {
        return self::$isDebug;
    }
    /**
     * Request for a http/https resource
     *
     * @param string $url Url to request
     * @param array $params Parameters for the request
     * @param string $httpMethod Http method, 'GET' or 'POST'
     * @param bool $multi Whether it's a multipart POST request
     * @return string|false Returns string if success, or false if failed
     */
    public static function request($url, $params = array(), $httpMethod = 'GET', $multi = false)
    {
        // when using bae(baidu app engine) to deploy the application,
        // just comment the following line
        $ch = curl_init();
        // when using bae(baidu app engine) to deploy the application,
        // and uncomment the following two lines
        //$fetch= new BaeFetchUrl();
        //$ch = $fetch->getHandle();
    
        $curl_opts = array(
                CURLOPT_CONNECTTIMEOUT    => 3,
                CURLOPT_TIMEOUT            => 5,
                CURLOPT_USERAGENT        => 'baidu-apiclient-php-2.0',
                CURLOPT_HTTP_VERSION    => CURL_HTTP_VERSION_1_1,
                CURLOPT_RETURNTRANSFER    => true,
                CURLOPT_HEADER            => false,
                CURLOPT_FOLLOWLOCATION    => false,
        );
    
        if (stripos($url, 'https://') === 0) {
            $curl_opts[CURLOPT_SSL_VERIFYPEER] = false;
        }
    
        if (strtoupper($httpMethod) === 'GET') {
            $query = http_build_query($params, '', '&');
            $delimiter = strpos($url, '?') === false ? '?' : '&';
            $curl_opts[CURLOPT_URL] = $url . $delimiter . $query;
            $curl_opts[CURLOPT_POST] = false;
        } else {
            $headers = array();
            if ($multi && is_array($params) && !empty($params)) {
                $body = self::buildHttpMultipartBody($params);
                $headers[] = 'Content-Type: multipart/form-data; boundary=' . self::$boundary;
            } else {
                $body = http_build_query($params, '', '&');
            }
            $curl_opts[CURLOPT_URL] = $url;
            $curl_opts[CURLOPT_POSTFIELDS] = $body;
            $curl_opts[CURLOPT_HTTPHEADER] = $headers;
        }
    
        curl_setopt_array($ch, $curl_opts);
        $result = curl_exec($ch);
    
        if ($result === false) {
            self::setError(curl_errno($ch), curl_error($ch));
            curl_close($ch);
            return false;
        } elseif (empty($result)) {
            $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            if ($http_code != 200) {
                self::setError($http_code, 'http response status code: ' . $http_code);
                curl_close($ch);
                return false;
            }
        }
    
        curl_close($ch);
         
        return $result;
    }
    
    /**
     * Prints to the error log if you aren't in command line mode.
     *
     * @param String log message
     */
    public static function errorLog($msg)
    {
        // disable error log if we are running in a CLI environment
        if (php_sapi_name() != 'cli') {
            error_log($msg);
        }
    
        // Set the debug mode if you want to see the errors on the page
        if (self::$isDebug) {
            echo 'error_log: '.$msg."\n";
        }
    }
    
    /**
     * Generate the signature for passed parameters.
     *
     * @param array $params Array of parameters to be signatured
     * @param string $secret Secret key for signature
     * @param string $namespace The parameter which will be excluded when calculate the signature
     * @return string Signature of the parameters
     */
    public static function generateSign($params, $secret, $namespace = 'sign')
    {
        $str = '';
        ksort($params);
        foreach ($params as $k => $v) {
            if ($k != $namespace) {
                $str .= "$k=$v";
            }
        }
        $str .= $secret;
        return md5($str);
    }
    
    /**
     * Get the url of current page.
     *
     * @return string
     */
    public static function getCurrentUrl()
    {
        $protocol = 'http://';
        if (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
            $protocol = strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) . '://';
        } elseif (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
            $protocol = 'https://';
        }
    
        if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
            $host = $_SERVER['HTTP_X_FORWARDED_HOST'];
        } else {
            $host = $_SERVER['HTTP_HOST'];
        }
    
        $currentUrl = $protocol . $host . $_SERVER['REQUEST_URI'];
        $parts = parse_url($currentUrl);
    
        $query = '';
        if (!empty($parts['query'])) {
            // drop known oauth params
            $params = explode('&', $parts['query']);
            $retained_params = array();
            foreach ($params as $param) {
                if (self::shouldRetainParam($param)) {
                    $retained_params[] = $param;
                }
            }
                
            if (!empty($retained_params)) {
                $query = '?' . implode($retained_params, '&');
            }
        }
    
        // use port if non default
        $port = isset($parts['port']) && (($protocol === 'http://' && $parts['port'] !== 80) ||
                ($protocol === 'https://' && $parts['port'] !== 443)) ? ':' . $parts['port'] : '';
    
        // rebuild
        return $protocol . $parts['host'] . $port . $parts['path'] . $query;
    }
    
    private static function shouldRetainParam($param)
    {
        foreach (self::$DROP_QUERY_PARAMS as $drop_query_param) {
            if (strpos($param, $drop_query_param . '=') === 0) {
                return false;
            }
        }
    
        return true;
    }
    
    /**
     * Build the multipart body for file uploaded request.
     * @param array $params Parameters for the request
     * @return string
     */
    private static function buildHttpMultipartBody($params)
    {
        $body = '';
        $pairs = array();
        self::$boundary = $boundary = md5('BAIDU-PHP-SDK-V2' . microtime(true));
    
        foreach ($params as $key => $value) {
            if ($value{0} == '@') {
                $url = ltrim($value, '@');
                $content = file_get_contents($url);
                $array = explode('?', basename($url));
                $filename = $array[0];
    
                $body .= '--' . $boundary . "\r\n";
                $body .= 'Content-Disposition: form-data; name="' . $key . '"; filename="' . $filename . '"'. "\r\n";
                $body .= 'Content-Type: ' . self::detectMimeType($url) . "\r\n\r\n";
                $body .= $content . "\r\n";
            } else {
                $body .= '--' . $boundary  . "\r\n";
                $body .= 'Content-Disposition: form-data; name="' . $key . "\"\r\n\r\n";
                $body .= $value . "\r\n";
            }
        }
    
        $body .= '--' . $boundary . '--';
        return $body;
    }
    
    /**
     * Tries to detect MIME type of a file
     *
     * The method will try to use fileinfo extension if it is available,
     * deprecated mime_content_type() function in the other case. If neither
     * works, default 'application/octet-stream' MIME type is returned
     *
     * @param    string  filename
     * @return   string  file MIME type
     */
    private static function detectMimeType($filename)
    {
        // finfo extension from PECL available
        if (function_exists('finfo_open')) {
            if (!isset(self::$fileinfoDb)) {
                self::$fileinfoDb = finfo_open(FILEINFO_MIME);
            }
            if (self::$fileinfoDb) {
                $info = finfo_file(self::$fileinfoDb, $filename);
            }
        }
        // (deprecated) mime_content_type function available
        if (empty($info) && function_exists('mime_content_type')) {
            $info = mime_content_type($filename);
        }
        return empty($info)? 'application/octet-stream': $info;
    }
}
第四步,在Common目录添加方法代码如下
function face($url){
    $clientId = '这里用API Key替换';
    $clientSecret = '这里用Secret Key替换';
    $image = new \Org\Util\Baidu($clientId,$clientSecret);
    return $image->getAccessFace($url);
}
第五步,使用函数
$url='http://xxx.xxx.com/xxx/xxx.jpg';
dump(face($url));
成功返回:
array(6) {
["face"] => array(1) {
[0] => array(3) {
["face_id"] => string(32) "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
["attribute"] => array(3) {
["gender"] => array(2) {
["confidence"] => string(8) "1.000000"
["value"] => string(6) "female"
}
["smiling"] => array(1) {
["confidence"] => string(8) "0.131746"
}
["face"] => array(2) {
["value"] => string(4) "true"
["confidence"] => string(4) "0.19"
}
}
["position"] => array(6) {
["center"] => array(2) {
["x"] => string(8) "0.653580"
["y"] => string(8) "0.285610"
}
["width"] => string(8) "0.624930"
["height"] => string(8) "0.468110"
["eye_left"] => array(2) {
["x"] => string(8) "0.541770"
["y"] => string(8) "0.115710"
}
["eye_right"] => array(2) {
["x"] => string(8) "0.875140"
["y"] => string(8) "0.186870"
}
["mouth"] => array(2) {
["x"] => string(8) "0.640980"
["y"] => string(8) "0.440060"
}
}
}
}
["img_id"] => string(32) "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
["url"] => string(35) "http://xxx.xxx.com/xxx/xxx.jpg"
["session_id"] => string(32) "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
["img_width"] => string(3) "200"
["img_height"] => string(3) "267"
dd