PHP项目图片鉴黄与违规检测

wen PHP项目 2

本文目录导读:

PHP项目图片鉴黄与违规检测

  1. 第三方API服务(推荐)
  2. 开源方案(本地部署)
  3. 综合解决方案
  4. 高性能批量检测
  5. 最佳实践建议

我来为你介绍PHP项目中实现图片鉴黄与违规检测的几种方案:

第三方API服务(推荐)

安全

<?php
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
class ImageModeration
{
    private $accessKeyId;
    private $accessKeySecret;
    public function __construct($accessKeyId, $accessKeySecret)
    {
        $this->accessKeyId = $accessKeyId;
        $this->accessKeySecret = $accessKeySecret;
        AlibabaCloud::accessKeyClient($this->accessKeyId, $this->accessKeySecret)
            ->regionId('cn-shanghai')
            ->asDefaultClient();
    }
    public function checkImage($imageUrl)
    {
        try {
            $result = AlibabaCloud::rpc()
                ->product('Green')
                ->version('2017-08-23')
                ->action('ImageScan')
                ->method('POST')
                ->options([
                    'query' => [
                        'RegionId' => 'cn-shanghai',
                        'Tasks' => json_encode([
                            [
                                'dataId' => uniqid(),
                                'url' => $imageUrl,
                                'time' => time()
                            ]
                        ]),
                        'Scenes' => json_encode(['porn', 'terrorism', 'ad'])
                    ],
                ])
                ->request();
            return $this->parseResult($result);
        } catch (ClientException $e) {
            return ['error' => $e->getErrorMessage()];
        } catch (ServerException $e) {
            return ['error' => $e->getErrorMessage()];
        }
    }
    private function parseResult($result)
    {
        $data = $result->toArray();
        $results = [];
        foreach ($data['data'] as $item) {
            $sceneResults = [];
            foreach ($item['results'] as $scene) {
                $sceneResults[$scene['scene']] = [
                    'suggestion' => $scene['suggestion'],
                    'rate' => $scene['rate'],
                    'label' => $scene['label'] ?? ''
                ];
            }
            $results[] = $sceneResults;
        }
        return $results;
    }
}
// 使用示例
$moderation = new ImageModeration('your-access-key-id', 'your-access-key-secret');
$result = $moderation->checkImage('https://example.com/image.jpg');
print_r($result);

腾讯云数据万象

<?php
require_once './vendor/autoload.php';
use Qcloud\Cos\Client;
use Qcloud\Cos\Exception\ServiceResponseException;
class TencentImageCheck
{
    private $secretId;
    private $secretKey;
    private $region;
    private $bucket;
    public function __construct($config)
    {
        $this->secretId = $config['secretId'];
        $this->secretKey = $config['secretKey'];
        $this->region = $config['region'];
        $this->bucket = $config['bucket'];
    }
    public function checkImage($imageKey)
    {
        $cosClient = new Client([
            'region' => $this->region,
            'schema' => 'https',
            'credentials' => [
                'secretId' => $this->secretId,
                'secretKey' => $this->secretKey
            ]
        ]);
        try {
            $result = $cosClient->detectImage([
                'Bucket' => $this->bucket,
                'Key' => $imageKey,
                'PornDetect' => 1,
                'TerroristDetect' => 1,
                'AdsDetect' => 1
            ]);
            return $this->analyzeResult($result);
        } catch (ServiceResponseException $e) {
            return ['error' => $e->getMessage()];
        }
    }
    private function analyzeResult($result)
    {
        $analysis = [
            'is_safe' => true,
            'details' => []
        ];
        // 色情检测
        if (isset($result['PornInfo'])) {
            $analysis['details']['porn'] = [
                'hit_flag' => $result['PornInfo']['HitFlag'],
                'score' => $result['PornInfo']['Score'],
                'label' => $result['PornInfo']['Label']
            ];
            if ($result['PornInfo']['HitFlag'] == 1) {
                $analysis['is_safe'] = false;
            }
        }
        // 暴恐检测
        if (isset($result['TerroristInfo'])) {
            $analysis['details']['terrorist'] = [
                'hit_flag' => $result['TerroristInfo']['HitFlag'],
                'score' => $result['TerroristInfo']['Score'],
                'label' => $result['TerroristInfo']['Label']
            ];
            if ($result['TerroristInfo']['HitFlag'] == 1) {
                $analysis['is_safe'] = false;
            }
        }
        return $analysis;
    }
}

开源方案(本地部署)

使用PHP扩展 + OpenCV

<?php
// 需要安装php-opencv扩展
class LocalImageDetector
{
    private $modelPath;
    private $nsfwModel;
    public function __construct($modelPath)
    {
        $this->modelPath = $modelPath;
        $this->loadModel();
    }
    private function loadModel()
    {
        // 加载NSFW检测模型
        // 可以使用TensorFlow或ONNX模型
    }
    public function detect($imagePath)
    {
        $image = cv\imread($imagePath);
        // 图像预处理
        $resized = cv\resize($image, new cv\Size(224, 224));
        $blob = cv\dnn\blobFromImage($resized, 1.0, new cv\Size(224, 224));
        // 执行推理
        $this->nsfwModel->setInput($blob);
        $output = $this->nsfwModel->forward();
        // 解析结果
        return $this->parseOutput($output);
    }
    private function parseOutput($output)
    {
        // 解析模型输出,返回检测结果
        return [
            'nsfw_score' => 0.95, // NSFW得分
            'safe_score' => 0.05,  // 安全得分
            'labels' => ['porn', 'hentai']
        ];
    }
}

调用Python模型(通过shell)

<?php
class PythonModelDetector
{
    private $pythonPath;
    private $scriptPath;
    public function __construct($pythonPath = '/usr/bin/python3', $scriptPath = './detect.py')
    {
        $this->pythonPath = $pythonPath;
        $this->scriptPath = $scriptPath;
    }
    public function detectImage($imagePath)
    {
        $command = sprintf(
            '%s %s --image %s 2>&1',
            escapeshellcmd($this->pythonPath),
            escapeshellarg($this->scriptPath),
            escapeshellarg($imagePath)
        );
        $output = shell_exec($command);
        return json_decode($output, true);
    }
}
# detect.py
import argparse
import json
import sys
from nsfw_detector import predict
def detect_image(image_path):
    try:
        # 使用预训练的NSFW模型
        model = predict.load_model('./nsfw_mobilenet2.h5')
        # 预测
        result = predict.classify(model, image_path)
        # 格式化输出
        output = {
            'status': 'success',
            'predictions': result,
            'is_nsfw': max(result.values()) > 0.5,
            'confidence': max(result.values())
        }
        return json.dumps(output)
    except Exception as e:
        return json.dumps({
            'status': 'error',
            'message': str(e)
        })
if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--image', required=True, help='Image path')
    args = parser.parse_args()
    result = detect_image(args.image)
    print(result)

综合解决方案

完整的图片检测系统

<?php
class ImageSafetyChecker
{
    private $providers = [];
    private $config;
    public function __construct($config)
    {
        $this->config = $config;
        $this->initProviders();
    }
    private function initProviders()
    {
        // 初始化多个检测服务
        if ($this->config['aliyun']['enabled']) {
            $this->providers[] = new AliyunModeration(
                $this->config['aliyun']['accessKeyId'],
                $this->config['aliyun']['accessKeySecret']
            );
        }
        if ($this->config['tencent']['enabled']) {
            $this->providers[] = new TencentImageCheck($this->config['tencent']);
        }
        if ($this->config['local']['enabled']) {
            $this->providers[] = new LocalImageDetector($this->config['local']['modelPath']);
        }
    }
    public function checkImage($imageUrl, $options = [])
    {
        $results = [];
        $errors = [];
        foreach ($this->providers as $provider) {
            try {
                $result = $provider->checkImage($imageUrl);
                $results[] = $result;
                // 如果有明确违规,立即返回
                if ($this->isDefinitelyViolation($result)) {
                    return [
                        'status' => 'violation',
                        'confidence' => 'high',
                        'details' => $result,
                        'provider' => get_class($provider)
                    ];
                }
            } catch (\Exception $e) {
                $errors[] = [
                    'provider' => get_class($provider),
                    'error' => $e->getMessage()
                ];
            }
        }
        // 综合分析结果
        return $this->aggregateResults($results, $errors);
    }
    private function isDefinitelyViolation($result)
    {
        // 根据业务需求定义明确违规的标准
        if (isset($result['suggestion']) && $result['suggestion'] === 'block') {
            return true;
        }
        if (isset($result['score']) && $result['score'] > 0.9) {
            return true;
        }
        return false;
    }
    private function aggregateResults($results, $errors)
    {
        $totalScore = 0;
        $violations = [];
        foreach ($results as $result) {
            // 提取分数和违规类型
            $score = $result['score'] ?? 0;
            $totalScore += $score;
            if (!empty($result['violations'])) {
                $violations = array_merge($violations, $result['violations']);
            }
        }
        $averageScore = count($results) > 0 ? $totalScore / count($results) : 0;
        return [
            'status' => $averageScore > 0.5 ? 'suspicious' : 'safe',
            'confidence' => $averageScore > 0.8 ? 'high' : 'medium',
            'average_score' => $averageScore,
            'violations' => $violations,
            'errors' => $errors,
            'providers_count' => count($results)
        ];
    }
    public function uploadAndCheck($file, $options = [])
    {
        // 上传图片到临时存储
        $uploadPath = $this->uploadImage($file);
        if (!$uploadPath) {
            return ['error' => 'Upload failed'];
        }
        // 执行检测
        $result = $this->checkImage($uploadPath, $options);
        // 如果违规,删除图片
        if ($result['status'] === 'violation') {
            @unlink($uploadPath);
        }
        return $result;
    }
    private function uploadImage($file)
    {
        // 实现图片上传逻辑
        $targetDir = '/tmp/uploads/';
        $fileName = uniqid() . '.' . pathinfo($file['name'], PATHINFO_EXTENSION);
        $targetFile = $targetDir . $fileName;
        if (move_uploaded_file($file['tmp_name'], $targetFile)) {
            return $targetFile;
        }
        return false;
    }
}
// 配置示例
$config = [
    'aliyun' => [
        'enabled' => true,
        'accessKeyId' => 'your-key',
        'accessKeySecret' => 'your-secret'
    ],
    'tencent' => [
        'enabled' => true,
        'secretId' => 'your-secret-id',
        'secretKey' => 'your-secret-key',
        'region' => 'ap-guangzhou',
        'bucket' => 'your-bucket'
    ],
    'local' => [
        'enabled' => false,
        'modelPath' => '/path/to/model'
    ]
];
// 使用示例
$checker = new ImageSafetyChecker($config);
$result = $checker->checkImage('https://example.com/image.jpg');
print_r($result);

高性能批量检测

<?php
class BatchImageChecker
{
    private $checker;
    private $queue = [];
    private $maxConcurrent = 5;
    public function __construct($config)
    {
        $this->checker = new ImageSafetyChecker($config);
    }
    public function batchCheck(array $images)
    {
        $results = [];
        $chunks = array_chunk($images, $this->maxConcurrent);
        foreach ($chunks as $chunk) {
            // 使用curl_multi并发检测
            $multiResults = $this->multiCurlCheck($chunk);
            $results = array_merge($results, $multiResults);
            // 避免API限制
            usleep(100000); // 100ms延迟
        }
        return $results;
    }
    private function multiCurlCheck($images)
    {
        $mh = curl_multi_init();
        $curlHandles = [];
        $results = [];
        foreach ($images as $index => $image) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $this->buildApiUrl($image));
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 10);
            curl_multi_add_handle($mh, $ch);
            $curlHandles[$index] = $ch;
        }
        // 执行并发请求
        $active = null;
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
        while ($active && $mrc == CURLM_OK) {
            if (curl_multi_select($mh) != -1) {
                do {
                    $mrc = curl_multi_exec($mh, $active);
                } while ($mrc == CURLM_CALL_MULTI_PERFORM);
            }
        }
        // 收集结果
        foreach ($curlHandles as $index => $ch) {
            $response = curl_multi_getcontent($ch);
            $results[$index] = json_decode($response, true);
            curl_multi_remove_handle($mh, $ch);
            curl_close($ch);
        }
        curl_multi_close($mh);
        return $results;
    }
    private function buildApiUrl($image)
    {
        // 构建检测API URL
        return "https://api.example.com/detect?image=" . urlencode($image);
    }
}

最佳实践建议

缓存机制

<?php
class CachedImageChecker
{
    private $checker;
    private $cache;
    private $cacheTTL = 3600; // 1小时
    public function checkWithCache($imageUrl)
    {
        $cacheKey = 'image_check_' . md5($imageUrl);
        // 检查缓存
        $cachedResult = $this->cache->get($cacheKey);
        if ($cachedResult) {
            return $cachedResult;
        }
        // 执行检测
        $result = $this->checker->checkImage($imageUrl);
        // 缓存结果
        $this->cache->set($cacheKey, $result, $this->cacheTTL);
        return $result;
    }
}

异步处理队列

<?php
// 使用Redis队列异步处理
class AsyncImageChecker
{
    private $redis;
    private $queueName = 'image_check_queue';
    public function queueCheck($imageUrl, $callback = null)
    {
        $job = [
            'image_url' => $imageUrl,
            'callback' => $callback,
            'created_at' => time()
        ];
        $this->redis->lpush($this->queueName, json_encode($job));
        return ['status' => 'queued', 'job_id' => uniqid()];
    }
    public function processQueue()
    {
        while ($job = $this->redis->rpop($this->queueName)) {
            $jobData = json_decode($job, true);
            try {
                $result = $this->checker->checkImage($jobData['image_url']);
                // 执行回调
                if ($jobData['callback']) {
                    call_user_func($jobData['callback'], $result);
                }
                // 记录结果
                $this->logResult($jobData['image_url'], $result);
            } catch (\Exception $e) {
                $this->logError($jobData['image_url'], $e->getMessage());
            }
        }
    }
}

这些方案可以根据你的具体需求选择使用,建议:

  1. 生产环境:优先使用阿里云/腾讯云等成熟API服务
  2. 成本敏感:结合本地开源方案+云API混合使用
  3. 高并发:使用队列+缓存+批量处理优化性能
  4. 隐私要求高:考虑本地部署方案或使用私有化部署的API

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