# 在C#中進行單詞和字元OCR資料處理(坐標、自信度、界定框)
在對文件運行OCR後,僅提取文字通常是不夠的。 要在頁面上定位特定值、排除低質量檢測或在多欄佈局上重建自然閱讀順序,您需要每個單詞的坐標、頁碼、區域索引和自信度分數。
`AdvancedOcrResultBase`中披露這些資料。 對於識別版面文件的[`ReadDocumentAdvanced()`](https://ironsoftware.com/csharp/ocr/how-to/read-table-in-document/)和對於相機輸入的<a href="https://ironsoftware.com/csharp/ocr/how-to/read-photo/">`OcrResult.Words`集合可用的相同細節。</a>
本指南介紹五個常見模式:單詞資料迭代、重建閱讀順序、根據自信度過濾、在字元層級工作及從界定框中裁剪源圖像。
[開始免費30天試用](#trial-license)以在您的管道中測試這些集合。
!!!--LIBRARY_NUGET_INSTALL_BLOCK--!!!
*as-heading:2(快速入門:從OCR結果讀取單詞和字元資料)*
調用`result.Words`幾行程式碼來獲取每個被識別單詞的坐標、頁碼和自信度分數。
```cs
:title=Iterate words from an advanced OCR result
var result = new IronTesseract().ReadDocumentAdvanced(new OcrInput("scan.png"));
foreach (var word in result.Words)
Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf:{word.RegionConfidence:P0}");
```
<div class="hsg-featured-snippet">
<h3>最小化工作流(三步驟)</h3>
<ol>
<li><a class="js-modal-open" data-modal-id="trial-license-after-download" href="https://www.nuget.org/packages/IronOcr/">從NuGet下載C# OCR程式庫</a></li>
<li>在您的輸入上運行高級OCR,使用<code>ReadDocumentAdvanced</code>或<code>ReadPhoto</code></li>
<li>迭代<code>result.Words</code>或<code>result.Characters</code>以獲取坐標、信度和界定框</li>
</ol>
</div>
<br class="clear" />
## 您如何迭代具有坐標和自信度的單詞?
`Words`集合返回整個頁面上的每個檢測到的單詞。 每個條目(`AdvancedOcrElement`)展示了文字、像素坐標、尺寸、所屬頁面、識別包含它的檢測文字區塊的區域索引和該區域的自信度分數。
```csharp
using IronOcr;
using System;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("receipt.png");
var result = ocr.ReadDocumentAdvanced(input);
foreach (var word in result.Words)
{
Console.WriteLine(
$"Page {word.PageNumber} | " +
$"'{word.Text}' | " +
$"Position: ({word.X}, {word.Y}) | " +
$"Size: {word.Width}x{word.Height} | " +
$"Confidence: {word.RegionConfidence:P1}"
);
}
// ToString() override for diagnostic logging
Console.WriteLine(result.Words.First().ToString());
```
[[t:(`PageNumber` 是以1為基數:頁一是`0`。 這與大多數 .NET 集合不同,.NET集合採用零基數索引。})]] `RegionIndex` 遵循標準的0為基數的慣例。)]
)}]
要將坐標傳遞給圖形或裁剪API,使用`BoundingBox`屬性。 它將位置和尺寸打包成單個`IronSoftware.Drawing.Rectangle`。
## 您如何重建閱讀順序?
在多欄佈局中,`Words`集合迭代順序與頁面上的視覺閱讀順序不一致。 單詞按檢測到的區域分組,因此列和表格單元可以是未按順序返回的。
要重建自上而下、從左到右的自然順序,首先按Y坐標排序集合,然後在每行內按X排序。少量Y容差可將相同基準線上的單詞分組。
```csharp
using IronOcr;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("multi-column-doc.png");
var result = ocr.ReadDocumentAdvanced(input);
int targetPage = 1;
int lineThreshold = 10; // pixel tolerance for grouping same-line words
// Sort by line (Y), then left-to-right (X)
var pageWords = result.Words
.Where(w => w.PageNumber == targetPage)
.OrderBy(w => w.Y / lineThreshold)
.ThenBy(w => w.X)
.ToList();
foreach (var word in pageWords)
{
Console.Write($"{word.Text} ");
}
Console.WriteLine();
```
調整`lineThreshold`以匹配您的文件:標準300 DPI下12pt文字適用於10-15像素。 較大的標題或手寫輸入需要更寬的容差。 此模式對於多欄頁面和表格單元內特別有用,因為引擎將每個列或單元檢測為其自身的區域。
## 您如何過濾低自信度單詞?
要在低質量檢測達到您的資料庫、搜尋索引或下游提取前將其排除,可通過`RegionConfidence`過濾集合。 分數範圍從0.0到1.0,較高的值表示對檢測文字更大信心。
```csharp
using IronOcr;
using System;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("noisy-scan.png");
var result = ocr.ReadDocumentAdvanced(input);
double threshold = 0.75;
var highConfidenceWords = result.Words
.Where(w => w.RegionConfidence >= threshold)
.ToList();
var lowConfidenceWords = result.Words
.Where(w => w.RegionConfidence < threshold)
.ToList();
Console.WriteLine($"Accepted: {highConfidenceWords.Count} words");
Console.WriteLine($"Rejected: {lowConfidenceWords.Count} words");
// Log rejected words for manual review
foreach (var word in lowConfidenceWords)
{
Console.WriteLine(
$" LOW CONF: '{word.Text}' at ({word.X},{word.Y}) — {word.RegionConfidence:P1}"
);
}
```
對於混合質量的掃描(一些區域清晰一些區域降解),這樣可以防止低信度的輸出達到下游系統。 要在源頭提高自信度分數,[圖像預處理過濾器](https://ironsoftware.com/csharp/ocr/how-to/image-quality-correction/)(Deskew、DeNoise、Binarize)會在應用閾值之前改進質量。
## 您如何在字元層級進行迭代?
對於[OCR 驗證疊加層](https://ironsoftware.com/csharp/ocr/examples/highlight-texts-for-debugging/)、字元層級的對比真實背景或對表單欄位的精確空間分析,使用`Characters`集合。 它反映`Words`但在個別字元級別上解決。
```csharp
using IronOcr;
using System;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("form-field.png");
var result = ocr.ReadDocumentAdvanced(input);
foreach (var ch in result.Characters)
{
Console.WriteLine(
$"'{ch.Text}' | " +
$"Box: ({ch.X}, {ch.Y}, {ch.Width}, {ch.Height}) | " +
$"Page {ch.PageNumber}"
);
}
// ToString() override provides diagnostic-friendly output
Console.WriteLine(result.Characters.First().ToString());
```
[[i:(兩者`Characters`都是懶惰計算的並被快取。 首次存取觸發計算; 隨後的存取返回快取結果,因此第二次迭代不消耗成本。)]]
## 您如何使用界定框裁剪原始圖像?
要提取單詞的視覺區域以供驗證、註釋或構建標記訓練資料,將`AnyBitmap.CropRegion()`。 界定框直接映射到其在源圖像中的位置。
```csharp
using IronOcr;
using IronSoftware.Drawing;
using System;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("invoice.png");
var result = ocr.ReadDocumentAdvanced(input);
// Load the original image for cropping
var originalImage = AnyBitmap.FromFile("invoice.png");
// Find a specific word and crop its region
var targetWord = result.Words.FirstOrDefault(w => w.Text == "Total");
if (targetWord != null)
{
Rectangle cropRect = targetWord.BoundingBox;
AnyBitmap croppedRegion = originalImage.Clone(cropRect);
croppedRegion.SaveAs("total-region.png");
Console.WriteLine(
$"Cropped '{targetWord.Text}' from " +
$"({cropRect.X}, {cropRect.Y}, {cropRect.Width}, {cropRect.Height})"
);
}
```
此模式可擴展到批量操作:迭代每個單詞、裁剪每個框並導出標記資料集以供[自訂字體訓練](https://ironsoftware.com/csharp/ocr/how-to/ocr-custom-font-training/)或下游ML管道使用。 坐標反映預處理後的圖像; 如果像`EnhanceResolution`這樣的過濾器改變了尺寸,那麼界定框會匹配處理後的圖像,而不是磁碟上的原始圖像。
## 下一步
高階管道提供與`IronTesseract.Read()`相同的空間細節,以及附加的版面智慧。相關主題:
- [表格提取指南](https://ironsoftware.com/csharp/ocr/how-to/read-table-in-document/):涵蓋`ReadDocumentAdvanced`的結構化單元資料。
- [讀取OCR結果](https://ironsoftware.com/csharp/ocr/how-to/read-results/):標準管道的單詞資料。
- [圖像質量校正](https://ironsoftware.com/csharp/ocr/how-to/image-quality-correction/):提高自信度分數的預處理過濾器。
- [OCR教程](https://ironsoftware.com/csharp/ocr/tutorials/how-to-read-text-from-an-image-in-csharp-net/):新手使用者的端到端設置。
[開始您的免費30天試用](#trial-license)或[查看授權選項](#licensing)。
Install IronOCR by running the command above in the NuGet Package Manager Console, or search for the package in the NuGet Package Manager.
快速入門:從OCR結果讀取單詞和字元資料
調用result.Words幾行程式碼來獲取每個被識別單詞的坐標、頁碼和自信度分數。
1Install IronOCR with NuGet Package Manager
PM > Install-Package IronOcr
Install-Package IronOcr
2複製並運行這段程式碼片段。
var result = new IronTesseract().ReadDocumentAdvanced(new OcrInput("scan.png"));foreach (var word in result.Words)Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf:{word.RegionConfidence:P0}");
var result = new IronTesseract().ReadDocumentAdvanced(new OcrInput("scan.png"));
foreach (var word in result.Words)
Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf:{word.RegionConfidence:P0}");
Dim result = New IronTesseract().ReadDocumentAdvanced(New OcrInput("scan.png"))For Each word In result.WordsConsole.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf:{word.RegionConfidence:P0}")Next
Dim result = New IronTesseract().ReadDocumentAdvanced(New OcrInput("scan.png"))
For Each word In result.Words
Console.WriteLine($"{word.Text} @ ({word.X},{word.Y}) conf:{word.RegionConfidence:P0}")
Next
using IronOcr;using System;using System.Linq;var ocr = new IronTesseract();using var input = new OcrInput();input.LoadImage("receipt.png");var result = ocr.ReadDocumentAdvanced(input);foreach (var word in result.Words){Console.WriteLine( $"Page {word.PageNumber} | " + $"'{word.Text}' | " + $"Position: ({word.X}, {word.Y}) | " + $"Size: {word.Width}x{word.Height} | " + $"Confidence: {word.RegionConfidence:P1}" );}// ToString() override for diagnostic loggingConsole.WriteLine(result.Words.First().ToString());
using IronOcr;
using System;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("receipt.png");
var result = ocr.ReadDocumentAdvanced(input);
foreach (var word in result.Words)
{
Console.WriteLine(
$"Page {word.PageNumber} | " +
$"'{word.Text}' | " +
$"Position: ({word.X}, {word.Y}) | " +
$"Size: {word.Width}x{word.Height} | " +
$"Confidence: {word.RegionConfidence:P1}"
);
}
// ToString() override for diagnostic logging
Console.WriteLine(result.Words.First().ToString());
ImportsIronOcrImportsSystemImportsSystem.LinqDim ocr = New IronTesseract()Using input = New OcrInput() input.LoadImage("receipt.png") Dim result = ocr.ReadDocumentAdvanced(input) For Each word In result.WordsConsole.WriteLine( $"Page {word.PageNumber} | " + $"'{word.Text}' | " + $"Position: ({word.X}, {word.Y}) | " + $"Size: {word.Width}x{word.Height} | " + $"Confidence: {word.RegionConfidence:P1}" ) Next ' ToString() override for diagnostic loggingConsole.WriteLine(result.Words.First().ToString())EndUsing
Imports IronOcr
Imports System
Imports System.Linq
Dim ocr = New IronTesseract()
Using input = New OcrInput()
input.LoadImage("receipt.png")
Dim result = ocr.ReadDocumentAdvanced(input)
For Each word In result.Words
Console.WriteLine(
$"Page {word.PageNumber} | " +
$"'{word.Text}' | " +
$"Position: ({word.X}, {word.Y}) | " +
$"Size: {word.Width}x{word.Height} | " +
$"Confidence: {word.RegionConfidence:P1}"
)
Next
' ToString() override for diagnostic logging
Console.WriteLine(result.Words.First().ToString())
End Using
using IronOcr;using System.Linq;var ocr = new IronTesseract();using var input = new OcrInput();input.LoadImage("multi-column-doc.png");var result = ocr.ReadDocumentAdvanced(input);int targetPage = 1;int lineThreshold = 10; // pixel tolerance for grouping same-line words// Sort by line (Y), then left-to-right (X)var pageWords = result.Words .Where(w => w.PageNumber == targetPage) .OrderBy(w => w.Y / lineThreshold) .ThenBy(w => w.X) .ToList();foreach (var word in pageWords){Console.Write($"{word.Text} ");}Console.WriteLine();
using IronOcr;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("multi-column-doc.png");
var result = ocr.ReadDocumentAdvanced(input);
int targetPage = 1;
int lineThreshold = 10; // pixel tolerance for grouping same-line words
// Sort by line (Y), then left-to-right (X)
var pageWords = result.Words
.Where(w => w.PageNumber == targetPage)
.OrderBy(w => w.Y / lineThreshold)
.ThenBy(w => w.X)
.ToList();
foreach (var word in pageWords)
{
Console.Write($"{word.Text} ");
}
Console.WriteLine();
ImportsIronOcrImportsSystem.LinqDim ocr As New IronTesseract()Using input As New OcrInput() input.LoadImage("multi-column-doc.png") Dim result = ocr.ReadDocumentAdvanced(input) Dim targetPage AsInteger = 1 Dim lineThreshold AsInteger = 10 ' pixel tolerance for grouping same-line words ' Sort by line (Y), then left-to-right (X) Dim pageWords = result.Words _ .Where(Function(w) w.PageNumber = targetPage) _ .OrderBy(Function(w) w.Y \ lineThreshold) _ .ThenBy(Function(w) w.X) _ .ToList() For Each word In pageWordsConsole.Write($"{word.Text} ") NextConsole.WriteLine()EndUsing
Imports IronOcr
Imports System.Linq
Dim ocr As New IronTesseract()
Using input As New OcrInput()
input.LoadImage("multi-column-doc.png")
Dim result = ocr.ReadDocumentAdvanced(input)
Dim targetPage As Integer = 1
Dim lineThreshold As Integer = 10 ' pixel tolerance for grouping same-line words
' Sort by line (Y), then left-to-right (X)
Dim pageWords = result.Words _
.Where(Function(w) w.PageNumber = targetPage) _
.OrderBy(Function(w) w.Y \ lineThreshold) _
.ThenBy(Function(w) w.X) _
.ToList()
For Each word In pageWords
Console.Write($"{word.Text} ")
Next
Console.WriteLine()
End Using
using IronOcr;using System;using System.Linq;var ocr = new IronTesseract();using var input = new OcrInput();input.LoadImage("noisy-scan.png");var result = ocr.ReadDocumentAdvanced(input);double threshold = 0.75;var highConfidenceWords = result.Words .Where(w => w.RegionConfidence >= threshold) .ToList();var lowConfidenceWords = result.Words .Where(w => w.RegionConfidence < threshold) .ToList();Console.WriteLine($"Accepted: {highConfidenceWords.Count} words");Console.WriteLine($"Rejected: {lowConfidenceWords.Count} words");// Log rejected words for manual reviewforeach (var word in lowConfidenceWords){Console.WriteLine( $" LOW CONF: '{word.Text}' at ({word.X},{word.Y}) — {word.RegionConfidence:P1}" );}
using IronOcr;
using System;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("noisy-scan.png");
var result = ocr.ReadDocumentAdvanced(input);
double threshold = 0.75;
var highConfidenceWords = result.Words
.Where(w => w.RegionConfidence >= threshold)
.ToList();
var lowConfidenceWords = result.Words
.Where(w => w.RegionConfidence < threshold)
.ToList();
Console.WriteLine($"Accepted: {highConfidenceWords.Count} words");
Console.WriteLine($"Rejected: {lowConfidenceWords.Count} words");
// Log rejected words for manual review
foreach (var word in lowConfidenceWords)
{
Console.WriteLine(
$" LOW CONF: '{word.Text}' at ({word.X},{word.Y}) — {word.RegionConfidence:P1}"
);
}
ImportsIronOcrImportsSystemImportsSystem.LinqDim ocr = New IronTesseract()Using input = New OcrInput() input.LoadImage("noisy-scan.png") Dim result = ocr.ReadDocumentAdvanced(input) Dim threshold AsDouble = 0.75 Dim highConfidenceWords = result.Words _ .Where(Function(w) w.RegionConfidence >= threshold) _ .ToList() Dim lowConfidenceWords = result.Words _ .Where(Function(w) w.RegionConfidence < threshold) _ .ToList()Console.WriteLine($"Accepted: {highConfidenceWords.Count} words")Console.WriteLine($"Rejected: {lowConfidenceWords.Count} words") ' Log rejected words for manual review For Each word In lowConfidenceWordsConsole.WriteLine($" LOW CONF: '{word.Text}' at ({word.X},{word.Y}) — {word.RegionConfidence:P1}") NextEndUsing
Imports IronOcr
Imports System
Imports System.Linq
Dim ocr = New IronTesseract()
Using input = New OcrInput()
input.LoadImage("noisy-scan.png")
Dim result = ocr.ReadDocumentAdvanced(input)
Dim threshold As Double = 0.75
Dim highConfidenceWords = result.Words _
.Where(Function(w) w.RegionConfidence >= threshold) _
.ToList()
Dim lowConfidenceWords = result.Words _
.Where(Function(w) w.RegionConfidence < threshold) _
.ToList()
Console.WriteLine($"Accepted: {highConfidenceWords.Count} words")
Console.WriteLine($"Rejected: {lowConfidenceWords.Count} words")
' Log rejected words for manual review
For Each word In lowConfidenceWords
Console.WriteLine($" LOW CONF: '{word.Text}' at ({word.X},{word.Y}) — {word.RegionConfidence:P1}")
Next
End Using
using IronOcr;using System;using System.Linq;var ocr = new IronTesseract();using var input = new OcrInput();input.LoadImage("form-field.png");var result = ocr.ReadDocumentAdvanced(input);foreach (var ch in result.Characters){Console.WriteLine( $"'{ch.Text}' | " + $"Box: ({ch.X}, {ch.Y}, {ch.Width}, {ch.Height}) | " + $"Page {ch.PageNumber}" );}// ToString() override provides diagnostic-friendly outputConsole.WriteLine(result.Characters.First().ToString());
using IronOcr;
using System;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("form-field.png");
var result = ocr.ReadDocumentAdvanced(input);
foreach (var ch in result.Characters)
{
Console.WriteLine(
$"'{ch.Text}' | " +
$"Box: ({ch.X}, {ch.Y}, {ch.Width}, {ch.Height}) | " +
$"Page {ch.PageNumber}"
);
}
// ToString() override provides diagnostic-friendly output
Console.WriteLine(result.Characters.First().ToString());
ImportsIronOcrImportsSystemImportsSystem.LinqDim ocr = New IronTesseract()Using input = New OcrInput() input.LoadImage("form-field.png") Dim result = ocr.ReadDocumentAdvanced(input) For Each ch In result.CharactersConsole.WriteLine($"'{ch.Text}' | Box: ({ch.X}, {ch.Y}, {ch.Width}, {ch.Height}) | Page {ch.PageNumber}") Next ' ToString() override provides diagnostic-friendly outputConsole.WriteLine(result.Characters.First().ToString())EndUsing
Imports IronOcr
Imports System
Imports System.Linq
Dim ocr = New IronTesseract()
Using input = New OcrInput()
input.LoadImage("form-field.png")
Dim result = ocr.ReadDocumentAdvanced(input)
For Each ch In result.Characters
Console.WriteLine($"'{ch.Text}' | Box: ({ch.X}, {ch.Y}, {ch.Width}, {ch.Height}) | Page {ch.PageNumber}")
Next
' ToString() override provides diagnostic-friendly output
Console.WriteLine(result.Characters.First().ToString())
End Using
using IronOcr;using IronSoftware.Drawing;using System;using System.Linq;var ocr = new IronTesseract();using var input = new OcrInput();input.LoadImage("invoice.png");var result = ocr.ReadDocumentAdvanced(input);// Load the original image for croppingvar originalImage = AnyBitmap.FromFile("invoice.png");// Find a specific word and crop its regionvar targetWord = result.Words.FirstOrDefault(w => w.Text == "Total");if (targetWord != null){ Rectangle cropRect = targetWord.BoundingBox; AnyBitmap croppedRegion = originalImage.Clone(cropRect); croppedRegion.SaveAs("total-region.png");Console.WriteLine( $"Cropped '{targetWord.Text}' from " + $"({cropRect.X}, {cropRect.Y}, {cropRect.Width}, {cropRect.Height})" );}
using IronOcr;
using IronSoftware.Drawing;
using System;
using System.Linq;
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadImage("invoice.png");
var result = ocr.ReadDocumentAdvanced(input);
// Load the original image for cropping
var originalImage = AnyBitmap.FromFile("invoice.png");
// Find a specific word and crop its region
var targetWord = result.Words.FirstOrDefault(w => w.Text == "Total");
if (targetWord != null)
{
Rectangle cropRect = targetWord.BoundingBox;
AnyBitmap croppedRegion = originalImage.Clone(cropRect);
croppedRegion.SaveAs("total-region.png");
Console.WriteLine(
$"Cropped '{targetWord.Text}' from " +
$"({cropRect.X}, {cropRect.Y}, {cropRect.Width}, {cropRect.Height})"
);
}
ImportsIronOcrImportsIronSoftware.DrawingImportsSystemImportsSystem.LinqDim ocr = New IronTesseract()Using input As New OcrInput() input.LoadImage("invoice.png") Dim result = ocr.ReadDocumentAdvanced(input) ' Load the original image for cropping Dim originalImage = AnyBitmap.FromFile("invoice.png") ' Find a specific word and crop its region Dim targetWord = result.Words.FirstOrDefault(Function(w) w.Text = "Total") If targetWord IsNot Nothing Then Dim cropRect AsRectangle = targetWord.BoundingBox Dim croppedRegion AsAnyBitmap = originalImage.Clone(cropRect) croppedRegion.SaveAs("total-region.png")Console.WriteLine($"Cropped '{targetWord.Text}' from " & $"({cropRect.X}, {cropRect.Y}, {cropRect.Width}, {cropRect.Height})") End IfEndUsing
Imports IronOcr
Imports IronSoftware.Drawing
Imports System
Imports System.Linq
Dim ocr = New IronTesseract()
Using input As New OcrInput()
input.LoadImage("invoice.png")
Dim result = ocr.ReadDocumentAdvanced(input)
' Load the original image for cropping
Dim originalImage = AnyBitmap.FromFile("invoice.png")
' Find a specific word and crop its region
Dim targetWord = result.Words.FirstOrDefault(Function(w) w.Text = "Total")
If targetWord IsNot Nothing Then
Dim cropRect As Rectangle = targetWord.BoundingBox
Dim croppedRegion As AnyBitmap = originalImage.Clone(cropRect)
croppedRegion.SaveAs("total-region.png")
Console.WriteLine($"Cropped '{targetWord.Text}' from " &
$"({cropRect.X}, {cropRect.Y}, {cropRect.Width}, {cropRect.Height})")
End If
End Using
How can OCR results be used for custom font training or machine learning?
OCR results, including cropped image regions and labeled datasets derived from bounding boxes, can be used to train custom fonts or feed machine learning pipelines. IronOCR facilitates these processes with its detailed spatial data extraction capabilities.