在 OCR 获得的收据中查找总数 - PHP
Posted
技术标签:
【中文标题】在 OCR 获得的收据中查找总数 - PHP【英文标题】:Find the total in a receipt got by OCR - PHP 【发布时间】:2018-11-18 04:45:36 【问题描述】:我在通过 API 视觉获得的收据字符串中查找用户支付的总金额时遇到问题。
例如:
$testo2 = "Del burger Sr Via Carlo del Prete 106/d 50127 FIRENZE C.F. E P.IVA 08380120482 BRUNCH MAMMAMIA ONION RINGS SPICCHI PATATE ACQUA 0.5L TAVOLO 88 EURO 6,50 6,50 4,00 3,00 1,00 TOTALE EURO CONTANTI 21,00 21,00 NR.0057 23/05/18 20:21 MF U1 72005985";
为了找到总数,我试图在一个中搜索点或逗号(一些收据有点和另一个逗号),然后检查点或逗号后面是否有两个数字,然后搜索数字在逗号之前,直到找到找到的字符是一个数字。然后我将这些值放入一个数组中,并以这样的方式反转它以组成一个完整的价格字符串(包括逗号后面的值)。然后将价格输入到一个数组中。
for($i = 1; $i <= $lenghtTesto2 - 1; $i++)
if($testo2[$i] == "." || $testo2[$i] == ",")
if($testo2[$i + 1] == "0" || $testo2[$i + 1] == "1" || $testo2[$i + 1] == "2" || $testo2[$i + 1] == "3" || $testo2[$i + 1] == "4" || $testo2[$i + 1] == "5" || $testo2[$i + 1] == "6" || $testo2[$i + 1] == "7" || $testo2[$i + 1] == "8" || $testo2[$i + 1] == "9")
if($testo2[$i + 2] == "0" || $testo2[$i + 2] == "1" || $testo2[$i + 2] == "2" || $testo2[$i + 2] == "3" || $testo2[$i + 2] == "4" || $testo2[$i + 2] == "5" || $testo2[$i + 2] == "6" || $testo2[$i + 2] == "7" || $testo2[$i + 2] == "8" || $testo2[$i + 2] == "9")
$check = true;
while($check)
if($testo2[$i - $j] == "0" || $testo2[$i - $j] == "1" || $testo2[$i - $j] == "2" || $testo2[$i - $j] == "3" || $testo2[$i - $j] == "4" || $testo2[$i - $j] == "5" || $testo2[$i - $j] == "6" || $testo2[$i - $j] == "7" || $testo2[$i - $j] == "8" || $testo2[$i - $j] == "9")
array_push($arrPrezzi_invertiti, $testo2[$i - $j]);
$j++;
else
$prezzo = "";
$totaleFinale = "";
$dopoPunto1 = $testo2[$i + 1];
$dopoPunto2 = $testo2[$i + 2];
$j = 1;
$lenght_arrPrezzi_invertiti = count($arrPrezzi_invertiti);
for($k = $lenght_arrPrezzi_invertiti - 1; $k >= 0; $k--)
$totaleFinale .= $arrPrezzi_invertiti[$k];
$prezzo = $totaleFinale . "." . $dopoPunto1 . $dopoPunto2;
array_push($array, $prezzo);
$check = false;
钱是 6,50 6,50 4,00 3,00 1,00 21,00 21,00
提前致谢。
【问题讨论】:
首先,有什么问题?你没有指定。其次,您是否尝试过使用正则表达式?它更干净。并请具体说明字符串中列出的钱在哪里。并非所有人都懂意大利语 您是在尝试创建通用解决方案还是字符串始终采用这种精确格式? 不就是TOTALE
这个词后面的第一个数字吗(假设CONTANTE
表示现金,也可以是一个不同的词(或多个词),所以你可能想要灵活处理那?所以我认为你想隔离从 TOTALE 之后的第一个数字到之后的第一个空格的所有内容。
在第二张收据上,是所有的数据还是你把它剪掉了,请用你的真实字符串而不是图片发布代码,我需要使用你的真实字符串进行测试。
第二个有不同的格式,没有你说会一直存在的这个文本。
【参考方案1】:
使用 preg_match();
您必须将可能的单词组合添加到[\sEURO|\sCONTANTI|\sECT.]
无论如何,这会给你一个想法。修补它,直到你让它按你想要的方式工作。
$testo2 = "Del burger Sr Via Carlo del Prete 106/d 50127 FIRENZE C.F. E P.IVA 08380120482 BRUNCH MAMMAMIA ONION RINGS SPICCHI PATATE ACQUA 0.5L TAVOLO 88 EURO 6,50 6,50 4,00 3,00 1,00 TOTALE EURO CONTANTI 21,00 21,00 NR.0057 23/05/18 20:21 MF U1 72005985";
$testo2 = preg_replace('/\s1,/', ' ', $testo2);
preg_match('/[\s\S]0,TOTALE\s[\sEURO|\sCONTANTI]0,\s(.*?)\s/', $testo2, $match);
echo $match[1]; //<--- Outputs "21,00"
第二种解决方案
我相信你可以疯狂地使用正则表达式并得到一些工作,但我们需要多个示例来借鉴。一个更好的想法可能是假设总金额始终是收据上的最高金额。如果是这种情况,我们可以这样做:
function getReceiptTotal($receipt)
preg_match_all('/\d+[\.,]\d+\s/', $receipt, $match);
$comma = preg_match('/,/', $match[0][0]) ? TRUE : FALSE;
for($i = 0; $i < count($match[0]); $i++)
$match[0][$i] = trim($match[0][$i]);
if($comma)
$temp[] = preg_replace('/,/', '.', $match[0][$i]);
sort($temp);
$total = end($temp);
if($comma)
return preg_replace('/\./', ',', $total);
else
return $total;
echo getReceiptTotal($testo2); //Will output "21,00".
这应该适用于您的所有收据类型。
【讨论】:
$testo2 是收据的一个例子,但是使用 OCR 的用户可以从不同的收据中获取文本。这个解决方案是通用的还是特定的? 你需要告诉我们!我们正在尝试寻找匹配的模式。这适用于价格在单词totale和单词(EURO或CONTANTI)之后下降的任何收据数据。 @AlessioRaddi - 下定决心。字符串总是采用完全相同的格式(相同的文本)还是可以不同?你陈述不同的事情。首先你说“一些收据有一个点和另一个逗号”,然后你说它将是这种精确的格式。这将解决您的问题,确切的格式并处理点和逗号。如果其他情况有所不同,您需要告诉我们,否则您既浪费了您的时间,也浪费了我们的时间。 @MagnusEriksson 收据可以包含点或逗号。我刚刚检查过TOTALE EURO CONTANTI
可能不同,它们的值可能会在它们之前和之后移动
@MagnusEriksson 我在我的问题中添加了两个不同收据的示例【参考方案2】:
要查找总数,您可以使用preg_match。
TOTALE EURO CONTANTI\s*\K\d+[.,]\d+
或者在 TOTALE EURO CONTANTI 之间有一个或多个空白字符:
TOTALE\s+EURO\s+CONTANTI\s+\K\d+[.,]\d+
您可以匹配TOTALE EURO CONTANTI
,后跟零个或多个空格字符\s*
,然后重置匹配的起点。然后使用字符类匹配一个或多个数字、逗号或点,后跟一个或多个数字\d+[.,]\d+
$re = '/TOTALE EURO CONTANTI\s*\K\d+,\d+/';
$str = 'Del burger Sr Via Carlo del Prete 106/d 50127 FIRENZE C.F. E P.IVA 08380120482 BRUNCH MAMMAMIA ONION RINGS SPICCHI PATATE ACQUA 0.5L TAVOLO 88 EURO 6,50 6,50 4,00 3,00 1,00 TOTALE EURO CONTANTI 21,00 21,00 NR.0057 23/05/18 20:21 MF U1 72005985';
preg_match($re, $str, $matches);
echo $matches[0]; // 21,00
Demo
【讨论】:
@MagnusEriksson 感谢您的评论。我已经用一个匹配点或逗号的字符类更新了我的答案。 我在我的问题中添加了两张不同收据的例子以上是关于在 OCR 获得的收据中查找总数 - PHP的主要内容,如果未能解决你的问题,请参考以下文章
在 Apple iOS 应用购买服务器到服务器通知沙箱中未获得统一收据
SKReceiptReceiptRequest - 在模拟器上,仅调用 request:didFailWithError 方法。我无法让我的应用获得沙盒收据