本文目录导读:

- 方案一:使用第三方OCR API(推荐)
- 方案二:使用Tesseract OCR(开源免费)
- 方案三:基于OpenCV的图像预处理+自定义模板
- 方案四:基于规则的简易提取(适合特定格式)
- 推荐方案选择
- 完整项目示例:基于百度OCR的发票识别系统
在PHP项目中实现票据识别(OCR)并提取关键字段,通常有几种方案,以下是几种主流实现方式及代码示例:
使用第三方OCR API(推荐)
百度AI OCR(国内常用)
<?php
// 使用百度AI OCR接口识别发票
require_once 'vendor/autoload.php';
use Baidu\Aip\Ocr;
// 配置API Key
$client = new AipOcr('APP_ID', 'API_KEY', 'SECRET_KEY');
// 读取图片文件
$image = file_get_contents('invoice.jpg');
// 调用增值税发票识别接口
$result = $client->vatInvoice($image);
// 提取关键字段
if (isset($result['words_result'])) {
$data = [
'invoice_code' => $result['words_result']['InvoiceCode'] ?? '',
'invoice_number' => $result['words_result']['InvoiceNumber'] ?? '',
'invoice_date' => $result['words_result']['InvoiceDate'] ?? '',
'total_amount' => $result['words_result']['TotalAmount'] ?? '',
'seller_name' => $result['words_result']['SellerName'] ?? '',
'buyer_name' => $result['words_result']['BuyerName'] ?? '',
];
print_r($data);
}
阿里云OCR
<?php
// 阿里云OCR识别
require_once 'vendor/autoload.php';
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
// 配置阿里云凭证
AlibabaCloud::accessKeyClient('ACCESS_KEY_ID', 'ACCESS_KEY_SECRET')
->regionId('cn-hangzhou')
->asDefaultClient();
try {
$result = AlibabaCloud::rpc()
->product('ocr')
->version('2019-12-30')
->action('RecognizeVATInvoice')
->method('POST')
->options([
'query' => [
'ImageURL' => 'https://example.com/invoice.jpg',
],
])
->request();
$data = $result->toArray();
if (isset($data['Data'])) {
$invoice = [
'invoice_code' => $data['Data']['InvoiceCode'] ?? '',
'invoice_number' => $data['Data']['InvoiceNumber'] ?? '',
'invoice_date' => $data['Data']['InvoiceDate'] ?? '',
'total_amount' => $data['Data']['TotalAmount'] ?? '',
'seller' => $data['Data']['SellerName'] ?? '',
];
print_r($invoice);
}
} catch (ClientException $e) {
echo $e->getErrorMessage();
}
使用Tesseract OCR(开源免费)
安装准备
# 安装Tesseract sudo apt-get install tesseract-ocr tesseract-ocr-chi-sim # 使用Composer安装PHP-Tesseract composer require thiagoalessio/tesseract_ocr
代码实现
<?php
use thiagoalessio\TesseractOCR\TesseractOCR;
class InvoiceOCR {
public function extractFields($imagePath) {
// 执行OCR识别
$text = (new TesseractOCR($imagePath))
->lang('chi_sim+eng') // 中文+英文
->psm(6) // 页面分割模式
->run();
// 解析提取关键字段
return $this->parseInvoiceText($text);
}
private function parseInvoiceText($text) {
$data = [];
// 发票号码模式匹配
if (preg_match('/发票号码[::]\s*(\d{8})/', $text, $matches)) {
$data['invoice_number'] = $matches[1];
}
// 发票代码
if (preg_match('/发票代码[::]\s*(\d{12})/', $text, $matches)) {
$data['invoice_code'] = $matches[1];
}
// 金额
if (preg_match('/价税合计[((][大写][))][::]\s*([\d\.]+)/', $text, $matches)) {
$data['total_amount'] = $matches[1];
}
// 购买方名称
if (preg_match('/购买方[名称]?[::]\s*(.+?)\n/', $text, $matches)) {
$data['buyer_name'] = trim($matches[1]);
}
// 销售方名称
if (preg_match('/销售方[名称]?[::]\s*(.+?)\n/', $text, $matches)) {
$data['seller_name'] = trim($matches[1]);
}
// 日期
if (preg_match('/(\d{4})年(\d{2})月(\d{2})日/', $text, $matches)) {
$data['invoice_date'] = "{$matches[1]}-{$matches[2]}-{$matches[3]}";
}
return $data;
}
}
// 使用示例
$ocr = new InvoiceOCR();
$result = $ocr->extractFields('invoice.jpg');
print_r($result);
基于OpenCV的图像预处理+自定义模板
安装OpenCV for PHP
composer require php-opencv/php-opencv
自定义模板匹配实现
<?php
class CustomInvoiceOCR {
private $templateData;
public function __construct() {
// 定义发票模板位置数据
$this->templateData = [
'invoice_code' => ['x' => 100, 'y' => 50, 'w' => 200, 'h' => 30],
'invoice_number' => ['x' => 350, 'y' => 50, 'w' => 200, 'h' => 30],
'total_amount' => ['x' => 400, 'y' => 600, 'w' => 150, 'h' => 30],
'seller_name' => ['x' => 150, 'y' => 400, 'w' => 300, 'h' => 30],
];
}
public function extractByTemplate($imagePath) {
// 图像预处理
$image = $this->preprocessImage($imagePath);
$result = [];
foreach ($this->templateData as $field => $region) {
// 裁剪特定区域
$cropped = $this->cropRegion($image, $region);
// OCR识别该区域
$text = $this->ocrRegion($cropped);
$result[$field] = $this->cleanText($text);
}
return $result;
}
private function preprocessImage($path) {
// 图像处理:灰度化、二值化、去噪等
// 使用GD库或Imagick
$image = imagecreatefromjpeg($path);
// 转为灰度
imagefilter($image, IMG_FILTER_GRAYSCALE);
// 增强对比度
imagefilter($image, IMG_FILTER_CONTRAST, -50);
return $image;
}
private function cropRegion($image, $region) {
// 裁剪指定区域
$cropped = imagecreatetruecolor($region['w'], $region['h']);
imagecopy($cropped, $image, 0, 0,
$region['x'], $region['y'],
$region['w'], $region['h']);
// 保存临时文件
$tempFile = tempnam(sys_get_temp_dir(), 'ocr_');
imagepng($cropped, $tempFile);
return $tempFile;
}
private function ocrRegion($imagePath) {
// 使用Tesseract识别
$text = (new TesseractOCR($imagePath))
->lang('chi_sim+eng')
->run();
unlink($imagePath); // 清理临时文件
return $text;
}
private function cleanText($text) {
return trim(preg_replace('/\s+/', '', $text));
}
}
基于规则的简易提取(适合特定格式)
<?php
class SimpleInvoiceParser {
public function parseFromText($text) {
$data = [
'invoice_code' => '',
'invoice_number' => '',
'total_amount' => '',
'date' => '',
'seller' => '',
'buyer' => ''
];
// 提取发票代码 (12位数字)
if (preg_match('/\b(\d{12})\b/', $text, $matches)) {
$data['invoice_code'] = $matches[1];
}
// 提取发票号码 (8位数字,通常在代码后面)
if (preg_match('/\d{12}\s*(\d{8})\b/', $text, $matches)) {
$data['invoice_number'] = $matches[1];
}
// 提取金额(价税合计)
preg_match_all('/价税合计[::]\s*¥?([\d,]+\.?\d*)/', $text, $matches);
if (!empty($matches[1])) {
$data['total_amount'] = $matches[1][0];
}
// 提取日期
preg_match('/(\d{4}[-年]\d{1,2}[-月]\d{1,2})/', $text, $matches);
if (!empty($matches[1])) {
$data['date'] = str_replace(['年', '月'], '-', $matches[1]);
}
return $data;
}
/**
* 批量处理多个发票
*/
public function batchProcess($texts) {
$results = [];
foreach ($texts as $text) {
$results[] = $this->parseFromText($text);
}
return $results;
}
}
推荐方案选择
| 方案 | 准确率 | 成本 | 复杂度 | 适用场景 |
|---|---|---|---|---|
| 百度/Ali API | 95%+ | 按量付费 | 低 | 生产环境,高精度要求 |
| Tesseract | 70-85% | 免费 | 中 | 测试/低预算项目 |
| 自定义模板 | 90%+(固定模板) | 低 | 高 | 特定格式发票 |
| 规则提取 | 60-80% | 免费 | 低 | 纯文本处理 |
建议: 如果项目预算允许,推荐使用百度AI OCR API,准确率高且接口简单,如果处理量较小,可以先用免费方案测试效果。
完整项目示例:基于百度OCR的发票识别系统
<?php
class InvoiceRecognitionSystem {
private $ocrClient;
private $db;
public function __construct() {
$this->ocrClient = new AipOcr(APP_ID, API_KEY, SECRET_KEY);
$this->db = new PDO('mysql:host=localhost;dbname=invoices', 'user', 'pass');
}
/**
* 自动识别并保存发票信息
*/
public function processInvoice($imagePath) {
try {
// 1. 图片预处理
$optimizedPath = $this->optimizeImage($imagePath);
// 2. OCR识别
$result = $this->recognize($optimizedPath);
// 3. 提取字段
$invoiceData = $this->extractFields($result);
// 4. 验证数据
if ($this->validateData($invoiceData)) {
// 5. 保存到数据库
$invoiceId = $this->saveToDatabase($invoiceData);
// 6. 生成报告
return $this->generateReport($invoiceId, $invoiceData);
}
return ['error' => '数据验证失败'];
} catch (Exception $e) {
return ['error' => $e->getMessage()];
}
}
private function optimizeImage($path) {
// 图像优化:调整大小、增强对比度等
return $path;
}
private function recognize($imagePath) {
$image = file_get_contents($imagePath);
return $this->ocrClient->vatInvoice($image);
}
private function extractFields($ocrResult) {
$fields = $ocrResult['words_result'] ?? [];
return [
'invoice_code' => $fields['InvoiceCode'] ?? '',
'invoice_number' => $fields['InvoiceNumber'] ?? '',
'invoice_date' => $fields['InvoiceDate'] ?? '',
'total_amount' => $fields['TotalAmount'] ?? '',
'tax_amount' => $fields['TaxAmount'] ?? '',
'seller_name' => $fields['SellerName'] ?? '',
'seller_tax_id' => $fields['SellerTaxID'] ?? '',
'buyer_name' => $fields['BuyerName'] ?? '',
'buyer_tax_id' => $fields['BuyerTaxID'] ?? '',
];
}
private function validateData($data) {
// 验证关键字段
return !empty($data['invoice_number']) &&
!empty($data['total_amount']) &&
!empty($data['invoice_date']);
}
private function saveToDatabase($data) {
$sql = "INSERT INTO invoices (invoice_code, invoice_number, invoice_date,
total_amount, tax_amount, seller_name, seller_tax_id,
buyer_name, buyer_tax_id, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())";
$stmt = $this->db->prepare($sql);
$stmt->execute([
$data['invoice_code'],
$data['invoice_number'],
$data['invoice_date'],
$data['total_amount'],
$data['tax_amount'],
$data['seller_name'],
$data['seller_tax_id'],
$data['buyer_name'],
$data['buyer_tax_id']
]);
return $this->db->lastInsertId();
}
private function generateReport($id, $data) {
return [
'id' => $id,
'status' => 'success',
'data' => $data,
'time' => date('Y-m-d H:i:s')
];
}
}
根据你的具体需求(预算、准确率要求、处理量等),选择合适的方案实现,如果需求复杂,建议结合多种方案使用。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播