如何使用 Google Vision Api 检测块内的所有文本
how can I detect all the text that inside a block with Google Vision Api
我正在尝试从具有 google 视觉 api 的图像中提取文本,它有效。但我只想检测图像的一部分以获得某些文本。
这是我用的图片
我只想提取从 maybank2u.com
到 From Account:
的所有文本
我知道有一些教程可以通过使用块来完成此技巧,但这些教程是不同的编程语言。
我的代码:
<div class="row">
<div class="col-12">
<ol>
<?php foreach ($text as $key => $texts): ?>
<li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br>
</li>
<?php endforeach ?>
</ol>
</div>
</div>
此代码将从图像中获取所有文本
输出:
如果您只想限制输出及其每次应该停止执行的相同字符串,请执行以下操作:
<div class="row">
<div class="col-12">
<ol>
<?php foreach ($text as $key => $texts): ?>
<?php if (strpos($texts->info()['description'], 'From Account') !== false) break; ?>
<li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br>
</li>
<?php endforeach ?>
</ol>
</div>
</div>
解释:
如果 $texts->info()['description']
包含文本 From Account
,则通过 break
结束 foreach 循环的执行。如果需要检查多个关键字 read this.
另一种解决方案是在将图像发送到 API 之前用 imagecrop()
裁剪图像。但是为此你需要确保它永远不会改变文本的大小/位置。
P.S。你确定每个人都应该在你的屏幕截图中看到那些私人数据吗?
更新1
正如你所问。这将是相同的代码,但使用 alternative syntax for control structures:
<div class="row">
<div class="col-12">
<ol>
<?php foreach ($text as $key => $texts): ?>
<?php if (strpos($texts->info()['description'], 'From Account') !== false): ?>
<?php break; ?>
<?php endif; ?>
<li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br>
</li>
<?php endforeach ?>
</ol>
</div>
</div>
也许这可以解决您的问题,因为同一页面包含此注释:
Mixing syntaxes in the same control block is not supported.
更新2
在你更新你的问题后,它现在更清楚了。输出不包含每个文本行的一个元素。相反,它包含多行文本。因此,我的第一个代码没有回显任何内容,因为它在第一个数组元素中找到 From Account
。
因此我们需要搜索字符串 From Account
和 剪切文本行:
<div class="row">
<div class="col-12">
<ol>
<?php foreach ($text as $key => $texts): ?>
<?php
$text = $texts->info()['description'];
// search for string
$pos = strpos($texts->info()['description'], 'From Account');
if ($pos !== false) {
// if the string was found cut the text
$text = substr($text, 0, $pos);
}
?>
<li><h6> <?php echo $text ?></h6><<br><br>
</li>
<?php endforeach ?>
</ol>
</div>
</div>
您可以选择在 <?php endforeach ?>
之前添加此内容以跳过所有以下数组元素:
<?php
if ($pos !== false) {
break;
}
?>
注意: @TerryLennox 使用 preg_match
来查找 From Account
。这与使用 strpos
(most prefer avoiding regex) 没有区别。但他的回答包含另一个很好的提示。他使用文本位置信息将文本逐行添加到新数组中。这可能非常有用,具体取决于您的目标如何 display/store 文本。
下面的代码适合我。我有一个 php 文件,test.php 和一个图像文件 /images/UUIPXl.png。
为了获取每一行文本,我迭代了来自 Google Vision 的文本注释,并创建了一个行项目数组。其中每一个都有一个 x 位置和一个文本值。
然后我按 x 位置对每一行进行排序并连接以创建一行文本。
最后,我们在获得所需的最终文本行后停止。
我得到这样的结果:
- maybank2u.com
- 打开账单支付
- 状态:成功
- 参考编号:2950211545
- 交易日期:2016年2月1日13:09:17
- 金额:RM100.00
- 来自账户 564155051577 WCA
php代码:
<?php
require 'vendor/autoload.php';
use Google\Cloud\Vision\VisionClient;
$config = ["keyFile" => json_decode(file_get_contents("./APIKey.json"), true) ];
$vision = new VisionClient($config);
$image = $vision->image(
fopen('./images/UUIPXl.png', 'r'),
['TEXT_DETECTION']
);
$textAnnotations = $vision->annotate($image)->text();
$rows = [];
// Function used to sort our lines.
function sortProc($a, $b)
{
if ($a["x"] === $b["x"]) {
return 0;
}
return ($a["x"] < $b["x"]) ? -1 : 1;
}
// Remove first row (complete text).
array_shift($textAnnotations);
// We should calculate this, use a reasonable value to begin with.
$lineHeight = 8;
foreach ($textAnnotations as $text) {
$key = round(((double)($text->info()["boundingPoly"]["vertices"][0]["y"]))/$lineHeight);
$x = (int)$text->info()["boundingPoly"]["vertices"][0]["x"];
$value = ["x" => $x, "text" => $text->description()];
if (!isset($rows[$key])) {
$rows[$key] = [];
}
$rows[$key][] = $value;
}
$text = [];
foreach ($rows as $key => $value) {
// Sort by x value.
usort($value, "sortProc");
// Concatenate each line
$result = array_reduce($value, function($acc, $elem) {
$acc .= " " . $elem["text"];
return $acc;
}, "");
$text[] = $result;
// Stop when we get here!
if (preg_match("/from account/i", $result)) {
break;
}
}
?>
<div class="row" style="padding: 20px;">
<div class="col-12">
<ul>
<?php foreach ($text as $row): ?>
<li><h3> <?php echo ucfirst($row) ?></h3></li>
<?php endforeach ?>
</ul>
</div>
</div>
我正在尝试从具有 google 视觉 api 的图像中提取文本,它有效。但我只想检测图像的一部分以获得某些文本。
这是我用的图片
我只想提取从 maybank2u.com
到 From Account:
的所有文本
我知道有一些教程可以通过使用块来完成此技巧,但这些教程是不同的编程语言。
我的代码:
<div class="row">
<div class="col-12">
<ol>
<?php foreach ($text as $key => $texts): ?>
<li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br>
</li>
<?php endforeach ?>
</ol>
</div>
</div>
此代码将从图像中获取所有文本
输出:
如果您只想限制输出及其每次应该停止执行的相同字符串,请执行以下操作:
<div class="row">
<div class="col-12">
<ol>
<?php foreach ($text as $key => $texts): ?>
<?php if (strpos($texts->info()['description'], 'From Account') !== false) break; ?>
<li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br>
</li>
<?php endforeach ?>
</ol>
</div>
</div>
解释:
如果 $texts->info()['description']
包含文本 From Account
,则通过 break
结束 foreach 循环的执行。如果需要检查多个关键字 read this.
另一种解决方案是在将图像发送到 API 之前用 imagecrop()
裁剪图像。但是为此你需要确保它永远不会改变文本的大小/位置。
P.S。你确定每个人都应该在你的屏幕截图中看到那些私人数据吗?
更新1
正如你所问。这将是相同的代码,但使用 alternative syntax for control structures:
<div class="row">
<div class="col-12">
<ol>
<?php foreach ($text as $key => $texts): ?>
<?php if (strpos($texts->info()['description'], 'From Account') !== false): ?>
<?php break; ?>
<?php endif; ?>
<li><h6> <?php echo ucfirst($texts->info()['description']) ?></h6><<br><br>
</li>
<?php endforeach ?>
</ol>
</div>
</div>
也许这可以解决您的问题,因为同一页面包含此注释:
Mixing syntaxes in the same control block is not supported.
更新2
在你更新你的问题后,它现在更清楚了。输出不包含每个文本行的一个元素。相反,它包含多行文本。因此,我的第一个代码没有回显任何内容,因为它在第一个数组元素中找到 From Account
。
因此我们需要搜索字符串 From Account
和 剪切文本行:
<div class="row">
<div class="col-12">
<ol>
<?php foreach ($text as $key => $texts): ?>
<?php
$text = $texts->info()['description'];
// search for string
$pos = strpos($texts->info()['description'], 'From Account');
if ($pos !== false) {
// if the string was found cut the text
$text = substr($text, 0, $pos);
}
?>
<li><h6> <?php echo $text ?></h6><<br><br>
</li>
<?php endforeach ?>
</ol>
</div>
</div>
您可以选择在 <?php endforeach ?>
之前添加此内容以跳过所有以下数组元素:
<?php
if ($pos !== false) {
break;
}
?>
注意: @TerryLennox 使用 preg_match
来查找 From Account
。这与使用 strpos
(most prefer avoiding regex) 没有区别。但他的回答包含另一个很好的提示。他使用文本位置信息将文本逐行添加到新数组中。这可能非常有用,具体取决于您的目标如何 display/store 文本。
下面的代码适合我。我有一个 php 文件,test.php 和一个图像文件 /images/UUIPXl.png。
为了获取每一行文本,我迭代了来自 Google Vision 的文本注释,并创建了一个行项目数组。其中每一个都有一个 x 位置和一个文本值。
然后我按 x 位置对每一行进行排序并连接以创建一行文本。
最后,我们在获得所需的最终文本行后停止。
我得到这样的结果:
- maybank2u.com
- 打开账单支付
- 状态:成功
- 参考编号:2950211545
- 交易日期:2016年2月1日13:09:17
- 金额:RM100.00
- 来自账户 564155051577 WCA
php代码:
<?php
require 'vendor/autoload.php';
use Google\Cloud\Vision\VisionClient;
$config = ["keyFile" => json_decode(file_get_contents("./APIKey.json"), true) ];
$vision = new VisionClient($config);
$image = $vision->image(
fopen('./images/UUIPXl.png', 'r'),
['TEXT_DETECTION']
);
$textAnnotations = $vision->annotate($image)->text();
$rows = [];
// Function used to sort our lines.
function sortProc($a, $b)
{
if ($a["x"] === $b["x"]) {
return 0;
}
return ($a["x"] < $b["x"]) ? -1 : 1;
}
// Remove first row (complete text).
array_shift($textAnnotations);
// We should calculate this, use a reasonable value to begin with.
$lineHeight = 8;
foreach ($textAnnotations as $text) {
$key = round(((double)($text->info()["boundingPoly"]["vertices"][0]["y"]))/$lineHeight);
$x = (int)$text->info()["boundingPoly"]["vertices"][0]["x"];
$value = ["x" => $x, "text" => $text->description()];
if (!isset($rows[$key])) {
$rows[$key] = [];
}
$rows[$key][] = $value;
}
$text = [];
foreach ($rows as $key => $value) {
// Sort by x value.
usort($value, "sortProc");
// Concatenate each line
$result = array_reduce($value, function($acc, $elem) {
$acc .= " " . $elem["text"];
return $acc;
}, "");
$text[] = $result;
// Stop when we get here!
if (preg_match("/from account/i", $result)) {
break;
}
}
?>
<div class="row" style="padding: 20px;">
<div class="col-12">
<ul>
<?php foreach ($text as $row): ?>
<li><h3> <?php echo ucfirst($row) ?></h3></li>
<?php endforeach ?>
</ul>
</div>
</div>