本文目录导读:

我将为您介绍几种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;
使用建议
- 简单验证码:使用Tesseract OCR + 基本图像预处理
- 复杂验证码:使用第三方API服务(如Google Vision、OCR.Space)
- 特定类型:针对特定验证码模式进行定制开发
- 生产环境:建议使用成熟的OCR服务,准确率更高
注意事项
- 识别准确率取决于验证码的复杂程度
- 过度的图像处理可能会降低准确率
- 考虑使用机器学习提高识别率
- 遵守网站的使用条款和法律规定
选择哪种方案取决于您的具体需求和验证码的复杂程度,对于简单的数字验证码,Tesseract OCR通常就足够了;对于复杂的图形验证码,建议使用专业OCR服务。