IronOCR OCR 프로그램으로 C#에서 문서 표 이미지 텍스트 변환하는 방법
IronOCR는 ReadDocumentAdvanced 메서드를 사용하여 이미지 텍스트 변환을 통해 병합된 셀을 포함한 인보이스와 같은 복잡한 구조와 기본 셀을 가진 간단한 테이블 모두를 처리하면서 고급 머신 러닝 모델로 PDF 및 이미지에서 테이블 데이터를 추출할 수 있도록 C# 개발자에게 제공합니다.
일반 Tesseract를 사용하여 표에서 데이터를 추출하는 것은 텍스트가 셀에 존재하고 문서 전체에 드문드문 흩어져 있는 경우가 많기 때문에 어려울 수 있습니다. 하지만 저희 라이브러리에는 테이블 데이터를 정확하게 감지하고 추출하도록 학습 및 미세 조정된 머신 러닝 모델이 포함되어 있습니다. IronOCR은 재무 보고서, 재고 목록 또는 송장 데이터를 처리하든 관계없이 구조화된 데이터를 효율적으로 분석하는 도구를 제공합니다.
간단한 테이블의 경우, 표준 OcrInput 클래스를 사용하여 간단한 테이블 감지에 의존하세요. 보다 복잡한 구조의 경우, 당사의 독점 ReadDocumentAdvanced 메서드는 표를 효과적으로 구문 분석하고 데이터를 제공하여 견고한 결과를 제공합니다. 이 고급 방법은 머신 러닝을 활용하여 기존 OCR이 종종 어려움을 겪는 표 레이아웃, 병합된 셀 및 복잡한 서식을 이해합니다.
빠른 시작: 한 번의 호출로 복잡한 테이블 셀 추출
몇 분 안에 시작하세요. 이 예제는 복잡한 문서에서 세부적인 테이블 셀 데이터를 제공하는 ReadDocumentAdvanced을 사용하는 단일 IronOCR 호출 방법을 보여줍니다.
PDF 파일을 불러와 고급 표 감지 기능을 적용하고 셀 정보 목록을 직접 반환함으로써 사용 편의성을 보여줍니다.
-
NuGet 패키지 관리자를 사용하여 https://www.nuget.org/packages/IronOcr 설치하기
PM > Install-Package IronOcr -
다음 코드 조각을 복사하여 실행하세요.
var cells = new IronTesseract().ReadDocumentAdvanced(new OcrInput().LoadPdf("invoiceTable.pdf")).Tables.First().CellInfos; -
실제 운영 환경에서 테스트할 수 있도록 배포하세요.
무료 체험판으로 오늘 프로젝트에서 IronOCR 사용 시작하기
다음 단계는 IronOCR을 사용하여 표를 읽는 방법을 안내합니다.
- 테이블에서 데이터를 추출하는 C# 라이브러리를 다운로드하세요.
- 이미지와 PDF 문서를 추출할 수 있도록 준비하세요.
- 테이블 감지를 활성화하려면 `ReadDataTables` 속성을 true로 설정하십시오.
- 복잡한 표의 경우 `ReadDocumentAdvanced` 메서드를 사용하십시오.
- 이러한 방법으로 검출된 데이터를 추출합니다.
간단한 표에서 데이터를 추출하는 방법은 무엇인가요?
ReadDataTables 속성을 true로 설정하면 Tesseract를 사용하여 표 감지를 사용할 수 있습니다. 이 방법은 셀 경계가 명확하고 병합된 셀이 없는 기본적인 표에 효과적입니다. 이 기능을 테스트하기 위해 간단한 표 형식의 PDF 파일을 만들었습니다. 여기에서 다운로드하실 수 있습니다: ' simple-table.pdf '. 이 방법을 사용하면 셀 병합이 없는 단순 테이블을 감지할 수 있습니다. 더 복잡한 표의 경우 아래에 설명된 방법을 참조하십시오.
표준 테이블 감지 방법은 특히 다음과 같은 경우에 효과적입니다.
- 스프레드시트 내보내기
- 일관된 행/열 구조를 가진 기본 데이터 테이블
- 표 형식 데이터가 포함된 보고서
- 간단한 재고 목록
일반적으로 PDF OCR 텍스트 추출 작업을 하는 경우, 이 방법은 IronOCR의 광범위한 문서 처리 기능과 완벽하게 통합됩니다.
:path=/static-assets/ocr/content-code-examples/how-to/read-table-in-document-with-tesseract.cs
using IronOcr;
using System;
using System.Data;
// Instantiate OCR engine
var ocr = new IronTesseract();
// Enable table detection
ocr.Configuration.ReadDataTables = true;
using var input = new OcrPdfInput("simple-table.pdf");
var result = ocr.Read(input);
// Retrieve the data
var table = result.Tables[0].DataTable;
// Print out the table data
foreach (DataRow row in table.Rows)
{
foreach (var item in row.ItemArray)
{
Console.Write(item + "\t");
}
Console.WriteLine();
}
Imports Microsoft.VisualBasic
Imports IronOcr
Imports System
Imports System.Data
' Instantiate OCR engine
Private ocr = New IronTesseract()
' Enable table detection
ocr.Configuration.ReadDataTables = True
Dim input = New OcrPdfInput("simple-table.pdf")
Dim result = ocr.Read(input)
' Retrieve the data
Dim table = result.Tables(0).DataTable
' Print out the table data
For Each row As DataRow In table.Rows
For Each item In row.ItemArray
Console.Write(item & vbTab)
Next item
Console.WriteLine()
Next row
복잡한 송장 표를 어떻게 읽을 수 있나요?
비즈니스 환경에서 흔히 볼 수 있는 복잡한 표 중 하나는 송장입니다. 송장은 행과 열로 이루어진 복잡한 데이터 표이며, 종종 셀이 병합되거나, 열 너비가 다르거나, 중첩된 구조를 가지고 있습니다. IronOCR와 함께, 우리는 ReadDocumentAdvanced 메서드를 사용하여 이를 효과적으로 처리합니다. 이 과정은 문서를 스캔하고, 표 구조를 파악하고, 데이터를 추출하는 것을 포함합니다. 이 예시에서는 ' invoiceTable.pdf ' 파일을 사용하여 IronOCR이 송장에서 모든 정보를 추출하는 방법을 보여줍니다.
ReadDocumentAdvanced 메서드는 기본 IronOCR 패키지와 함께 IronOcr.Extensions.AdvancedScan 패키지를 설치해야 합니다. 이 확장 프로그램은 복잡한 문서 레이아웃에 맞게 특별히 학습된 고급 머신 러닝 기능을 제공합니다.
)}]
:path=/static-assets/ocr/content-code-examples/how-to/read-table-in-document-with-ml.cs
using IronOcr;
using System.Linq;
// Instantiate OCR engine
var ocr = new IronTesseract();
using var input = new OcrInput();
input.LoadPdf("invoiceTable.pdf");
// Perform OCR
var result = ocr.ReadDocumentAdvanced(input);
var cellList = result.Tables.First().CellInfos;
Imports IronOcr
Imports System.Linq
' Instantiate OCR engine
Dim ocr = New IronTesseract()
Using input As New OcrInput()
input.LoadPdf("invoiceTable.pdf")
' Perform OCR
Dim result = ocr.ReadDocumentAdvanced(input)
Dim cellList = result.Tables.First().CellInfos
End Using
이 방법은 문서의 텍스트 데이터를 테두리로 둘러싸인 텍스트와 테두리가 없는 텍스트, 이렇게 두 가지 범주로 나눕니다. 테두리가 있는 콘텐츠의 경우, 라이브러리는 테이블 구조에 따라 해당 콘텐츠를 하위 섹션으로 더 세분화합니다. 이 방법은 다음과 같은 상황에서 탁월한 성능을 발휘합니다:
- 설명이 다양한 송장 품목
- 다중 열 가격 분석
- 배송 및 청구 주소 블록
- 세금 및 총액 계산 부분
- 머리글 및 바닥글 정보
결과는 아래와 같습니다. 이 방법은 테두리로 둘러싸인 정보에 초점을 맞추기 때문에 여러 행에 걸쳐 병합된 셀은 단일 셀로 처리됩니다.
추출된 데이터는 어떤 형태인가요?
추출된 테이블 셀을 어떻게 정리하고 처리해야 하나요?
현재 구현에서는 추출된 세포들이 아직 제대로 정리되지 않았습니다. 하지만 각 셀에는 X, Y 좌표, 크기 등과 같은 귀중한 정보가 담겨 있습니다. 이 데이터를 활용하면 다양한 용도로 사용할 수 있는 헬퍼 클래스를 만들 수 있습니다. 세포 정보에는 다음이 포함됩니다.
- 정확한 위치 지정을 위한 X/Y 좌표
- 너비 및 높이 치수
- 텍스트 내용
- 신뢰도 점수
- 세포 간 관계
이러한 상세 정보를 통해 프로그래밍 방식으로 테이블 구조를 재구성하고 데이터 추출을 위한 사용자 지정 로직을 적용할 수 있습니다. 이러한 좌표를 사용하여 후속 작업에서 특정 영역을 대상으로 OCR 처리를 수행 할 수 있습니다.
다음은 몇 가지 기본적인 도우미 메서드입니다.
using System;
using System.Collections.Generic;
using System.Linq;
// A helper class to process table data by sorting cells based on coordinates
public static class TableProcessor
{
// Method to organize cells by their coordinates (Y top to bottom, X left to right)
public static List<CellInfo> OrganizeCellsByCoordinates(List<CellInfo> cells)
{
// Sort cells by Y (top to bottom), then by X (left to right)
var sortedCells = cells
.OrderBy(cell => cell.CellRect.Y)
.ThenBy(cell => cell.CellRect.X)
.ToList();
return sortedCells;
}
// Example method demonstrating how to process multiple tables
public static void ProcessTables(Tables tables)
{
foreach (var table in tables)
{
var sortedCells = OrganizeCellsByCoordinates(table.CellInfos);
Console.WriteLine("Organized Table Cells:");
// Initialize previous Y coordinate
int previousY = sortedCells.Any() ? sortedCells.First().CellRect.Y : 0;
foreach (var cell in sortedCells)
{
// Print a new line if the Y-coordinate changes, indicating a new row
if (Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8)
{
Console.WriteLine(); // Start a new row
previousY = cell.CellRect.Y;
}
// Print the cell text followed by a tab
Console.Write($"{cell.CellText}\t");
}
Console.WriteLine("\n--- End of Table ---"); // End of a table
}
}
// Method to extract a specific row by the given index
public static List<CellInfo> ExtractRowByIndex(TableInfo table, int rowIndex)
{
if (table == null || table.CellInfos == null || !table.CellInfos.Any())
{
throw new ArgumentException("Table is empty or invalid.");
}
var sortedCells = OrganizeCellsByCoordinates(table.CellInfos);
List<List<CellInfo>> rows = new List<List<CellInfo>>();
// Group cells into rows based on Y coordinates
int previousY = sortedCells.First().CellRect.Y;
List<CellInfo> currentRow = new List<CellInfo>();
foreach (var cell in sortedCells)
{
if (Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8)
{
// Store the completed row and start a new one
rows.Add(new List<CellInfo>(currentRow));
currentRow.Clear();
previousY = cell.CellRect.Y;
}
currentRow.Add(cell);
}
// Add the last row if it wasn't added yet
if (currentRow.Any())
{
rows.Add(currentRow);
}
// Retrieve the specified row
if (rowIndex < 0 || rowIndex >= rows.Count)
{
throw new IndexOutOfRangeException($"Row index {rowIndex} is out of range.");
}
return rows[rowIndex];
}
}
using System;
using System.Collections.Generic;
using System.Linq;
// A helper class to process table data by sorting cells based on coordinates
public static class TableProcessor
{
// Method to organize cells by their coordinates (Y top to bottom, X left to right)
public static List<CellInfo> OrganizeCellsByCoordinates(List<CellInfo> cells)
{
// Sort cells by Y (top to bottom), then by X (left to right)
var sortedCells = cells
.OrderBy(cell => cell.CellRect.Y)
.ThenBy(cell => cell.CellRect.X)
.ToList();
return sortedCells;
}
// Example method demonstrating how to process multiple tables
public static void ProcessTables(Tables tables)
{
foreach (var table in tables)
{
var sortedCells = OrganizeCellsByCoordinates(table.CellInfos);
Console.WriteLine("Organized Table Cells:");
// Initialize previous Y coordinate
int previousY = sortedCells.Any() ? sortedCells.First().CellRect.Y : 0;
foreach (var cell in sortedCells)
{
// Print a new line if the Y-coordinate changes, indicating a new row
if (Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8)
{
Console.WriteLine(); // Start a new row
previousY = cell.CellRect.Y;
}
// Print the cell text followed by a tab
Console.Write($"{cell.CellText}\t");
}
Console.WriteLine("\n--- End of Table ---"); // End of a table
}
}
// Method to extract a specific row by the given index
public static List<CellInfo> ExtractRowByIndex(TableInfo table, int rowIndex)
{
if (table == null || table.CellInfos == null || !table.CellInfos.Any())
{
throw new ArgumentException("Table is empty or invalid.");
}
var sortedCells = OrganizeCellsByCoordinates(table.CellInfos);
List<List<CellInfo>> rows = new List<List<CellInfo>>();
// Group cells into rows based on Y coordinates
int previousY = sortedCells.First().CellRect.Y;
List<CellInfo> currentRow = new List<CellInfo>();
foreach (var cell in sortedCells)
{
if (Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8)
{
// Store the completed row and start a new one
rows.Add(new List<CellInfo>(currentRow));
currentRow.Clear();
previousY = cell.CellRect.Y;
}
currentRow.Add(cell);
}
// Add the last row if it wasn't added yet
if (currentRow.Any())
{
rows.Add(currentRow);
}
// Retrieve the specified row
if (rowIndex < 0 || rowIndex >= rows.Count)
{
throw new IndexOutOfRangeException($"Row index {rowIndex} is out of range.");
}
return rows[rowIndex];
}
}
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Linq
' A helper class to process table data by sorting cells based on coordinates
Public Module TableProcessor
' Method to organize cells by their coordinates (Y top to bottom, X left to right)
Public Function OrganizeCellsByCoordinates(ByVal cells As List(Of CellInfo)) As List(Of CellInfo)
' Sort cells by Y (top to bottom), then by X (left to right)
Dim sortedCells = cells.OrderBy(Function(cell) cell.CellRect.Y).ThenBy(Function(cell) cell.CellRect.X).ToList()
Return sortedCells
End Function
' Example method demonstrating how to process multiple tables
Public Sub ProcessTables(ByVal tables As Tables)
For Each table In tables
Dim sortedCells = OrganizeCellsByCoordinates(table.CellInfos)
Console.WriteLine("Organized Table Cells:")
' Initialize previous Y coordinate
Dim previousY As Integer = If(sortedCells.Any(), sortedCells.First().CellRect.Y, 0)
For Each cell In sortedCells
' Print a new line if the Y-coordinate changes, indicating a new row
If Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8 Then
Console.WriteLine() ' Start a new row
previousY = cell.CellRect.Y
End If
' Print the cell text followed by a tab
Console.Write($"{cell.CellText}" & vbTab)
Next cell
Console.WriteLine(vbLf & "--- End of Table ---") ' End of a table
Next table
End Sub
' Method to extract a specific row by the given index
Public Function ExtractRowByIndex(ByVal table As TableInfo, ByVal rowIndex As Integer) As List(Of CellInfo)
If table Is Nothing OrElse table.CellInfos Is Nothing OrElse Not table.CellInfos.Any() Then
Throw New ArgumentException("Table is empty or invalid.")
End If
Dim sortedCells = OrganizeCellsByCoordinates(table.CellInfos)
Dim rows As New List(Of List(Of CellInfo))()
' Group cells into rows based on Y coordinates
Dim previousY As Integer = sortedCells.First().CellRect.Y
Dim currentRow As New List(Of CellInfo)()
For Each cell In sortedCells
If Math.Abs(cell.CellRect.Y - previousY) > cell.CellRect.Height * 0.8 Then
' Store the completed row and start a new one
rows.Add(New List(Of CellInfo)(currentRow))
currentRow.Clear()
previousY = cell.CellRect.Y
End If
currentRow.Add(cell)
Next cell
' Add the last row if it wasn't added yet
If currentRow.Any() Then
rows.Add(currentRow)
End If
' Retrieve the specified row
If rowIndex < 0 OrElse rowIndex >= rows.Count Then
Throw New IndexOutOfRangeException($"Row index {rowIndex} is out of range.")
End If
Return rows(rowIndex)
End Function
End Module
테이블 추출을 위한 모범 사례
IronOCR에서 테이블 추출 작업을 할 때는 다음과 같은 모범 사례를 고려하십시오.
-
문서 품질 : 해상도가 높은 문서일수록 더 나은 결과를 얻을 수 있습니다. 스캔한 문서의 경우 최소 300 DPI를 확인하십시오.
-
전처리 : 품질이 낮거나 표가 왜곡된 문서의 경우, 처리 전에 IronOCR의 이미지 보정 기능을 사용하는 것을 고려해 보세요.
-
성능 : 여러 테이블이 포함된 대용량 문서의 경우, 페이지를 병렬로 처리하기 위해 멀티스레딩 및 비동기 지원을 활용하는 것을 고려하십시오.
-
출력 옵션 : 테이블 데이터를 추출한 후 다양한 형식으로 결과를 내보낼 수 있습니다. 데이터 출력 옵션 과 처리된 문서에서 검색 가능한 PDF를 생성하는 방법에 대해 자세히 알아보세요.
- 스트림 처리 : 웹 애플리케이션이나 메모리 내 문서를 사용하는 시나리오의 경우 파일 시스템 작업을 피하기 위해 PDF 스트림에 OCR을 사용하는 것을 고려해 보세요.
요약
IronOCR은 표준 Tesseract 기반 탐지 및 고급 머신 러닝 방법을 통해 강력한 테이블 추출 기능을 제공합니다. 표준 접근법은 간단한 테이블에 잘 작동하며, ReadDocumentAdvanced 메서드는 인보이스와 같은 복잡한 문서에 뛰어납니다. 제공된 도우미 메서드를 사용하면 추출된 데이터를 특정 요구 사항에 맞게 구성하고 처리할 수 있습니다.
IronOCR의 다양한 기능을 살펴보고 문서 처리 워크플로를 개선하며 .NET 애플리케이션에서 광학 문자 인식의 잠재력을 최대한 활용해 보세요.
자주 묻는 질문
C#에서 PDF 및 이미지에서 표 데이터를 추출하는 방법은 무엇입니까?
IronOCR은 C# 개발자가 고급 머신러닝 모델을 사용하여 PDF 및 이미지에서 표 데이터를 추출할 수 있도록 지원합니다. 간단한 표의 경우, ReadDataTables 속성을 true로 설정한 OcrInput 클래스를 사용하십시오. 병합된 셀이 있는 복잡한 표의 경우, 더 정확한 결과를 얻으려면 ReadDocumentAdvanced 메서드를 사용하십시오.
단순 테이블 추출과 복잡 테이블 추출의 차이점은 무엇인가요?
IronOCR에서 간단한 표 추출은 Tesseract의 ReadDataTables 속성을 사용하며, 셀 경계가 명확한 기본 표에 적합합니다. 복잡한 표 추출에는 ReadDocumentAdvanced 메서드가 필요하며, 이 메서드는 머신 러닝을 사용하여 병합된 셀, 송장 및 복잡한 서식을 처리합니다.
복잡한 표에서 데이터를 빠르게 추출하는 방법은 무엇인가요?
IronOCR의 ReadDocumentAdvanced 메서드를 한 번에 호출하여 사용할 수 있습니다. 예를 들어, 다음과 같이 작성할 수 있습니다. var cells = new IronTesseract().ReadDocumentAdvanced(new OcrInput().LoadPdf('invoiceTable.pdf')).Tables.First().CellInfos; 이 코드는 머신 러닝을 활용하여 테이블 레이아웃과 복잡한 서식을 이해합니다.
간단한 테이블 감지 기능에 가장 적합한 문서 유형은 무엇인가요?
IronOCR의 간단한 테이블 감지 방법은 스프레드시트 내보내기, 일관된 행/열 구조를 가진 기본 데이터 테이블, 표 형식 데이터가 포함된 보고서, 병합된 셀이 없는 간단한 재고 목록에서 특히 효과적입니다.
기본 테이블에 대한 테이블 감지 기능을 어떻게 활성화할 수 있나요?
IronOCR에서 기본 테이블에 대한 테이블 감지 기능을 활성화하려면 ReadDataTables 속성을 true로 설정하십시오. 이렇게 하면 Tesseract의 테이블 감지 기능을 사용할 수 있으며, 셀 경계가 명확하고 병합된 셀이 없는 테이블에서 잘 작동합니다.
도서관에서 복잡한 레이아웃의 청구서와 재무 보고서를 처리할 수 있습니까?
네, IronOCR의 ReadDocumentAdvanced 메서드는 송장이나 재무 보고서와 같은 복잡한 문서를 처리하도록 특별히 설계되었습니다. 이 메서드는 병합된 셀과 복잡한 서식이 포함된 표에서 데이터를 감지하고 추출하도록 학습된 머신 러닝 모델을 사용합니다.

