IronOCR 사용한 Acrobat DC OCR 대체 프로그램
Google Cloud Vision이 이미지를 통해 단일 문자라도 읽기 전에, 귀하는 이미 GCP 프로젝트를 생성하고 Vision API를 활성화하고, 서비스 계정을 만든 후, RSA 개인 키가 포함된 JSON 키 파일을 다운로드하며, 귀하의 코드를 실행할 모든 서버에 GOOGLE_APPLICATION_CREDENTIALS 환경 변수를 설정하고, 1,800-분당-요청-기본 쿼터가 소진될 때 StatusCode.ResourceExhausted을 처리하는 재시도 루프를 작성한 상태입니다. 그러고 나면 PDF 처리가 Google.Cloud.Storage.V1이라는 두 번째 NuGet 패키지, GCS 버킷, 비동기 폴링 루프, JSON 출력 파싱, 클라우드 스토리지에서 객체를 삭제하기 위한 정리 단계가 필요하다는 것을 알게 됩니다. Google Cloud Vision은 머신러닝 기반 모델이 중국어, 일본어, 한국어 텍스트에서 높은 정확도를 보이는 등 확실한 강점을 가지고 있지만, 실제 운영 환경에서 단 하나의 문서라도 처리하기 전에는 해결해야 할 과제가 상당히 많습니다.
구글 클라우드 비전 이해하기
Google Cloud Vision은 Google의 머신러닝 인프라를 기반으로 하는 클라우드 기반 이미지 분석 API입니다. OCR의 경우, 두 가지 뚜렷한 기능 유형을 제공합니다: TEXT_DETECTION, 거리 표지판 및 제품 라벨과 같은 자연적인 장면에서 희소한 텍스트에 최적화된 것과 DOCUMENT_TEXT_DETECTION, 단락, 테이블 및 다중 열 레이아웃이 있는 밀집 문서에 최적화된 것. 이 서비스는 gRPC 전송 계층을 래핑하고 Protobuf 생성 응답 객체를 반환하는 Google.Cloud.Vision.V1 NuGet 패키지를 통해 호출됩니다.
주요 건축적 특징:
- 클라우드 전용 처리: 모든 문서는 Google의 인프라로 전송되어 처리됩니다. 온프레미스 모드는 없습니다.
- 서비스 계정 인증: 인증에는 RSA 개인 키, 클라이언트 이메일 및 프로젝트 ID가 포함된 JSON 키 파일이 필요합니다. 파일은 모든 호스트에 배포되어야 하며
GOOGLE_APPLICATION_CREDENTIALS환경 변수 또는 Google Application Default Credentials을 통해 참조되어야 합니다. - PDF 처리에는 GCS 및 비동기 처리가 필요합니다. PDF 문서 처리는 직접적인 API 호출이 아닙니다. PDF는 Google Cloud Storage에 업로드되고
AsyncBatchAnnotateFilesAsync를 통해 제출되어야 하며, 완료될 때까지 폴링한 후 GCS에서 JSON 출력 파일을 다운로드하고 파싱합니다. - Protobuf 응답 계층 구조:
DOCUMENT_TEXT_DETECTION이TextAnnotationProtobuf 객체를 반환하며,Pages→Blocks→Paragraphs→Words→Symbols의 계층 구조를 가집니다. 단락 텍스트를 추출하려면 4단계에 걸쳐 반복 작업을 수행하고 개별 기호 문자열을 연결해야 합니다. - 속도 제한: 기본 할당량은 분당 1,800건의 요청입니다. 이 임계값 이상에서 일괄 처리하는 경우
StatusCode.ResourceExhausted응답에 대해 재시도 로직을 구현해야 합니다. - FedRAMP 인증 상태: Google Cloud Vision은 페드램 인증을 받지 않았으므로 Azure Computer Vision(FedRAMP High) 또는 AWS Textract(FedRAMP High)와 같은 대안이 있는 연방 기관 사용 사례에는 적합하지 않습니다.
- 가격:
TEXT_DETECTION및DOCUMENT_TEXT_DETECTION에 대한 1,000 이미지 당 요금은 월 1,000개의 무료 단위 이후 시작됩니다; PDF 비동기 처리는 페이지당 청구됩니다. 현재 요금은 Google Cloud Vision 가격 페이지를 참조하십시오.
서비스 계정 자격 증명 설정
google-vision-vs-ironocr-examples.cs의 다음 코드는 클라이언트 초기화 패턴을 설명합니다. 초기화 라인이 숨기는 것은 전제조건입니다: GOOGLE_APPLICATION_CREDENTIALS 환경 변수는 현재 컴퓨터의 유효한 서비스 계정 JSON 키 파일을 이미 가리키고 있어야 합니다:
using Google.Cloud.Vision.V1;
public class GoogleVisionService
{
private readonly ImageAnnotatorClient _client;
public GoogleVisionService()
{
// Requires GOOGLE_APPLICATION_CREDENTIALS env var
// pointing to a service account JSON key file
_client = ImageAnnotatorClient.Create();
}
public string DetectText(string imagePath)
{
// WARNING: Image uploaded to Google Cloud
var image = Image.FromFile(imagePath);
var response = _client.DetectText(image);
if (response.Count > 0)
{
return response[0].Description;
}
return string.Empty;
}
}
using Google.Cloud.Vision.V1;
public class GoogleVisionService
{
private readonly ImageAnnotatorClient _client;
public GoogleVisionService()
{
// Requires GOOGLE_APPLICATION_CREDENTIALS env var
// pointing to a service account JSON key file
_client = ImageAnnotatorClient.Create();
}
public string DetectText(string imagePath)
{
// WARNING: Image uploaded to Google Cloud
var image = Image.FromFile(imagePath);
var response = _client.DetectText(image);
if (response.Count > 0)
{
return response[0].Description;
}
return string.Empty;
}
}
Imports Google.Cloud.Vision.V1
Public Class GoogleVisionService
Private ReadOnly _client As ImageAnnotatorClient
Public Sub New()
' Requires GOOGLE_APPLICATION_CREDENTIALS env var
' pointing to a service account JSON key file
_client = ImageAnnotatorClient.Create()
End Sub
Public Function DetectText(imagePath As String) As String
' WARNING: Image uploaded to Google Cloud
Dim image = Image.FromFile(imagePath)
Dim response = _client.DetectText(image)
If response.Count > 0 Then
Return response(0).Description
End If
Return String.Empty
End Function
End Class
JSON 키 파일에는 RSA 개인 키, 클라이언트 이메일 및 프로젝트 식별자가 포함되어 있습니다. 이 파일은 소스 코드 관리 시스템에 절대 커밋해서는 안 되며, Docker 이미지에서 제외해야 하고, 주기적으로 로테이션해야 하며, 적절한 파일 시스템 권한으로 보호해야 합니다. 손상된 키는 GCP 콘솔에서 수동으로 취소할 때까지 API 액세스 권한을 부여합니다.
IronOCR이해하기
IronOCR 최적화된 Tesseract 5 엔진을 기반으로 구축된 .NET 용 상용 온프레미스 OCR 라이브러리입니다. 모든 문서를 로컬에서 처리하므로 클라우드 전송이나 인터넷 연결이 필요 없고, 제3자 데이터 처리도 필요하지 않습니다. 하나의 NuGet Install-Package (IronOcr)로 모든 것을 제공합니다: OCR 엔진, 자동 전처리 필터, 네이티브 PDF 지원, 그리고 개별 NuGet 패키지로 제공되는 125개 이상의 언어 팩.
주요 특징:
- 온프레미스 처리: 문서는 귀사 인프라를 벗어나지 않습니다. 외부 연결이 없는 에어갭 환경, 기밀 네트워크 및 Docker 컨테이너에서 작동합니다.
- 단일 NuGet 배포: tessdata 폴더가 필요 없고, 네이티브 라이브러리 관리도 필요 없으며, 라이선스 키 문자열 외에는 환경 변수가 필요하지 않습니다.
- 자동 전처리: 기울기 보정, 노이즈 제거, 대비 조정, 이진화 및 해상도 향상 필터는 품질이 낮은 입력에 자동으로 적용되며, 개별적으로 명시적으로 제어할 수도 있습니다.
- 네이티브 PDF 입력: PDF는
input.LoadPdf()를 통해 비동기 처리로 직접 로드됩니다. 암호로 보호된 PDF 파일에는 매개변수가 하나 필요합니다. - 구조화된
OcrResult: 결과는Text,Confidence,Pages,Paragraphs,Lines,Words,Barcodes를 .NET 객체 유형으로 노출합니다 — Protobuf 역직렬화도 없고, 기호 연결도 아닙니다. - 스레드 안전:
IronTesseract인스턴스는 병렬 사용에 안전합니다. 일괄 작업은 추가 구성이 필요 없이Parallel.ForEach을 사용할 수 있습니다. - 영구 라이선스: $999 Lite, $1,499 Plus, $2,999 Professional, $5,999 Unlimited — 한 번 구매로 거래량에 대한 비용 없음.
기능 비교
| 기능 | 구글 클라우드 비전 | IronOCR |
|---|---|---|
| 처리 모델 | 클라우드 전용 | 온프레미스 전용 |
| PDF 처리 | GCS + 비동기 API를 통해 | 직접적, 동기적 |
| 입증 | 서비스 계정 JSON 키 | 라이선스 키 문자열 |
| 페드램 인증 | 권한이 없습니다 | 해당 없음 (현장 판매) |
| 문서당 비용 | 페이지당 (자세한 내용은 Google Cloud Vision 가격 참조) | None |
| 오프라인/에어갭 | 아니요 | 예 |
상세 기능 비교
| 카테고리 | 기능 | 구글 클라우드 비전 | IronOCR |
|---|---|---|---|
| 입력 | 이미지 OCR | 예 | 예 |
| PDF OCR | GCS + 비동기 방식을 통해 (50줄 이상) | input.LoadPdf() (3줄) |
|
| 비밀번호로 보호된 PDF | 지원되지 않음 | LoadPdf(path, Password: "...") |
|
| 스트림 입력 | 예 | 예 | |
| URL 입력 | 아니요 | input.LoadImageFromUrl() |
|
| TIFF/GIF 멀티프레임 | 제한적 | 예 | |
| 인증 | 자격 증명 유형 | JSON 키 파일 + 환경 변수 | 라이선스 키 문자열 |
| 자격 순환 | 필수 (수동) | 필요하지 않음 | |
| CI/CD 비밀 키가 필요합니다 | 예 (키 파일) | 예 (라이선스 문자열만 해당) | |
| 처리 중 | 오프라인/에어갭 | 아니요 | 예 |
| 동기 처리 | 이미지 전용 | 이미지 및 PDF | |
| 요금 제한 | 기본값 1,800 요청/분 | 없음 (CPU 부하가 높음) | |
| 전처리(자동) | 없음(ML 기반) | 기울기 보정, 노이즈 제거, 대비 조정, 이진화, 해상도 향상 | |
| 산출 | 일반 텍스트 | 예 | 예 |
| 구조화된 결과(유형화됨) | Protobuf 계층 구조 | OcrResult (.NET 객체) |
|
| 신뢰도 점수 | 기호/단어당 | 단어별 및 전체 | |
| 검색 가능한 PDF 출력 | 아니요 | result.SaveAsSearchablePdf() |
|
| 바코드 판독 | 별도의 API 기능 | ocr.Configuration.ReadBarCodes = true |
|
| 영역 기반 OCR | 원산지가 없는 작물 | CropRectangle 입력 시 |
|
| 언어 | 언어 개수 | ~50 | NuGet 팩을 통해 125개 이상 |
| CJK 정확도 | 강력한 (ML 기반) | 좋음 (테서랙트 5 LSTM) | |
| 규정 준수 | 페드램 | 권한이 없습니다 | 해당 없음 (현장 판매) |
| HIPAA/ITAR | BAA + 복합 검토 | 제3자 처리 없음 | |
| GDPR 제28조 | DPA 필수 | 해당 사항 없음 (현지) | |
| 비용 | 가격 모델 | 현재 가격 문의는 Google에 문의. | 영구 ($5,999) |
인증 복잡성 및 자격 증명 관리
구글 클라우드 비전의 가장 과소평가된 비용은 이미지당 요금이 아닙니다. 이는 애플리케이션이 실행되는 모든 환경에서 서비스 계정 자격 증명을 관리하는 데 드는 운영상의 오버헤드입니다.
구글 클라우드 비전 접근 방식
클라이언트 초기화는 한 줄처럼 보이지만, 그 줄은 RpcException을 StatusCode.PermissionDenied과 함께 던지게 되며 7개의 전제조건이 갖추어져 있어야 합니다. google-cloud-vision-migration-examples.cs로부터, 자격증명 설정이 전체 이야기를 전달합니다:
public GoogleVisionCredentialSetup()
{
// BEFORE: Requires GOOGLE_APPLICATION_CREDENTIALS environment variable
// pointing to a service account JSON key file:
// export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
//
// The JSON file contains sensitive data:
// - private_key: RSA private key
// - client_email: service account email
// - project_id: GCP project identifier
//
// Security concerns:
// - Key file must never be committed to source control
// - Key file must be rotated periodically
// - Key file must be protected with file system permissions
// - Key file compromise grants API access until revoked
_client = ImageAnnotatorClient.Create();
}
public GoogleVisionCredentialSetup()
{
// BEFORE: Requires GOOGLE_APPLICATION_CREDENTIALS environment variable
// pointing to a service account JSON key file:
// export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
//
// The JSON file contains sensitive data:
// - private_key: RSA private key
// - client_email: service account email
// - project_id: GCP project identifier
//
// Security concerns:
// - Key file must never be committed to source control
// - Key file must be rotated periodically
// - Key file must be protected with file system permissions
// - Key file compromise grants API access until revoked
_client = ImageAnnotatorClient.Create();
}
Public Sub New()
' BEFORE: Requires GOOGLE_APPLICATION_CREDENTIALS environment variable
' pointing to a service account JSON key file:
' export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
'
' The JSON file contains sensitive data:
' - private_key: RSA private key
' - client_email: service account email
' - project_id: GCP project identifier
'
' Security concerns:
' - Key file must never be committed to source control
' - Key file must be rotated periodically
' - Key file must be protected with file system permissions
' - Key file compromise grants API access until revoked
_client = ImageAnnotatorClient.Create()
End Sub
Docker 기반 배포 환경에서는 JSON 키 파일을 시크릿 볼륨으로 마운트하거나 Kubernetes 시크릿을 통해 주입해야 합니다. 다중 지역 설정에서는 각 지역에 동일한 자격 증명 구성이 필요합니다. 키 순환은 모든 배포를 동시에 업데이트하거나 이전 키와 새 키가 모두 유효한 기간을 허용해야 하는 수동 프로세스입니다. 오류 처리 계층은 비례적으로 증가하며 — 생산 코드는 StatusCode.PermissionDenied, StatusCode.ResourceExhausted, StatusCode.Unavailable, 그리고 StatusCode.DeadlineExceeded를 위한 별개의 catch 블록을 필요로 합니다.
IronOCR접근법
IronOCR의 설정 은 라이선스 키 문자열입니다. 배포할 파일도 없고, 키 자체 외에는 환경 변수도 필요 없으며, 갱신 일정도 없습니다.
public IronOcrCredentialSetup()
{
// Simple license key - no key files, no environment variables required
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
?? "YOUR-LICENSE-KEY";
// 아니요 service accounts, no key rotation, no IAM configuration
_ocr = new IronTesseract();
}
public IronOcrCredentialSetup()
{
// Simple license key - no key files, no environment variables required
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
?? "YOUR-LICENSE-KEY";
// 아니요 service accounts, no key rotation, no IAM configuration
_ocr = new IronTesseract();
}
Public Sub New()
' Simple license key - no key files, no environment variables required
IronOcr.License.LicenseKey = If(Environment.GetEnvironmentVariable("IRONOCR_LICENSE"), "YOUR-LICENSE-KEY")
' 아니요 service accounts, no key rotation, no IAM configuration
_ocr = New IronTesseract()
End Sub
CI/CD 환경에서 라이선스 키는 단일 파이프라인 시크릿입니다. Docker에서는 단 하나의 환경 변수로 충분합니다. 마운트할 JSON 파일도 없고, 할당할 IAM 역할도 없으며, 상호 작용할 GCP 콘솔도 없습니다. 개발자가 팀에 합류하면 문자열 하나를 받습니다. 인증 관련 오류의 전체 발생 원인은 다음과 같습니다. 키가 유효하지 않거나 평가 기간이 만료되었습니다.
PDF 처리: GCS 파이프라인 vs 직접 로드
PDF 처리는 두 라이브러리 간의 운영상 차이가 구체화되는 부분입니다. Google Cloud Vision은 PDF 파일을 API 입력으로 직접 허용하지 않습니다. 파일은 Google Cloud Storage를 중간 단계로 거쳐야 합니다.
구글 클라우드 비전 접근 방식
google-cloud-vision-migration-examples.cs에서부터의 완전한 PDF 처리 흐름은 DownloadAndParseResultsAsync 구현 이전에 40개 이상의 줄로 실행되며 — 이 구현 자체는 GCS 출력 URI를 파싱하며, 결과 객체 나열, JSON 파일 다운로드, 페이지 간 텍스트 연결을 요구합니다:
public async Task<string> ProcessPdfAsync(string pdfPath)
{
// Step 1: Create storage client
var storageClient = StorageClient.Create();
var objectName = $"ocr-input/{Guid.NewGuid()}.pdf";
// Step 2: Upload PDF to GCS (document leaves your infrastructure)
using (var stream = File.OpenRead(pdfPath))
{
await storageClient.UploadObjectAsync(
_bucketName, objectName, "application/pdf", stream);
}
// Step 3: Build async annotation request
var asyncRequest = new AsyncAnnotateFileRequest
{
InputConfig = new InputConfig
{
GcsSource = new GcsSource { Uri = $"gs://{_bucketName}/{objectName}" },
MimeType = "application/pdf"
},
Features = { new기능{ Type = Feature.Types.Type.DocumentTextDetection } },
OutputConfig = new OutputConfig
{
GcsDestination = new GcsDestination { Uri = $"gs://{_bucketName}/ocr-output/" },
BatchSize = 1
}
};
// Step 4: Submit and wait for async operation
var operation = await _visionClient.AsyncBatchAnnotateFilesAsync(
new[] { asyncRequest });
var completedOperation = await operation.PollUntilCompletedAsync();
// Step 5: Download and parse results from GCS output
var outputUri = completedOperation.Result.Responses[0]
.OutputConfig.GcsDestination.Uri;
var text = await DownloadAndParseResultsAsync(storageClient, outputUri);
// Step 6: Clean up input file from GCS
await storageClient.DeleteObjectAsync(_bucketName, objectName);
return text;
}
public async Task<string> ProcessPdfAsync(string pdfPath)
{
// Step 1: Create storage client
var storageClient = StorageClient.Create();
var objectName = $"ocr-input/{Guid.NewGuid()}.pdf";
// Step 2: Upload PDF to GCS (document leaves your infrastructure)
using (var stream = File.OpenRead(pdfPath))
{
await storageClient.UploadObjectAsync(
_bucketName, objectName, "application/pdf", stream);
}
// Step 3: Build async annotation request
var asyncRequest = new AsyncAnnotateFileRequest
{
InputConfig = new InputConfig
{
GcsSource = new GcsSource { Uri = $"gs://{_bucketName}/{objectName}" },
MimeType = "application/pdf"
},
Features = { new기능{ Type = Feature.Types.Type.DocumentTextDetection } },
OutputConfig = new OutputConfig
{
GcsDestination = new GcsDestination { Uri = $"gs://{_bucketName}/ocr-output/" },
BatchSize = 1
}
};
// Step 4: Submit and wait for async operation
var operation = await _visionClient.AsyncBatchAnnotateFilesAsync(
new[] { asyncRequest });
var completedOperation = await operation.PollUntilCompletedAsync();
// Step 5: Download and parse results from GCS output
var outputUri = completedOperation.Result.Responses[0]
.OutputConfig.GcsDestination.Uri;
var text = await DownloadAndParseResultsAsync(storageClient, outputUri);
// Step 6: Clean up input file from GCS
await storageClient.DeleteObjectAsync(_bucketName, objectName);
return text;
}
Imports System
Imports System.IO
Imports System.Threading.Tasks
Public Class PdfProcessor
Private _bucketName As String
Private _visionClient As VisionClient
Public Async Function ProcessPdfAsync(pdfPath As String) As Task(Of String)
' Step 1: Create storage client
Dim storageClient = StorageClient.Create()
Dim objectName = $"ocr-input/{Guid.NewGuid()}.pdf"
' Step 2: Upload PDF to GCS (document leaves your infrastructure)
Using stream = File.OpenRead(pdfPath)
Await storageClient.UploadObjectAsync(_bucketName, objectName, "application/pdf", stream)
End Using
' Step 3: Build async annotation request
Dim asyncRequest = New AsyncAnnotateFileRequest With {
.InputConfig = New InputConfig With {
.GcsSource = New GcsSource With {.Uri = $"gs://{_bucketName}/{objectName}"},
.MimeType = "application/pdf"
},
.Features = {New Feature With {.Type = Feature.Types.Type.DocumentTextDetection}},
.OutputConfig = New OutputConfig With {
.GcsDestination = New GcsDestination With {.Uri = $"gs://{_bucketName}/ocr-output/"},
.BatchSize = 1
}
}
' Step 4: Submit and wait for async operation
Dim operation = Await _visionClient.AsyncBatchAnnotateFilesAsync({asyncRequest})
Dim completedOperation = Await operation.PollUntilCompletedAsync()
' Step 5: Download and parse results from GCS output
Dim outputUri = completedOperation.Result.Responses(0).OutputConfig.GcsDestination.Uri
Dim text = Await DownloadAndParseResultsAsync(storageClient, outputUri)
' Step 6: Clean up input file from GCS
Await storageClient.DeleteObjectAsync(_bucketName, objectName)
Return text
End Function
Private Async Function DownloadAndParseResultsAsync(storageClient As StorageClient, outputUri As String) As Task(Of String)
' Implementation of downloading and parsing results
Return Await Task.FromResult(String.Empty)
End Function
End Class
Public Class StorageClient
Public Shared Function Create() As StorageClient
Return New StorageClient()
End Function
Public Async Function UploadObjectAsync(bucketName As String, objectName As String, mimeType As String, stream As Stream) As Task
' Implementation of uploading object
Await Task.CompletedTask
End Function
Public Async Function DeleteObjectAsync(bucketName As String, objectName As String) As Task
' Implementation of deleting object
Await Task.CompletedTask
End Function
End Class
Public Class VisionClient
Public Async Function AsyncBatchAnnotateFilesAsync(requests As AsyncAnnotateFileRequest()) As Task(Of Operation)
' Implementation of async batch annotate files
Return Await Task.FromResult(New Operation())
End Function
End Class
Public Class Operation
Public Async Function PollUntilCompletedAsync() As Task(Of OperationResult)
' Implementation of polling until completed
Return Await Task.FromResult(New OperationResult())
End Function
End Class
Public Class OperationResult
Public Property Responses As Response()
End Class
Public Class Response
Public Property OutputConfig As OutputConfig
End Class
Public Class AsyncAnnotateFileRequest
Public Property InputConfig As InputConfig
Public Property Features As List(Of Feature) = New List(Of Feature)()
Public Property OutputConfig As OutputConfig
End Class
Public Class InputConfig
Public Property GcsSource As GcsSource
Public Property MimeType As String
End Class
Public Class GcsSource
Public Property Uri As String
End Class
Public Class Feature
Public Class Types
Public Enum Type
DocumentTextDetection
End Enum
End Class
Public Property Type As Types.Type
End Class
Public Class OutputConfig
Public Property GcsDestination As GcsDestination
Public Property BatchSize As Integer
End Class
Public Class GcsDestination
Public Property Uri As String
End Class
이는 최소한의 작동만 가능한 구현 버전이며, 실제 운영 환경에 적합한 버전은 아닙니다. 프로덕션 코드에는 GCS 업로드 실패에 대한 재시도 로직, 느린 비동기 작업에 대한 시간 초과 처리, 출력 객체(입력 객체뿐 아니라) 정리, 작업 도중 실패할 경우 오류 처리, 중간 상태 로깅 기능이 추가되었습니다. 암호로 보호된 PDF 파일은 어떤 수준의 암호 설정에서도 지원되지 않습니다.
IronOCR접근법
IronOCR의 PDF 지원 기능 은 파일을 직접 불러와 동기적으로 처리합니다.
public string ProcessPdf(string pdfPath)
{
// DirectPDF 처리- no GCS, no async, no cleanup
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return _ocr.Read(input).Text;
}
public string ProcessPdfPages(string pdfPath, int startPage, int endPage)
{
// Process specific page range
using var input = new OcrInput();
input.LoadPdfPages(pdfPath, startPage, endPage);
return _ocr.Read(input).Text;
}
public string ProcessEncryptedPdf(string pdfPath, string password)
{
// Password-protected PDFs - not possible with Google Cloud Vision
using var input = new OcrInput();
input.LoadPdf(pdfPath, Password: password);
return _ocr.Read(input).Text;
}
public string ProcessPdf(string pdfPath)
{
// DirectPDF 처리- no GCS, no async, no cleanup
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return _ocr.Read(input).Text;
}
public string ProcessPdfPages(string pdfPath, int startPage, int endPage)
{
// Process specific page range
using var input = new OcrInput();
input.LoadPdfPages(pdfPath, startPage, endPage);
return _ocr.Read(input).Text;
}
public string ProcessEncryptedPdf(string pdfPath, string password)
{
// Password-protected PDFs - not possible with Google Cloud Vision
using var input = new OcrInput();
input.LoadPdf(pdfPath, Password: password);
return _ocr.Read(input).Text;
}
Option Strict On
Public Function ProcessPdf(ByVal pdfPath As String) As String
' DirectPDF 처리- no GCS, no async, no cleanup
Using input As New OcrInput()
input.LoadPdf(pdfPath)
Return _ocr.Read(input).Text
End Using
End Function
Public Function ProcessPdfPages(ByVal pdfPath As String, ByVal startPage As Integer, ByVal endPage As Integer) As String
' Process specific page range
Using input As New OcrInput()
input.LoadPdfPages(pdfPath, startPage, endPage)
Return _ocr.Read(input).Text
End Using
End Function
Public Function ProcessEncryptedPdf(ByVal pdfPath As String, ByVal password As String) As String
' Password-protected PDFs - not possible with Google Cloud Vision
Using input As New OcrInput()
input.LoadPdf(pdfPath, Password:=password)
Return _ocr.Read(input).Text
End Using
End Function
두 번째 NuGet 패키지가 없습니다. 프로비저닝하거나 유지 관리할 GCS 버킷이 없습니다. 정리 단계가 없습니다. 비동기 상태 머신도 없습니다. 비밀번호로 보호된 버전은 매개변수를 정확히 하나 추가합니다. 스캔된 입력에서 검색 가능한 PDF를 생성해야 하는 팀의 경우, result.SaveAsSearchablePdf("output.pdf")는 검색 가능한 PDF 출력을 추가한 한 줄 안에서 처리하며 — Google Cloud Vision는 API 복잡성 수준에서 이 기능을 제공하지 않습니다.
Protobuf 응답 파싱과 일반 OCR 결과 비교
DOCUMENT_TEXT_DETECTION 호출에서 구조화된 데이터를 얻으려면 Protobuf 응답 계층을 탐색해야 합니다. API 호출에서 문단 텍스트에 이르는 경로는 5단계의 중첩된 반복 과정을 거칩니다.
구글 클라우드 비전 접근 방식
텍스트가 빽빽하게 담긴 문서에서 단락 텍스트를 추출하려면 페이지, 블록, 단락을 차례로 탐색한 다음 각 단어의 심볼을 연결해야 합니다. 이는 Protobuf 설계 방식이 텍스트를 단어나 단락 수준이 아닌 심볼 수준으로 저장하기 때문입니다.
public DocumentStructure ExtractDocumentStructure(string imagePath)
{
var image = Image.FromFile(imagePath);
var annotation = _client.DetectDocumentText(image);
var structure = new DocumentStructure
{
FullText = annotation.Text,
Pages = new List<PageInfo>()
};
// Navigate: Pages -> Blocks -> Paragraphs -> Words -> Symbols
foreach (var page in annotation.Pages)
{
var pageInfo = new PageInfo
{
Confidence = page.Confidence,
Paragraphs = new List<ParagraphInfo>()
};
foreach (var block in page.Blocks)
{
foreach (var paragraph in block.Paragraphs)
{
// Must concatenate symbols to get paragraph text
var text = string.Join("", paragraph.Words
.SelectMany(w => w.Symbols)
.Select(s => s.Text));
pageInfo.Paragraphs.Add(new ParagraphInfo
{
Text = text,
Confidence = paragraph.Confidence
});
}
}
structure.Pages.Add(pageInfo);
}
return structure;
}
public DocumentStructure ExtractDocumentStructure(string imagePath)
{
var image = Image.FromFile(imagePath);
var annotation = _client.DetectDocumentText(image);
var structure = new DocumentStructure
{
FullText = annotation.Text,
Pages = new List<PageInfo>()
};
// Navigate: Pages -> Blocks -> Paragraphs -> Words -> Symbols
foreach (var page in annotation.Pages)
{
var pageInfo = new PageInfo
{
Confidence = page.Confidence,
Paragraphs = new List<ParagraphInfo>()
};
foreach (var block in page.Blocks)
{
foreach (var paragraph in block.Paragraphs)
{
// Must concatenate symbols to get paragraph text
var text = string.Join("", paragraph.Words
.SelectMany(w => w.Symbols)
.Select(s => s.Text));
pageInfo.Paragraphs.Add(new ParagraphInfo
{
Text = text,
Confidence = paragraph.Confidence
});
}
}
structure.Pages.Add(pageInfo);
}
return structure;
}
Imports System.Drawing
Public Function ExtractDocumentStructure(imagePath As String) As DocumentStructure
Dim image = Image.FromFile(imagePath)
Dim annotation = _client.DetectDocumentText(image)
Dim structure As New DocumentStructure With {
.FullText = annotation.Text,
.Pages = New List(Of PageInfo)()
}
' Navigate: Pages -> Blocks -> Paragraphs -> Words -> Symbols
For Each page In annotation.Pages
Dim pageInfo As New PageInfo With {
.Confidence = page.Confidence,
.Paragraphs = New List(Of ParagraphInfo)()
}
For Each block In page.Blocks
For Each paragraph In block.Paragraphs
' Must concatenate symbols to get paragraph text
Dim text = String.Join("", paragraph.Words _
.SelectMany(Function(w) w.Symbols) _
.Select(Function(s) s.Text))
pageInfo.Paragraphs.Add(New ParagraphInfo With {
.Text = text,
.Confidence = paragraph.Confidence
})
Next
Next
structure.Pages.Add(pageInfo)
Next
Return structure
End Function
기호 수준의 연결은 선택 사항이 아닙니다 — Protobuf 응답에서 paragraph.Text는 직접 속성이 아닙니다. 이 API를 사용하는 모든 팀은 동일한 중첩 루프 집계의 자체 변형을 작성합니다. 단어 수준의 신뢰도는 word.Confidence 값을 액세스하기 위한 6번째 수준의 반복을 요구하며, 그런 다음 그것들을 기호 연결 결과에 다시 매핑합니다.
IronOCR접근법
IronOCR의 OcrResult는 평면화된 타입의 API를 노출합니다. Pages, Paragraphs, Lines, 및 Words는 모두 Text, Confidence, X, Y, Width, Height와 함께 직접 속성입니다.
public DocumentStructure ExtractDocumentStructure(string imagePath)
{
var result = _ocr.Read(imagePath);
// Direct access - no symbol concatenation, no nested loops
return new DocumentStructure
{
FullText = result.Text,
Confidence = result.Confidence,
Paragraphs = result.Paragraphs.Select(p => new ParagraphInfo
{
Text = p.Text,
Confidence = p.Confidence
}).ToList(),
Lines = result.Lines.Select(l => new LineInfo
{
Text = l.Text,
X = l.X,
Y = l.Y
}).ToList()
};
}
public DocumentStructure ExtractDocumentStructure(string imagePath)
{
var result = _ocr.Read(imagePath);
// Direct access - no symbol concatenation, no nested loops
return new DocumentStructure
{
FullText = result.Text,
Confidence = result.Confidence,
Paragraphs = result.Paragraphs.Select(p => new ParagraphInfo
{
Text = p.Text,
Confidence = p.Confidence
}).ToList(),
Lines = result.Lines.Select(l => new LineInfo
{
Text = l.Text,
X = l.X,
Y = l.Y
}).ToList()
};
}
Public Function ExtractDocumentStructure(imagePath As String) As DocumentStructure
Dim result = _ocr.Read(imagePath)
' Direct access - no symbol concatenation, no nested loops
Return New DocumentStructure With {
.FullText = result.Text,
.Confidence = result.Confidence,
.Paragraphs = result.Paragraphs.Select(Function(p) New ParagraphInfo With {
.Text = p.Text,
.Confidence = p.Confidence
}).ToList(),
.Lines = result.Lines.Select(Function(l) New LineInfo With {
.Text = l.Text,
.X = l.X,
.Y = l.Y
}).ToList()
}
End Function
읽기 결과 가이드에서는 구조화된 데이터 API의 전체 내용을 다룹니다. 단어 수준의 위치 및 신뢰도 점수는 중간 계층을 탐색하지 않고 result.Words[i].X, result.Words[i].Y, 그리고 result.Words[i].Confidence에서 사용할 수 있습니다. 지역별 추출의 경우, 지역 기반 OCR은 CropRectangle을 OcrInput에 사용하여 전체 이미지를 처리하지 않으며, 헤더 행이나 특정 필드만 필요할 때 사용합니다.
비용 모델: 이미지당 청구 방식 vs. 영구 라이선스 방식
비용 비교는 판매량과 기간에 따라 크게 달라집니다.
구글 클라우드 비전 접근 방식
Google Cloud Vision의 가격은 사용 기반이며, 기능 유형 및 볼륨에 따라 다릅니다. 현재 요금은 Google Cloud Vision 가격 페이지를 참조하십시오. 총 비용은 또한 PDF 워크플로의 GCS 저장소 및 운영 비용, 네트워크 egress 비용, 자격 증명 관리 및 키 회전의 엔지니어링 시간이 포함될 수 있습니다.
높은 문서 볼륨에서 이미지 당 수수료는 상당히 누적됩니다. 볼륨과 함께 비용이 선형적으로 증가하며, 커밋된 사용 계약을 협상하지 않는 한 상한이 없습니다.
IronOCR접근법
IronOCR 가격은 한 번의 영구 구매입니다: $999 Lite (1 명의 개발자), $1,499 Plus (3 명의 개발자), $2,999 Professional (10 명의 개발자), $5,999 Unlimited. 해당 라이선스는 사용량 제한 없이 무제한 문서 처리를 지원합니다. 2년 차 비용은 0입니다. 3년 차 비용은 0원입니다. 높은 문서 볼륨에서IronOCR영구 라이선스는 이미지당 클라우드 가격보다 비용 효율적이 됩니다. IronOCR 라이선스 페이지에서 현재 티어 세부 정보를 확인하세요.
IronOCR가 Google Cloud Vision보다 더 저렴해지는 교차점은 볼륨 및 Google의 현재 가격에 따라 다릅니다. 대부분의 프로덕션에서 문서를 안정적으로 처리하는 팀의 경우, IronOCR의 영구 라이선스는 사용 첫 몇 개월 내에 스스로 비용을 감당할 수 있습니다.
API 매핑 참조
| 구글 클라우드 비전 | IronOCR | 노트 |
|---|---|---|
ImageAnnotatorClient.Create() |
new IronTesseract() |
클라이언트 초기화 |
_client.DetectText(image) |
_ocr.Read(imagePath).Text |
기본 텍스트 추출 |
_client.DetectDocumentText(image) |
_ocr.Read(imagePath) |
고밀도 문서 OCR |
AsyncBatchAnnotateFilesAsync() |
input.LoadPdf(); _ocr.Read(input) |
PDF 처리 |
StorageClient.Create() |
필요 없음 | IronOCR에서는 GCS가 필요하지 않습니다. |
storageClient.UploadObjectAsync() |
필요 없음 | PDF 파일이 바로 로드됩니다. |
operation.PollUntilCompletedAsync() |
필요 없음 | 처리는 동기식으로 진행됩니다. |
TextAnnotation |
OcrResult |
결과 컨테이너 |
annotation.Text |
result.Text |
문서 전문 |
annotation.Pages[i] |
result.Pages[i] |
페이지별 접근 권한 |
page.Blocks[i].Paragraphs[j] |
result.Paragraphs[i] |
단락 접근 |
paragraph.Words.SelectMany(w => w.Symbols).Select(s => s.Text) |
paragraph.Text |
직접 텍스트 속성 |
word.Confidence |
word.Confidence |
단어별 신뢰도 |
page.Confidence |
result.Confidence |
전반적인 자신감 |
Feature.Types.Type.DocumentTextDetection |
자동 | IronOCR모드를 자동으로 선택합니다. |
Image.FromFile(path) |
_ocr.Read(path) 또는 input.LoadImage(path) |
이미지 로딩 중 |
response[0].Description |
result.Text |
전체 텍스트 추출 |
annotation.BoundingPoly.Vertices |
word.X, word.Y, word.Width, word.Height |
경계 좌표 |
RpcException (StatusCode.ResourceExhausted) |
적용 안 됨 | 현지 요금 제한 없음 |
RpcException (StatusCode.PermissionDenied) |
적용 안 됨 | 런타임 시 인증 없음 |
팀이 Google Cloud Vision에서IronOCR로 마이그레이션을 고려할 때
클라우드 프로세싱 차단 관련 규정 준수 요구 사항
가장 흔한 마이그레이션 동기는 비용이 아니라 규정 준수 감사입니다. 정부 계약업체들은 ITAR(국제 무기 거래 규정) 제한에 직면하게 되고, 통제 대상 기술 데이터를 구글 클라우드로 전송하는 것이 금지되어 있음을 알게 됩니다. 의료기관들이 문서 처리 파이프라인을 구축할 때, HIPAA 보안 담당자가 모든 데이터 처리 업체에 대해 사업 제휴 계약(BAA) 검토를 요구하며, 구글 클라우드 인프라 범위에 대한 평가가 그들의 위험 허용 범위를 초과한다는 사실을 알게 됩니다. 기밀 유지 대상인 고객 문서를 처리하는 법무 부서는 클라우드 처리의 편리함보다 변호사-고객 비밀 유지 의무에 대한 우려가 더 중요하다고 판단합니다. 방위산업체는 조직 경계를 벗어나는 모든 데이터를 문제점으로 간주하는 CMMC 요건을 충족해야 합니다. 이러한 모든 시나리오에서 구글 머신러닝 모델의 기술적 품질은 무관하며, 아키텍처 자체가 결정적인 요소입니다. IronOCR의 온프레미스 모델은 데이터 처리 과정에 제3자가 관여하지 않기 때문에 제3자 데이터 처리자 규정 준수라는 범주 자체를 없애줍니다.
PDF 워크플로는 규모가 커지면 관리가 불가능해집니다.
이미지 OCR을 위해 Google Cloud Vision으로 시작한 팀은 범위를 확장해야 할 때 PDF의 복잡성에 직면하는 경우가 많습니다. GCS 비동기 파이프라인을 이용해 하루에 PDF 파일 200개를 처리하는 것은 가능하지만 매우 힘든 작업입니다. 하루에 10,000개의 PDF 파일을 처리하려면 전체 파이프라인을 강화해야 합니다. GCS 업로드 실패에 대한 재시도 로직, 완료되지 않은 작업을 위한 데드 레터 큐, 파이프라인 도중 애플리케이션이 충돌할 때 남은 GCS 객체를 정리하는 작업, 그리고 Vision API 비용과 GCS 스토리지 비용 모두에 대한 모니터링이 필요합니다. 이러한 규모에 도달한 팀들은IronOCR마이그레이션이 매우 간단하다는 것을 일관되게 발견합니다. 전체 비동기 GCS 파이프라인이 로컬 파일 직접 로드 후 단일 읽기 호출로 축소되고, 오류 발생 원인도 네트워크 시간 초과, 인증 실패, GCS 할당량 오류 및 JSON 구문 분석 예외에서 로컬 파일 I/O 예외로만 줄어듭니다.
예산 예측 가능성이 이미지별 유연성보다 더 중요합니다.
초기 단계 프로젝트에서는 Google Cloud Vision을 선택하는 경우가 많은데, 이는 무료 티어가 초기 개발 비용을 상쇄하고 이미지별 모델이 처리 중인 항목이 없을 때는 확장성이 0이 되기 때문입니다. 제품의 생산량이 일정한 수준(일반적으로 월 5만 부 이상)에 도달하면 재무팀은 해당 반복적인 항목을 인지하게 됩니다. 비즈니스 규모에 따라 성장하는 SaaS 구독과 달리, IronOCR의 영구 라이선스는 OCR을 변동 운영 비용에서 고정 자본 지출로 전환합니다. 규제된 산업에서 문서를 처리하는 10명의 개발자 팀의 경우, $2,999 한 번의 구매로 Professional 라이선스는 첫 분기 안에서 생산 볼륨과 비교할 때 일반적으로 정당화됩니다.
일괄 처리 적중률 제한
법률 증거 수집, 금융 문서 디지털화, 보험금 청구 처리와 같이 문서 처리량이 많은 워크플로는 일반적으로 시간당 수천 건의 문서를 처리해야 합니다. Google Cloud Vision의 기본 분당 요청 할당량은 1,800건으로 제한되어 있어 3,000건의 문서가 한꺼번에 요청되면 속도 제한이 발생하며, GCP 콘솔을 통해 할당량 증가를 요청하거나(Google의 승인을 기다려야 함) 지터가 있는 지수 백오프를 구현해야 합니다. 할당량 초과가 한 번이라도 발생하면 전체 처리 파이프라인이 60초 동안 의무적으로 중단된 후 재시도가 진행됩니다. IronOCR의 로컬 처리는 사용 가능한 CPU 코어 수에 의해서만 제한되며, 병렬 처리는 외부 승인 없이 모든 코어를 활용합니다.
에어갭 방식의 배포가 필수적입니다.
일부 환경은 설계상 외부 인터넷 연결이 차단되어 있습니다. 예를 들어 기밀 군사 네트워크, 산업 제어 시스템, 금융 결제를 위한 보안 데이터 센터 등이 있습니다. Google Cloud Vision은 아키텍처의 창의성 수준에 관계없이 이러한 환경에서 제대로 작동할 수 없습니다. API는 Google 엔드포인트에 대한 인터넷 연결이 필요합니다. IronOCR의 Docker 배포는 외부 연결 없이 작동합니다. 라이선스 키는 최초 사용 시 유효성 검사를 거쳐 캐시됩니다. 이후 사용 시에는 네트워크 접속이 필요하지 않습니다.
일반적인 마이그레이션 고려사항
GCS 종속성 제거
마이그레이션 시 가장 중요한 구조적 변화는 GCS 파이프라인을 완전히 제거하는 것입니다. Google 패키지를 제거하기 전에 OCR 입력 및 출력을 위해 생성된 모든 GCS 버킷을 기록하고, 지속적인 스토리지 요금이 발생하지 않도록 정리하십시오. GOOGLE_APPLICATION_CREDENTIALS 환경 변수와 JSON 키 파일은 모든 배포 구성, CI/CD 비밀, 개발자 컴퓨터에서 제거되어야 합니다. GCP 콘솔에서 IAM 서비스 계정은 다른 서비스가 해당 계정에 의존하지 않는지 확인한 후 비활성화하거나 삭제할 수 있습니다.
Google.Cloud.Vision.V1 및 Google.Cloud.Storage.V1 제거 후, 이전에 비동기 조정으로 50개 이상의 줄로 확장되었던 PDF 처리 코드는 OcrInput과 LoadPdf과 Read 호출로 축소됩니다. 오류 처리 계약이 변경됩니다. 네트워크 예외, 인증 예외, 속도 제한 예외가 모두 사라집니다. 남은 예외는 파일 I/O 예외 (파일을 찾을 수 없음, 파일 잠김) 및 처리 실패용 OcrException입니다. IronOCR 이미지 입력 가이드 와 PDF 입력 가이드는 스트림, 바이트 배열, URL 로딩을 포함한 전체 입력 API를 다룹니다.
Protobuf 심볼 연결을 통한 직접 텍스트 접근
Protobuf 계층에서 단락 또는 단어 텍스트를 추출하기 위해 작성한 귀하의 코드베이스의 모든 위치가 직접 속성 접근이 됩니다. paragraph.Text, line.Text, 및 word.Text는IronOCR결과 객체에서 형식화된 문자열 속성으로 존재합니다. 구조화된 데이터 추출 코드를 모두 검토하고 중간 집계 로직을 제거하십시오. 읽기 결과 사용 방법 안내서는 OcrResult, OcrResult.Page, OcrResult.Paragraph, OcrResult.Line, OcrResult.Word에서 사용 가능한 모든 속성을 매핑합니다.
PDF 워크플로의 비동기-동기 전환
Google Cloud Vision의 PDF 처리는 GCS를 통한 왕복 통신이 필요하기 때문에 비동기 방식으로만 작동합니다. IronOCR의 Read 메서드는 동기 방식입니다. 응용 프로그램의 PDF 처리 계층이 async Task<string> 서명 및 await 기반 호출 체인 중심으로 구축된 경우, 마이그레이션 패턴은 Task.Run 래퍼입니다.
public async Task<string> ProcessPdfAsync(string pdfPath)
{
return await Task.Run(() =>
{
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return _ocr.Read(input).Text;
});
}
public async Task<string> ProcessPdfAsync(string pdfPath)
{
return await Task.Run(() =>
{
using var input = new OcrInput();
input.LoadPdf(pdfPath);
return _ocr.Read(input).Text;
});
}
Imports System.Threading.Tasks
Public Async Function ProcessPdfAsync(pdfPath As String) As Task(Of String)
Return Await Task.Run(Function()
Using input As New OcrInput()
input.LoadPdf(pdfPath)
Return _ocr.Read(input).Text
End Using
End Function)
End Function
이렇게 하면 스레드 풀에서 OCR 작업을 실행하는 동안 호출자에게 비동기 인터페이스가 유지됩니다. 높은 처리량 시나리오의 경우, IronOCR의 내장된 비동기 OCR 지원은 Task.Run 래퍼 없이 이 패턴을 네이티브로 처리합니다.
구글 머신러닝이 처리한 이미지의 전처리
Google Cloud Vision의 머신러닝 기반 모델은 명시적인 전처리 구성 없이도 낮은 대비, 약간의 왜곡, 중간 정도의 노이즈와 같은 일부 이미지 품질 문제를 처리합니다.IronOCR포함한 Tesseract 기반 엔진은 손상된 입력에 대한 명시적 전처리를 통해 성능을 향상시킵니다. 문서의 집합에 저품질의 스캔이 포함된 경우, 입력 파이프라인에 input.Deskew(), input.DeNoise(), input.EnhanceResolution(300)를 추가하세요. IronOCR의 자동 전처리는 이러한 필터를 이미지 품질 문제를 탐지하여 지능적으로 적용하나, 알려진 문제 있는 스캔 소스에 대해 명시적인 필터 적용은 결정적인 결과를 제공합니다. 이미지 품질 보정 가이드는 전체 필터 API를 다루고, 이미지 색상 보정 가이드는 조명이 고르지 않은 스캔 이미지의 대비 및 이진화에 대해 설명합니다.
IronOCR의 추가 기능
위 비교에서 다룬 기능 외에도 IronOCR Google Cloud Vision의 OCR 기능에는 없는 기능을 제공합니다.
- hOCR 내보내기: hOCR 형식을 소비하는 다운스트림 도구를 위해
result.SaveAsHocrFile()와 함께 hOCR 파일로 결과 저장. - 배치 작업 진행 상황 추적 : 장시간 실행되는 배치 워크로드는 큐를 폴링하거나 로그 출력을 분석할 필요 없이 진행 상황 추적 API를 통해 문서별 완료 여부를 보고할 수 있습니다.
- 특수 문서 유형 :IronOCR여권, 차량 번호판, MICR 수표 및 필기 문서와 같이 일반 OCR을 넘어 특정 엔진 튜닝이 필요한 문서 유형에 대한 사전 조정 구성이 포함되어 있습니다.
- 문서에서 표 추출 : 스캔한 문서의 구조화된 표 데이터를 원시 텍스트 스트림을 후처리하지 않고 행-열 형식으로 추출할 수 있습니다.
- 이미지 색상 보정 : 명암 정규화, 이진화 임계값 조정 및 회색조 변환은 조명이 고르지 않거나 잉크가 흐릿한 스캔 이미지에 대해 명시적인 전처리 단계로 제공됩니다.
.NET 호환성 및 미래 준비
IronOCR .NET 8 및 .NET 9를 적극적으로 지원하며, 레거시 코드베이스를 위해 .NET Framework 4.6.2부터 4.8까지 및 .NET Standard 2.0도 지원합니다. 배포 가이드는 Windows , Linux , macOS , Docker , Azure 및 AWS Lambda를 다루며, 동일한 NuGet 패키지를 사용하면 플랫폼별 구성 없이 모든 플랫폼에 배포할 수 있습니다. Google Cloud Vision은 REST/gRPC API로서 .NET 버전에 의존하지 않지만, Google.Cloud.Vision.V1 클라이언트 라이브러리는 .NET Standard 2.0 및 이후 버전을 대상으로 하며, 그 종속성 트리 (gRPC, Protobuf) 는 그 라이브러리의 주요 버전이 증가함에 따라 증가하는 NuGet 패키지 관리 영역을 추가합니다.
결론
Google Cloud Vision은 기술적으로 유능한 OCR 서비스로서 진정한 강점을 가지고 있습니다: 그 ML 지원 모델은 CJK 텍스트, 필기체 및 자연 장면 이미지에 대해 잘 작동하며, DOCUMENT_TEXT_DETECTION 기능의 계층화된 Protobuf 출력은 그것을 필요로 하는 사용 사례를 위해 세분화된 기호-수준 데이터를 제공합니다. 이러한 강점은 적절한 상황에서는 중요하지만, 아키텍처적 제약 조건(필수적인 클라우드 전송, JSON 키 파일 자격 증명 관리, GCS 종속 PDF 처리, 이미지별 요금 청구, 분당 1,800건 요청 제한, 페드램 인증 부재)은 설정을 통해 해결할 수 있는 문제가 아닙니다. 이것들은 클라우드 API의 기본적인 속성입니다.
IronOCR의 온프레미스 모델은 이러한 제약 조건들을 거의 모두 뒤집습니다. 문서는 처리 서버를 벗어나지 않습니다. 라이선스 키는 JSON 키 파일과 서비스 계정 IAM 구성을 대체합니다. PDF 처리는 세 줄로 이루어진 동기식 작업입니다. 속도 제한도 없고, 프로비저닝해야 할 GCS 버킷도 없고, 비동기 폴링 루프도 없고, Protobuf 역직렬화도 없습니다. OcrResult 객체는 기호 연결을 통해 단락 텍스트를 읽을 필요 없이 구조화된 데이터를 형식화된 .NET 속성으로 노출합니다.
이 결정은 건축에 관한 단 하나의 질문으로 귀결됩니다. 문서를 규정 준수, 규제 또는 계약상의 문제 없이 Google 인프라로 전송할 수 있고, 이미지당 비용이 허용 가능한 수준일 정도로 데이터 양이 적다면 Google Cloud Vision의 머신러닝 정확도와 관리형 인프라는 분명한 이점이 될 수 있습니다. HIPAA, ITAR, CMMC, 정부 계약업체 요구사항, 에어갭 배포 또는 데이터 주권 정책 등의 이유로 문서를 사내에 보관해야 하는 경우, 다른 기능을 평가하기 전에 이미 해당 질문에 대한 답이 나와 있습니다. IronOCR의 영구 라이선스는 OCR 비용을 문서량에 따라 변동되는 가변 비용에서 고정 비용으로 전환하여 생산 규모에서 예산 계획을 상당히 간소화합니다.
마이그레이션을 검토 중인 팀을 위해IronOCR문서 및 튜토리얼 허브는 Google Cloud Vision의 OCR 범위에서 완전히 제외되는 전처리, 구조화된 데이터 및 특수 문서 기능을 포함하여 전체 API에 대한 완벽한 정보를 제공합니다.
자주 묻는 질문
Google Cloud Vision API란 무엇인가요?
Google Cloud Vision API는 개발자와 기업이 이미지와 문서에서 텍스트를 추출하는 데 사용하는 OCR 솔루션입니다. 이 솔루션은 .NET 애플리케이션 개발용 IronOCR과 함께 평가된 여러 OCR 옵션 중 하나입니다.
IronOCR은 .NET 개발자를 위한 Google Cloud Vision API와 어떻게 비교되나요?
IronOCR은 IronTesseract를 핵심 엔진으로 사용하는 NuGet 네이티브 .NET OCR 라이브러리입니다. Google Cloud Vision API에 비해 배포가 간편하고(SDK 설치 프로그램 없음), 정액제 요금이 적용되며, COM 인터롭이나 클라우드 종속성이 없는 깔끔한 C# API를 제공합니다.
IronOCR이 Google Cloud Vision API보다 설정하기가 더 쉬운가요?
IronOCR은 단일 NuGet 패키지를 통해 설치됩니다. SDK 설치 프로그램, 복사할 라이선스 파일, 등록할 COM 구성 요소 또는 관리해야 할 별도의 런타임 바이너리가 없습니다. 전체 OCR 엔진이 패키지에 번들로 제공됩니다.
Google Cloud Vision API와 IronOCR 간에는 어떤 정확도 차이가 있나요?
IronOCR은 표준 비즈니스 문서, 송장, 영수증, 스캔 양식에 대해 높은 인식 정확도를 달성합니다. 품질이 많이 저하된 문서나 일반적이지 않은 스크립트의 경우 정확도는 소스 품질에 따라 달라집니다. IronOCR에는 이미지 전처리 필터가 포함되어 있어 저품질 입력에 대한 인식률을 향상시킵니다.
IronOCR은 PDF 텍스트 추출을 지원하나요?
예. IronOCR은 한 번의 호출로 원본 PDF와 스캔한 PDF 이미지 모두에서 텍스트를 추출합니다. 또한 여러 페이지의 TIFF 파일, 이미지, 스트림도 지원합니다. 스캔한 PDF의 경우 OCR은 페이지별 결과 개체를 사용하여 페이지별로 적용됩니다.
Google Cloud Vision API 라이선싱은 IronOCR과 어떻게 비교되나요?
IronOCR은 페이지당 또는 스캔당 요금이 없는 정액제 영구 라이선스를 사용합니다. 대량의 문서를 처리하는 조직은 문서 양에 관계없이 동일한 라이선스 비용을 지불합니다. 자세한 내용과 볼륨 가격은 IronOCR 라이선스 페이지에서 확인할 수 있습니다.
IronOCR 어떤 언어를 지원하나요?
IronOCR은 별도의 NuGet 언어 팩을 통해 127개 언어를 지원합니다. 언어를 추가하려면 '닷넷 추가 패키지 IronOcr.Languages.{Language}' 명령 하나만 있으면 됩니다. 수동으로 파일을 배치하거나 경로를 구성할 필요가 없습니다.
.NET 프로젝트에 IronOCR 설치하는 방법은 무엇인가요?
NuGet을 통해 설치합니다: 패키지 관리자 콘솔에서 '설치-패키지 IronOcr' 또는 CLI에서 '닷넷 추가 패키지 IronOcr'을 실행합니다. 추가 언어 팩도 같은 방법으로 설치됩니다. 기본 SDK 인스톨러가 필요하지 않습니다.
IronOCR은 Google Cloud Vision과 달리 Docker 및 컨테이너화된 배포에 적합한가요?
예. IronOCR은 NuGet 패키지를 통해 Docker 컨테이너에서 작동합니다. 라이선스 키는 환경 변수를 통해 설정됩니다. OCR 엔진 자체에는 라이선스 파일, SDK 경로 또는 볼륨 마운트가 필요하지 않습니다.
구매하기 전에 Google Cloud Vision과 비교하여 IronOCR을 사용해 볼 수 있나요?
예. IronOCR 평가판 모드는 문서를 처리하고 출력물에 워터마크 오버레이가 포함된 OCR 결과를 반환합니다. 라이선스를 구매하기 전에 자신의 문서에서 정확성을 확인할 수 있습니다.
IronOCR은 텍스트 추출과 함께 바코드 판독을 지원하나요?
IronOCR은 텍스트 추출과 OCR에 중점을 둡니다. 바코드 판독을 위해 Iron Software는 동반 라이브러리로 IronBarcode를 제공합니다. 두 가지 모두 개별적으로 또는 Iron Suite 번들의 일부로 사용할 수 있습니다.
Google Cloud Vision API에서 IronOCR로 쉽게 마이그레이션할 수 있나요?
Google Cloud Vision API에서 IronOCR로의 마이그레이션에는 일반적으로 초기화 시퀀스를 IronTesseract 인스턴스화로 대체하고, COM 수명 주기 관리를 제거하고, API 호출을 업데이트하는 작업이 포함됩니다. 대부분의 마이그레이션은 코드 복잡성을 크게 줄여줍니다.

