一、概述与适用场景
本文演示如何在 PHP 服务端用 ImageMagick 做图像预处理,再调用系统安装的 Tesseract 做 OCR,最后用 Laravel 封装为 REST API。适合把验证码识别功能接入测试工具、后台自动化流程或内部管理平台。
优点:
PHP 技术栈贴合多数 Web 后端;
ImageMagick 提供强大的命令行图像处理能力;
Tesseract 负责 OCR,稳定成熟;
Laravel 提供路由、文件上传、队列、日志等工程能力。
二、环境准备
更多内容访问ttocr.com或联系1436423940
系统依赖(Ubuntu 举例)
sudo apt update
sudo apt install -y php php-cli php-mbstring php-xml php-zip git unzip
sudo apt install -y imagemagick
sudo apt install -y tesseract-ocr
安装 Composer 与 Laravel 项目
安装 Composer(若未安装)
php -r "copy('https://getcomposer.org/installer','composer-setup.php');"
php composer-setup.php
sudo mv composer.phar /usr/local/bin/composer
创建 Laravel 项目
composer create-project --prefer-dist laravel/laravel captcha-ocr
cd captcha-ocr
可选:安装 Imagick PHP 扩展(如果你想直接在 PHP 里用 Imagick 类)
sudo apt install -y php-imagick
然后重启 PHP-FPM / web server
sudo systemctl restart php7.4-fpm # 或 apache2/nginx 对应服务
注意:本文示范主要使用 ImageMagick 命令行 convert / magick(更容易调试),也提供 PHP Imagick 选项。
三、设计思路
前端将验证码图片(或截图)上传到后端。
后端先用 ImageMagick 做灰度、对比度增强、阈值二值化、去噪(开/闭操作)、放大等预处理,生成临时处理图像。
调用 Tesseract(命令行或通过 PHP 绑定)识别文本,同时设置字符白名单以减少误识别。
清洗、校验识别结果(长度、合法字符),返回 JSON 给客户端。
对高并发场景,可把识别任务放到队列(worker)中异步处理。
四、图像预处理命令示例(ImageMagick)
这是常用的一套命令串(可根据样本调参),保存为 shell 脚本或直接在 PHP 中调用:
preprocess.sh
INPUT="$1"
OUTPUT="$2"
1. 转灰度,2. 提高对比度,3. 伸缩放大,4. 中值去噪,5. 二值化(自适应)
magick convert "$INPUT" -colorspace Gray
-contrast-stretch 0.5%
-resize 200%
-morphology Convolve DoG:0,0,2
-median 2
-threshold 50%
"$OUTPUT"
解释:
-colorspace Gray:灰度化;
-contrast-stretch:增强对比,去掉极端像素;
-resize 200%:放大(提高小字体可读性);
-morphology Convolve DoG:0,0,2:差分高斯(可增强边缘);
-median 2:中值去噪;
-threshold 50%:全局二值化(阈值可改为 Otsu 或多尝试值)。
你可以把这套命令调成若干不同参数集合,后端对同一图片尝试多套预处理并投票选择结果(提升鲁棒性)。
五、PHP 调用 Tesseract 的简单封装
在 Laravel 项目 app/Services 下创建 OcrService.php:
/dev/null",$this->tesseractPath,escapeshellarg($imagePath),escapeshellarg($this->whitelist)));$output = shell_exec($cmd);if ($output === null) return '';// 清洗:去掉非字母数字,去换行空格$clean = preg_replace('/[^A-Z0-9]/', '', strtoupper($output));return $clean;} }说明:--psm 7:页面分割模式,7 表示单行文本。对不同验证码可切换(PSM_SINGLE_BLOCK、PSM_SINGLE_WORD、PSM_SINGLE_CHAR)试效果。tessedit_char_whitelist 降低误识别概率。shell_exec 简洁,但在高并发或安全敏感环境要注意命令注入风险并采取更严的 path 和输入验证。六、在 Laravel 中暴露 REST API在 routes/api.php 添加路由:use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use App\Http\Controllers\OcrController;Route::post('/ocr/upload', [OcrController::class, 'upload']);创建控制器 app/Http/Controllers/OcrController.php:ocr = $ocr;}public function upload(Request $request){$request->validate(['image' => 'required|file|mimes:png,jpg,jpeg']);$file = $request->file('image');$origPath = $file->storeAs('uploads', Str::random(12) . '.' . $file->getClientOriginalExtension());$storagePath = storage_path('app/' . $origPath);$procPath = storage_path('app/' . 'proc_' . basename($storagePath));// 调用 ImageMagick 预处理(使用上面的脚本或命令)// 这里直接在 PHP 中用 exec 运行 convert 命令$convertCmd = sprintf('magick convert %s -colorspace Gray -contrast-stretch 0.5%% -resize 200%% -median 2 -threshold 50%% %s 2>&1',escapeshellarg($storagePath),escapeshellarg($procPath));exec($convertCmd, $out, $ret);if ($ret !== 0) {return response()->json(['error' => 'preprocess failed', 'detail' => $out], 500);}// OCR$text = $this->ocr->recognize($procPath);// 清理临时文件(可选择保留以便调试)@unlink($storagePath);@unlink($procPath);return response()->json(['text' => $text]);} }说明:用 storeAs 存文件到 storage/app/uploads,便于后台访问;magick convert 可替换为 convert,或使用 PHP Imagick 函数链替代;生产环境建议把预处理与 OCR 放入队列(Laravel Queue),避免请求阻塞。七、批量识别与队列化(异步)使用 Laravel 队列(Redis/Database driver)把识别任务放后台处理。在控制器里把上传的文件推送为 Job,马上返回任务 id;前端轮询或 Webhook 获取识别结果。示意 Job(app/Jobs/OcrJob.php)核心:public function handle() {// 调用与 Controller 同样的预处理 + OCR 流程$procPath = storage_path('app/' . 'proc_' . basename($this->filePath));exec("magick convert {$this->filePath} ... {$procPath}");$text = (new OcrService())->recognize($procPath);// 将结果存 DB 或写文件,供前端查询 }八、提升识别率的实务技巧白名单严格:如果验证码只数字就只设置 0123456789,白名单必须与真实分布一致。多方案预处理投票:对同一图像按不同阈值或滤波参数生成多张预处理图,分别 OCR,取出现频率最高的结果。字符分割:若验证码字符彼此分隔明显,可先做连通域分割,把每个字符单独识别并拼接(提高粘连字符场景准确率)。放大+锐化:Tesseract 对小字敏感,放大 1.5-2x 通常有效。微调 Tesseract:对固定风格验证码可做自训练(生成训练样本并训练 .traineddata)来极大提升准确率(此步骤复杂,适合长期项目)。后处理规则:固定长度校验、常见混淆映射(例如把 O → 0 或 0 → O 根据业务规则)能提升整串匹配率。采样真实样本微调:收集真实失败样本,分析错误模式并调整预处理或白名单。九、性能、并发与安全考虑并发:Tesseract 启动开销较高,建议使用长期运行的 worker 进程(队列)维护 Tesseract 实例或复用客户端,避免每次请求都启动子进程。沙箱与安全:不要直接把未验证的命令拼接给 shell,确保 escapeshellarg,并严格校验上传文件类型与大小。日志与样本收集:把识别失败的图片保留或记录,以便后续分析与改进。容器化:用 Docker 打包 PHP + ImageMagick + Tesseract,方便部署与依赖管理。十、常见问题排查识别为空或乱码:检查 tessdata 是否安装,tesseract --version 是否报错;检查预处理是否把图像变成全白或全黑。字符被错分或长度不对:尝试把 --psm 改为不同模式(7、8、6、3)看效果;或者用字符切割策略。高并发下失败/慢:使用队列,限制并发 worker 数,避免短时间内大量启动外部进程。输出有小写字母但你只想要大写:strtoupper 转为大写并根据业务规则映射混淆字符。十一、示例:简单 curl 测试启动 Laravel 本地服务器:php artisan serve --port=8000用 curl 上传测试图片:curl -F "image=@/path/to/captcha.png" http://127.0.0.1:8000/api/ocr/upload返回示例:{"text": "A9K7" }