PHP 识别图形验证码

wen PHP项目 3

本文目录导读:

PHP 识别图形验证码

  1. 使用OCR库(最简单)
  2. 图像预处理+OCR(提高准确率)
  3. 使用第三方API服务(最准确)
  4. 基于机器学习的自定义识别
  5. 简单验证码识别(特定模式)
  6. 完整示例:综合解决方案
  7. 使用建议
  8. 注意事项

我将为您介绍几种PHP识别图形验证码的方法,从简单到复杂:

使用OCR库(最简单)

Tesseract OCR

<?php
// 使用Tesseract OCR识别验证码
try {
    $tesseract = new TesseractOCR('captcha.png');
    $text = $tesseract->run();
    echo "识别结果: " . $text;
} catch (Exception $e) {
    echo "识别失败: " . $e->getMessage();
}

安装Tesseract

# Ubuntu/Debian
sudo apt-get install tesseract-ocr
# CentOS/RHEL
sudo yum install tesseract
# 使用Composer安装PHP库
composer require thiagoalessio/tesseract_ocr

图像预处理+OCR(提高准确率)

<?php
class CaptchaRecognizer {
    public function recognize($imagePath) {
        // 1. 图片预处理
        $processedImage = $this->preprocess($imagePath);
        // 2. 使用OCR识别
        $tesseract = new TesseractOCR($processedImage);
        $result = $tesseract->run();
        return $this->cleanResult($result);
    }
    private function preprocess($imagePath) {
        // 使用GD库处理图片
        $img = imagecreatefrompng($imagePath);
        // 转换为灰度
        imagefilter($img, IMG_FILTER_GRAYSCALE);
        // 增加对比度
        imagefilter($img, IMG_FILTER_CONTRAST, -50);
        // 二值化处理
        $width = imagesx($img);
        $height = imagesy($img);
        for ($x = 0; $x < $width; $x++) {
            for ($y = 0; $y < $height; $y++) {
                $rgb = imagecolorat($img, $x, $y);
                $r = ($rgb >> 16) & 0xFF;
                $g = ($rgb >> 8) & 0xFF;
                $b = $rgb & 0xFF;
                // 简单二值化
                $gray = ($r + $g + $b) / 3;
                $value = $gray > 128 ? 255 : 0;
                imagesetpixel($img, $x, $y, imagecolorallocate($img, $value, $value, $value));
            }
        }
        // 保存处理后的图片
        $processedPath = tempnam(sys_get_temp_dir(), 'captcha_') . '.png';
        imagepng($img, $processedPath);
        imagedestroy($img);
        return $processedPath;
    }
    private function cleanResult($text) {
        // 去除空格和特殊字符
        $text = preg_replace('/[^a-zA-Z0-9]/', '', $text);
        return strtoupper($text);
    }
}
// 使用示例
$recognizer = new CaptchaRecognizer();
$result = $recognizer->recognize('captcha.png');
echo "识别结果: " . $result;

使用第三方API服务(最准确)

<?php
class CaptchaAPIService {
    // 方法1:使用Google Cloud Vision API
    public function recognizeWithGoogle($imagePath) {
        $apiKey = 'YOUR_GOOGLE_API_KEY';
        $imageData = base64_encode(file_get_contents($imagePath));
        $requestData = [
            'requests' => [
                [
                    'image' => ['content' => $imageData],
                    'features' => [
                        ['type' => 'TEXT_DETECTION']
                    ]
                ]
            ]
        ];
        $ch = curl_init('https://vision.googleapis.com/v1/images:annotate?key=' . $apiKey);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData));
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
        $response = curl_exec($ch);
        curl_close($ch);
        $result = json_decode($response, true);
        // 提取识别文本
        if (isset($result['responses'][0]['textAnnotations'][0]['description'])) {
            return trim($result['responses'][0]['textAnnotations'][0]['description']);
        }
        return '';
    }
    // 方法2:使用通用API服务
    public function recognizeWithAPI($imagePath) {
        $apiUrl = 'https://api.ocr.space/parse/image';
        $apiKey = 'YOUR_API_KEY';
        $ch = curl_init();
        $data = [
            'apikey' => $apiKey,
            'language' => 'eng',
            'isOverlayRequired' => 'false',
        ];
        // 上传文件
        $file = new CURLFile($imagePath);
        $data['file'] = $file;
        curl_setopt($ch, CURLOPT_URL, $apiUrl);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $response = curl_exec($ch);
        curl_close($ch);
        $result = json_decode($response, true);
        if (isset($result['ParsedResults'][0]['ParsedText'])) {
            return trim($result['ParsedResults'][0]['ParsedText']);
        }
        return '';
    }
}
// 使用示例
$apiService = new CaptchaAPIService();
$result = $apiService->recognizeWithAPI('captcha.png');
echo "API识别结果: " . $result;

基于机器学习的自定义识别

<?php
// 使用PHP-ML进行数字/字母分类器
require_once __DIR__ . '/vendor/autoload.php';
use Phpml\Classification\KNearestNeighbors;
use Phpml\Dataset\CsvDataset;
class MLRecognizer {
    private $classifier;
    private $trainingData = [];
    private $labels = [];
    public function __construct() {
        $this->classifier = new KNearestNeighbors();
    }
    // 创建训练数据集
    public function train($samples, $labels) {
        $this->classifier->train($samples, $labels);
    }
    // 提取特征
    public function extractFeatures($imagePath) {
        $img = imagecreatefrompng($imagePath);
        $width = imagesx($img);
        $height = imagesy($img);
        // 调整为固定大小
        $resized = imagecreatetruecolor(20, 20);
        imagecopyresampled($resized, $img, 0, 0, 0, 0, 20, 20, $width, $height);
        // 提取像素特征
        $features = [];
        for ($x = 0; $x < 20; $x++) {
            for ($y = 0; $y < 20; $y++) {
                $rgb = imagecolorat($resized, $x, $y);
                $r = ($rgb >> 16) & 0xFF;
                $g = ($rgb >> 8) & 0xFF;
                $b = $rgb & 0xFF;
                $features[] = ($r + $g + $b) / 3; // 灰度值
            }
        }
        imagedestroy($img);
        imagedestroy($resized);
        return $features;
    }
    // 识别验证码
    public function recognize($imagePath) {
        // 分割单个字符(需要实现字符分割算法)
        $charImages = $this->segmentCharacters($imagePath);
        $result = '';
        foreach ($charImages as $charImage) {
            $features = $this->extractFeatures($charImage);
            $prediction = $this->classifier->predict($features);
            $result .= $prediction;
        }
        return $result;
    }
    private function segmentCharacters($imagePath) {
        // 字符分割逻辑(根据连通域或投影法)
        // 这里需要实现具体的分割算法
        return [];
    }
}

简单验证码识别(特定模式)

<?php
class SimpleCaptchaRecognizer {
    // 针对特定类型的验证码
    public function recognizeArithmetic($imagePath) {
        // 识别数学表达式验证码
        $ocr = new TesseractOCR($imagePath);
        $text = $ocr->run();
        // 解析数学表达式
        if (preg_match('/(\d+)\s*([+\-*\/])\s*(\d+)/', $text, $matches)) {
            $num1 = (int)$matches[1];
            $operator = $matches[2];
            $num2 = (int)$matches[3];
            switch ($operator) {
                case '+': return $num1 + $num2;
                case '-': return $num1 - $num2;
                case '*': return $num1 * $num2;
                case '/': return $num2 != 0 ? $num1 / $num2 : 0;
            }
        }
        return null;
    }
    // 识别纯数字验证码
    public function recognizeNumeric($imagePath) {
        // 预处理图片
        $img = imagecreatefrompng($imagePath);
        imagefilter($img, IMG_FILTER_GRAYSCALE);
        imagefilter($img, IMG_FILTER_CONTRAST, -100);
        // 保存临时文件
        $tempFile = tempnam(sys_get_temp_dir(), 'captcha') . '.png';
        imagepng($img, $tempFile);
        // OCR识别
        $ocr = new TesseractOCR($tempFile);
        $ocr->setWhitelist(range(0, 9)); // 只识别数字
        $result = $ocr->run();
        // 清理
        unlink($tempFile);
        imagedestroy($img);
        return preg_replace('/[^0-9]/', '', $result);
    }
}

完整示例:综合解决方案

<?php
class ComprehensiveCaptchaRecognizer {
    private $debug = false;
    public function recognize($imagePath) {
        $methods = [
            'tesseract' => [$this, 'recognizeWithTesseract'],
            'imagePreprocess' => [$this, 'recognizeWithPreprocess'],
            'apiService' => [$this, 'recognizeWithAPI']
        ];
        $results = [];
        // 尝试所有方法
        foreach ($methods as $name => $method) {
            try {
                $result = call_user_func($method, $imagePath);
                if (!empty($result)) {
                    $results[$name] = $result;
                }
            } catch (Exception $e) {
                if ($this->debug) {
                    echo "方法 $name 失败: " . $e->getMessage() . "\n";
                }
            }
        }
        // 统计分析结果
        $counts = array_count_values($results);
        arsort($counts);
        // 返回出现次数最多的结果
        return key($counts) ?? '';
    }
    private function recognizeWithTesseract($imagePath) {
        $tesseract = new TesseractOCR($imagePath);
        $result = $tesseract->run();
        return $this->cleanResult($result);
    }
    private function recognizeWithPreprocess($imagePath) {
        // 预处理增强识别
        $img = imagecreatefrompng($imagePath);
        // 多种预处理方式
        $variants = [];
        // 原图
        $variants['original'] = $imagePath;
        // 灰度+对比度
        $img1 = $img;
        imagefilter($img1, IMG_FILTER_GRAYSCALE);
        imagefilter($img1, IMG_FILTER_CONTRAST, -30);
        $variants['gray'] = $this->saveTemp($img1);
        // 二值化
        $img2 = $img;
        imagefilter($img2, IMG_FILTER_GRAYSCALE);
        imagefilter($img2, IMG_FILTER_CONTRAST, -100);
        $this->binarize($img2);
        $variants['binarized'] = $this->saveTemp($img2);
        // 尝试所有预处理变体
        $results = [];
        foreach ($variants as $variant) {
            $tesseract = new TesseractOCR($variant);
            $result = $tesseract->run();
            $results[] = $this->cleanResult($result);
        }
        // 清理临时文件
        foreach ($variants as $variant) {
            if ($variant !== $imagePath && file_exists($variant)) {
                unlink($variant);
            }
        }
        // 返回最可能的结果
        $counts = array_count_values($results);
        arsort($counts);
        return key($counts) ?? '';
    }
    private function recognizeWithAPI($imagePath) {
        // 使用免费API或付费服务
        // 这里以OCR.Space API为例
        $apiKey = 'YOUR_API_KEY';
        $ch = curl_init('https://api.ocr.space/parse/image');
        $file = new CURLFile($imagePath);
        $data = [
            'file' => $file,
            'apikey' => $apiKey,
            'language' => 'eng'
        ];
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
        $result = json_decode($response, true);
        if (isset($result['ParsedResults'][0]['ParsedText'])) {
            return $this->cleanResult($result['ParsedResults'][0]['ParsedText']);
        }
        return '';
    }
    private function cleanResult($text) {
        // 清除OCR常见错误
        $text = strtoupper($text);
        $text = preg_replace('/[^A-Z0-9]/', '', $text);
        // 修正常见OCR错误
        $replacements = [
            'O' => '0',
            'I' => '1',
            'L' => '1',
            'S' => '5',
            'B' => '8'
        ];
        // 根据实际情况决定是否替换
        // $text = strtr($text, $replacements);
        return $text;
    }
    private function saveTemp($image) {
        $tempFile = tempnam(sys_get_temp_dir(), 'captcha') . '.png';
        imagepng($image, $tempFile);
        return $tempFile;
    }
    private function binarize($image) {
        $width = imagesx($image);
        $height = imagesy($image);
        for ($x = 0; $x < $width; $x++) {
            for ($y = 0; $y < $height; $y++) {
                $rgb = imagecolorat($image, $x, $y);
                $r = ($rgb >> 16) & 0xFF;
                $g = ($rgb >> 8) & 0xFF;
                $b = $rgb & 0xFF;
                $gray = ($r + $g + $b) / 3;
                $value = $gray > 128 ? 255 : 0;
                imagesetpixel($image, $x, $y, imagecolorallocate($image, $value, $value, $value));
            }
        }
    }
}
// 使用示例
$recognizer = new ComprehensiveCaptchaRecognizer();
$result = $recognizer->recognize('captcha.png');
echo "最终识别结果: " . $result;

使用建议

  1. 简单验证码:使用Tesseract OCR + 基本图像预处理
  2. 复杂验证码:使用第三方API服务(如Google Vision、OCR.Space)
  3. 特定类型:针对特定验证码模式进行定制开发
  4. 生产环境:建议使用成熟的OCR服务,准确率更高

注意事项

  • 识别准确率取决于验证码的复杂程度
  • 过度的图像处理可能会降低准确率
  • 考虑使用机器学习提高识别率
  • 遵守网站的使用条款和法律规定

选择哪种方案取决于您的具体需求和验证码的复杂程度,对于简单的数字验证码,Tesseract OCR通常就足够了;对于复杂的图形验证码,建议使用专业OCR服务。

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