PHP项目人脸识别与比对

wen PHP项目 2

本文目录导读:

PHP项目人脸识别与比对

  1. 技术方案选择
  2. 完整的人脸识别系统
  3. PHP控制器实现
  4. 前端接口调用示例
  5. 性能优化建议
  6. 安全注意事项

我来详细讲解PHP项目中实现人脸识别与比对的完整方案。

技术方案选择

云服务API方案(推荐)

// 百度AI人脸识别
class BaiduFaceRecognizer {
    private $appId;
    private $apiKey;
    private $secretKey;
    public function __construct() {
        $this->appId = 'your_app_id';
        $this->apiKey = 'your_api_key';
        $this->secretKey = 'your_secret_key';
    }
    // 人脸检测
    public function detect($image) {
        $url = 'https://aip.baidubce.com/oauth/2.0/token';
        $data = [
            'grant_type' => 'client_credentials',
            'client_id' => $this->apiKey,
            'client_secret' => $this->secretKey
        ];
        $token = $this->curlPost($url, $data);
        $accessToken = json_decode($token, true)['access_token'];
        // 人脸检测
        $detectUrl = "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token={$accessToken}";
        $imageData = base64_encode(file_get_contents($image));
        $detectData = [
            'image' => $imageData,
            'image_type' => 'BASE64',
            'face_field' => 'age,gender,expression,beauty,face_shape'
        ];
        return $this->curlPost($detectUrl, $detectData);
    }
    // 人脸比对
    public function compare($image1, $image2) {
        $compareUrl = "https://aip.baidubce.com/rest/2.0/face/v3/match";
        $data = [
            [
                'image' => base64_encode(file_get_contents($image1)),
                'image_type' => 'BASE64',
                'face_type' => 'LIVE',
                'quality_control' => 'LOW'
            ],
            [
                'image' => base64_encode(file_get_contents($image2)),
                'image_type' => 'BASE64',
                'face_type' => 'LIVE',
                'quality_control' => 'LOW'
            ]
        ];
        return $this->curlPost($compareUrl, json_encode($data));
    }
    private function curlPost($url, $data) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, is_string($data) ? $data : http_build_query($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }
}

OpenCV + PHP扩展方案

// 使用PHP-FaceDetection扩展
class OpenCVFaceDetector {
    private $faceCascade;
    private $eyeCascade;
    public function __construct() {
        // 加载Haar级联分类器
        $this->faceCascade = new CascadeClassifier();
        $this->faceCascade->load('haarcascade_frontalface_alt.xml');
        $this->eyeCascade = new CascadeClassifier();
        $this->eyeCascade->load('haarcascade_eye.xml');
    }
    // 检测人脸
    public function detectFaces($imagePath) {
        $img = cvimread($imagePath);
        $gray = cvcvtColor($img, cvCOLOR_BGR2GRAY);
        $faces = $this->faceCascade->detectMultiScale(
            $gray,
            1.1,  // scaleFactor
            3,    // minNeighbors
            0,    // flags
            new Size(30, 30) // minSize
        );
        $result = [];
        foreach ($faces as $face) {
            $result[] = [
                'x' => $face->x,
                'y' => $face->y,
                'width' => $face->width,
                'height' => $face->height
            ];
        }
        return $result;
    }
    // 简单的人脸比对(基于直方图)
    public function compareFaces($face1Path, $face2Path) {
        $img1 = cvimread($face1Path);
        $img2 = cvimread($face2Path);
        // 转换为灰度图
        $gray1 = cvcvtColor($img1, cvCOLOR_BGR2GRAY);
        $gray2 = cvcvtColor($img2, cvCOLOR_BGR2GRAY);
        // 计算直方图
        $hist1 = cvcalcHist([$gray1], [0], null, [256], [0, 256]);
        $hist2 = cvcalcHist([$gray2], [0], null, [256], [0, 256]);
        // 归一化
        cvnormalize($hist1, $hist1, 0, 1, cvNORM_MINMAX);
        cvnormalize($hist2, $hist2, 0, 1, cvNORM_MINMAX);
        // 比较直方图
        $similarity = cvcompareHist($hist1, $hist2, cvHISTCMP_CORREL);
        return $similarity;
    }
}

完整的人脸识别系统

数据库设计

-- 用户表
CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) UNIQUE NOT NULL,
    password VARCHAR(255) NOT NULL,
    face_feature TEXT,  -- 人脸特征向量
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 人脸记录表
CREATE TABLE face_records (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT NOT NULL,
    image_path VARCHAR(255) NOT NULL,
    face_feature TEXT,
    confidence FLOAT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);
-- 识别日志表
CREATE TABLE recognition_logs (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    image_path VARCHAR(255),
    similarity FLOAT,
    is_match BOOLEAN,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

人脸注册功能

class FaceRegistration {
    private $db;
    private $faceService;
    public function __construct() {
        $this->db = new PDO('mysql:host=localhost;dbname=face_recognition', 'root', '');
        $this->faceService = new BaiduFaceRecognizer();
    }
    // 注册人脸
    public function registerFace($userId, $imageFile) {
        try {
            // 1. 检测人脸
            $detectResult = $this->faceService->detect($imageFile['tmp_name']);
            $detectData = json_decode($detectResult, true);
            if ($detectData['error_code'] !== 0) {
                throw new Exception('人脸检测失败: ' . $detectData['error_msg']);
            }
            if ($detectData['result']['face_num'] !== 1) {
                throw new Exception('请确保只有一张人脸');
            }
            // 2. 提取人脸特征
            $faceToken = $detectData['result']['face_list'][0]['face_token'];
            // 3. 保存人脸特征到数据库
            $stmt = $this->db->prepare("
                INSERT INTO face_records (user_id, image_path, face_feature, confidence) 
                VALUES (?, ?, ?, ?)
            ");
            // 保存图片
            $imagePath = $this->saveImage($imageFile, $userId);
            $stmt->execute([
                $userId,
                $imagePath,
                $faceToken,
                $detectData['result']['face_list'][0]['face_probability']
            ]);
            return [
                'success' => true,
                'face_token' => $faceToken,
                'image_path' => $imagePath
            ];
        } catch (Exception $e) {
            throw $e;
        }
    }
    private function saveImage($file, $userId) {
        $uploadDir = 'uploads/faces/' . $userId . '/';
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0777, true);
        }
        $fileName = time() . '_' . uniqid() . '.' . pathinfo($file['name'], PATHINFO_EXTENSION);
        $filePath = $uploadDir . $fileName;
        move_uploaded_file($file['tmp_name'], $filePath);
        return $filePath;
    }
}

人脸识别功能

class FaceRecognition {
    private $db;
    private $faceService;
    public function __construct() {
        $this->db = new PDO('mysql:host=localhost;dbname=face_recognition', 'root', '');
        $this->faceService = new BaiduFaceRecognizer();
    }
    // 1:N 人脸搜索
    public function searchFace($imageFile) {
        try {
            // 获取所有注册的人脸特征
            $stmt = $this->db->query("SELECT * FROM face_records");
            $registeredFaces = $stmt->fetchAll(PDO::FETCH_ASSOC);
            $bestMatch = null;
            $highestScore = 0;
            foreach ($registeredFaces as $face) {
                // 比对两个人脸
                $compareResult = $this->faceService->compare(
                    $imageFile['tmp_name'],
                    $face['image_path']
                );
                $compareData = json_decode($compareResult, true);
                if ($compareData['error_code'] === 0) {
                    $score = $compareData['result']['score'];
                    if ($score > $highestScore) {
                        $highestScore = $score;
                        $bestMatch = $face;
                    }
                }
            }
            // 记录识别日志
            $this->logRecognition(
                $bestMatch ? $bestMatch['user_id'] : null,
                $imageFile['name'],
                $highestScore,
                $highestScore > 80
            );
            return [
                'success' => true,
                'match_found' => $highestScore > 80,
                'user_id' => $bestMatch ? $bestMatch['user_id'] : null,
                'confidence' => $highestScore,
                'threshold' => 80
            ];
        } catch (Exception $e) {
            throw $e;
        }
    }
    // 1:1 人脸验证
    public function verifyFace($userId, $imageFile) {
        try {
            // 获取用户注册的人脸
            $stmt = $this->db->prepare("SELECT * FROM face_records WHERE user_id = ?");
            $stmt->execute([$userId]);
            $registeredFace = $stmt->fetch(PDO::FETCH_ASSOC);
            if (!$registeredFace) {
                throw new Exception('未找到用户注册的人脸');
            }
            // 比对
            $compareResult = $this->faceService->compare(
                $imageFile['tmp_name'],
                $registeredFace['image_path']
            );
            $compareData = json_decode($compareResult, true);
            if ($compareData['error_code'] !== 0) {
                throw new Exception('人脸比对失败');
            }
            $score = $compareData['result']['score'];
            $isMatch = $score > 80;
            // 记录日志
            $this->logRecognition($userId, $imageFile['name'], $score, $isMatch);
            return [
                'success' => true,
                'is_match' => $isMatch,
                'confidence' => $score,
                'threshold' => 80
            ];
        } catch (Exception $e) {
            throw $e;
        }
    }
    private function logRecognition($userId, $imageName, $similarity, $isMatch) {
        $stmt = $this->db->prepare("
            INSERT INTO recognition_logs (user_id, image_path, similarity, is_match) 
            VALUES (?, ?, ?, ?)
        ");
        $stmt->execute([
            $userId,
            $imageName,
            $similarity,
            $isMatch ? 1 : 0
        ]);
    }
}

PHP控制器实现

class FaceController {
    private $faceRecognition;
    private $faceRegistration;
    public function __construct() {
        $this->faceRecognition = new FaceRecognition();
        $this->faceRegistration = new FaceRegistration();
    }
    // 人脸注册API
    public function register() {
        header('Content-Type: application/json');
        try {
            if (!isset($_FILES['face_image']) || !isset($_POST['user_id'])) {
                throw new Exception('缺少必要参数');
            }
            $result = $this->faceRegistration->registerFace(
                $_POST['user_id'],
                $_FILES['face_image']
            );
            echo json_encode([
                'code' => 200,
                'message' => '人脸注册成功',
                'data' => $result
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'code' => 500,
                'message' => $e->getMessage()
            ]);
        }
    }
    // 人脸搜索API
    public function search() {
        header('Content-Type: application/json');
        try {
            if (!isset($_FILES['face_image'])) {
                throw new Exception('请上传人脸图片');
            }
            $result = $this->faceRecognition->searchFace($_FILES['face_image']);
            echo json_encode([
                'code' => 200,
                'message' => '识别完成',
                'data' => $result
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'code' => 500,
                'message' => $e->getMessage()
            ]);
        }
    }
    // 人脸验证API
    public function verify() {
        header('Content-Type: application/json');
        try {
            if (!isset($_FILES['face_image']) || !isset($_POST['user_id'])) {
                throw new Exception('缺少必要参数');
            }
            $result = $this->faceRecognition->verifyFace(
                $_POST['user_id'],
                $_FILES['face_image']
            );
            echo json_encode([
                'code' => 200,
                'message' => '验证完成',
                'data' => $result
            ]);
        } catch (Exception $e) {
            echo json_encode([
                'code' => 500,
                'message' => $e->getMessage()
            ]);
        }
    }
}

前端接口调用示例

<!DOCTYPE html>
<html>
<head>人脸识别系统</title>
</head>
<body>
    <h2>人脸注册</h2>
    <form id="registerForm">
        <input type="text" name="user_id" placeholder="用户ID">
        <input type="file" name="face_image" accept="image/*" capture="camera">
        <button type="submit">注册人脸</button>
    </form>
    <h2>人脸识别</h2>
    <form id="searchForm">
        <input type="file" name="face_image" accept="image/*" capture="camera">
        <button type="submit">识别</button>
    </form>
    <div id="result"></div>
    <script>
        document.getElementById('registerForm').addEventListener('submit', function(e) {
            e.preventDefault();
            const formData = new FormData(this);
            fetch('/api/face/register', {
                method: 'POST',
                body: formData
            })
            .then(response => response.json())
            .then(data => {
                document.getElementById('result').innerHTML = 
                    `<p>注册结果: ${data.message}</p>`;
            });
        });
        document.getElementById('searchForm').addEventListener('submit', function(e) {
            e.preventDefault();
            const formData = new FormData(this);
            fetch('/api/face/search', {
                method: 'POST',
                body: formData
            })
            .then(response => response.json())
            .then(data => {
                document.getElementById('result').innerHTML = 
                    `<p>识别结果: ${JSON.stringify(data.data)}</p>`;
            });
        });
    </script>
</body>
</html>

性能优化建议

缓存策略

// 使用Redis缓存人脸特征
class FaceFeatureCache {
    private $redis;
    public function __construct() {
        $this->redis = new Redis();
        $this->redis->connect('127.0.0.1', 6379);
    }
    public function getFaceFeature($userId) {
        $key = "face_feature:{$userId}";
        $feature = $this->redis->get($key);
        if (!$feature) {
            // 从数据库加载
            $stmt = $this->db->prepare("SELECT face_feature FROM face_records WHERE user_id = ?");
            $stmt->execute([$userId]);
            $feature = $stmt->fetchColumn();
            // 缓存到Redis,设置过期时间
            $this->redis->setex($key, 3600, $feature);
        }
        return $feature;
    }
}

批量处理优化

// 使用队列处理大量人脸识别请求
class FaceRecognitionQueue {
    private $queue;
    public function __construct() {
        $this->queue = new SplQueue();
    }
    public function addToQueue($imagePath, $callback) {
        $this->queue->enqueue([
            'image' => $imagePath,
            'callback' => $callback
        ]);
        if ($this->queue->count() >= 10) {
            $this->processBatch();
        }
    }
    private function processBatch() {
        $batch = [];
        while (!$this->queue->isEmpty()) {
            $batch[] = $this->queue->dequeue();
        }
        // 批量发送到API
        foreach ($batch as $job) {
            // 处理每个请求
        }
    }
}

安全注意事项

  1. 数据加密:人脸特征数据加密存储
  2. HTTPS传输:所有API请求使用HTTPS
  3. 访问控制:添加API认证和限流
  4. 合规性:遵守《个人信息保护法》

这个方案提供了从基础到完整的PHP人脸识别系统实现,可以根据实际需求选择使用云服务或本地部署方案。

抱歉,评论功能暂时关闭!