AWS와 Google Vision의 OCR 기능 비교
Dynamsoft Label Recognizer는 여권에서 MRZ를 추출하고, 차량에서 VIN을 스캔하고, 산업용 포장에서 구조화된 라벨을 읽는 등 한 가지 작업을 매우 잘 수행하며, 그 외의 다른 작업은 전혀 하지 않습니다. 그러한 특정 분야에 대한 전문성은 애플리케이션에 일반 문서 OCR 기능이 함께 필요해지는 순간 예산 문제로 이어집니다. 왜냐하면 MRZ용 Dynamsoft Label Recognizer, QR 코드용 Dynamsoft Barcode Reader, 경계 감지용 Dynamsoft Document Normalizer를 라이선스해야 하고, 전체 페이지 문서를 처리할 네 번째 라이브러리까지 찾아야 하기 때문입니다. IronOCR은 단일 NuGet 패키지로 모든 능력을 $999 영구적 라이선스로 제공합니다.
Dynamsoft 레이블 인식기 이해하기
캐나다 밴쿠버에 본사를 둔 Dynamsoft Corporation은 제한된 형식의 기계 판독 가능한 구조화된 텍스트를 안정적으로 인식한다는 특정 목표를 중심으로 Label Recognizer 제품을 개발했습니다. 제품 NuGet 패키지는 Dynamsoft.DotNet.LabelRecognizer이며, 상업적 라이선스는 오직 연간 구독을 통해 제공됩니다 — 영구적 옵션은 존재하지 않습니다. 현재 가격에 대해 Dynamsoft에 문의하십시오.
이 라이브러리의 인식 모델은 템플릿 기반입니다. JSON 설정 API(AppendSettingsFromString)를 통해 인식 작업을 설정한 후 이미지 파일에 대해 RecognizeFile 또는 RecognizeByFile을 호출합니다. 결과는 원시 텍스트 문자열을 포함하는 여러 줄의 결과 모음으로 반환됩니다. 해당 문자열을 의미 있는 구조화된 데이터(필드 오프셋, 날짜 변환, 검사 숫자 유효성 검사 등)로 파싱하는 것은 전적으로 귀하의 책임입니다.
Dynamsoft 라벨 인식기의 주요 아키텍처 특징:
- 템플릿 기반 인식 엔진: MRZ, VIN 및 라벨 패턴은 인식 전에 JSON 템플릿 구성이 필요합니다.
- 원본 텍스트 출력만:
RecognizeFile은 텍스트 문자열이 포함된LineResult개체를 반환합니다; 구조화된 필드 구문 분석 없음 - 이미지 전용 입력: PDF를 기본적으로 지원하지 않습니다. PDF 파일을 처리하기 전에 외부에서 이미지 파일로 변환해야 합니다.
- 연간 구독 라이센싱: 기기당 및 서버 당 계층이 제공됩니다; 현재 가격에 대해 Dynamsoft에 문의하십시오; no one-time purchase
- 기능별 별도 제품: 바코드 판독, 문서 표준화 및 카메라 최적화는 각각 별도의 라이선스 제품이 필요합니다.
- 지원 언어 범위가 제한적입니다. 라틴 문자 MRZ 형식에 초점을 맞추고 있습니다. 광범위한 다국어 문서 지원이 부족함
JSON 런타임 설정 API
모든 Dynamsoft 라벨 인식기 워크플로는 템플릿 구성 단계로 시작됩니다. 예를 들어 MRZ 인식의 경우 이미지 처리가 시작되기 전에 인식 매개변수, 문자 모델 및 영역 참조를 선언하는 JSON 문서를 로드해야 합니다.
using Dynamsoft.DLR;
public class DynamsoftMrzService : IDisposable
{
private readonly LabelRecognizer _recognizer;
public DynamsoftMrzService(string licenseKey)
{
// Static license initialization — must precede instance creation
LabelRecognizer.InitLicense(licenseKey);
_recognizer = new LabelRecognizer();
// MRZ requires specific template configuration loaded as JSON
string mrzTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""MRZ"",
""ReferenceRegionNameArray"": [""FullImage""],
""CharacterModelName"": ""MRZ""
}]
}";
_recognizer.AppendSettingsFromString(mrzTemplate);
}
public string ExtractRawMrz(string passportImagePath)
{
var results = _recognizer.RecognizeFile(passportImagePath);
// Returns raw MRZ text lines only — no field parsing
var mrzLines = new StringBuilder();
foreach (var result in results)
{
foreach (var lineResult in result.LineResults)
{
mrzLines.AppendLine(lineResult.Text);
}
}
return mrzLines.ToString().Trim();
}
public void Dispose() => _recognizer?.Dispose();
}
using Dynamsoft.DLR;
public class DynamsoftMrzService : IDisposable
{
private readonly LabelRecognizer _recognizer;
public DynamsoftMrzService(string licenseKey)
{
// Static license initialization — must precede instance creation
LabelRecognizer.InitLicense(licenseKey);
_recognizer = new LabelRecognizer();
// MRZ requires specific template configuration loaded as JSON
string mrzTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""MRZ"",
""ReferenceRegionNameArray"": [""FullImage""],
""CharacterModelName"": ""MRZ""
}]
}";
_recognizer.AppendSettingsFromString(mrzTemplate);
}
public string ExtractRawMrz(string passportImagePath)
{
var results = _recognizer.RecognizeFile(passportImagePath);
// Returns raw MRZ text lines only — no field parsing
var mrzLines = new StringBuilder();
foreach (var result in results)
{
foreach (var lineResult in result.LineResults)
{
mrzLines.AppendLine(lineResult.Text);
}
}
return mrzLines.ToString().Trim();
}
public void Dispose() => _recognizer?.Dispose();
}
Imports Dynamsoft.DLR
Imports System.Text
Public Class DynamsoftMrzService
Implements IDisposable
Private ReadOnly _recognizer As LabelRecognizer
Public Sub New(licenseKey As String)
' Static license initialization — must precede instance creation
LabelRecognizer.InitLicense(licenseKey)
_recognizer = New LabelRecognizer()
' MRZ requires specific template configuration loaded as JSON
Dim mrzTemplate As String = "{
""LabelRecognizerParameterArray"": [{
""Name"": ""MRZ"",
""ReferenceRegionNameArray"": [""FullImage""],
""CharacterModelName"": ""MRZ""
}]
}"
_recognizer.AppendSettingsFromString(mrzTemplate)
End Sub
Public Function ExtractRawMrz(passportImagePath As String) As String
Dim results = _recognizer.RecognizeFile(passportImagePath)
' Returns raw MRZ text lines only — no field parsing
Dim mrzLines As New StringBuilder()
For Each result In results
For Each lineResult In result.LineResults
mrzLines.AppendLine(lineResult.Text)
Next
Next
Return mrzLines.ToString().Trim()
End Function
Public Sub Dispose() Implements IDisposable.Dispose
_recognizer?.Dispose()
End Sub
End Class
RecognizeFile의 출력은 P<GBRSMITH<<JOHN<<<<<<<<<<<<<<<<<<<<<<<<<<<와 같은 원본 MRZ 텍스트입니다. Surname = "SMITH", GivenNames = "JOHN", DocumentNumber, DateOfBirth, ExpiryDate를 유형화된 속성으로 가져오기 위해서는 TD1/TD2/TD3 파서를 직접 구현해야 합니다. 이 저장소에 있는 Dynamsoft 문서 및 소스 파일은 파서가 약 150줄의 구문 분석 코드 — 문자 오프셋, << 이름 구분자, 두 자리 연도 명확화, 검사 숫자 검증 — 를 처리하도록 추정하고 있으며, 이 모든 것은 Dynamsoft가 제공하지 않습니다.
IronOCR이해하기
IronOCR 은 최적화된 Tesseract 5 엔진을 기반으로 구축된 상 for .NET OCR 라이브러리로, 전처리, 입력 형식, 구조화된 출력 및 특수 문서 구문 분석을 처리하는 관리형 API 계층을 제공합니다. 설치는 단일 NuGet 명령입니다: dotnet add package IronOcr. 네이티브 바이너리 관리 기능, tessdata 폴더 설정 기능, 템플릿 구성 파일이 없습니다.
주요 특징:
- 범용 및 특수 용도: 전체 페이지 문서 OCR, 여러 페이지로 구성된 PDF, 스캔 이미지 일괄 처리, 특수 형식(여권, 바코드, 차량 번호판) 등을 하나의 패키지로 처리할 수 있습니다.
- 자동 전처리 파이프라인: 기울기 보정, 노이즈 제거, 대비 조정, 이진화 및 해상도 향상 기능이 품질이 낮은 입력 이미지에 대해 수동 설정 없이 실행됩니다.
- PDF 기본 지원: 스캔한 PDF 파일과 디지털 PDF 파일(암호로 보호된 파일 포함)을 외부 변환 과정 없이 직접 읽을 수 있습니다.
- 구조화된 출력 계층 구조: 결과는 페이지, 단락, 줄, 단어 및 문자 경계 상자와 신뢰도 점수를 표시합니다.
- 내장된 바코드 읽기:
ocr.Configuration.ReadBarCodes = true을 활성화하고 텍스트와 함께 바코드를 동일한 패스로 추출합니다 - 125개 이상의 언어 팩: 각 언어는 별도의 NuGet 패키지로 설치됩니다. 테스데이터 폴더 관리 필요 없음
- 영구적 라이선싱: $999 Lite, $1,499 Plus, $2,999 Professional — 단 한번의 구매, 모든 플랫폼, 모든 기능이 포함됩니다.
- 크로스 플랫폼 배포: Windows, Linux, macOS, Docker, AWS 및 Azure 모두 플랫폼별 구성 없이 동일한 패키지로 작동합니다.
기능 비교
| 기능 | Dynamsoft 라벨 인식기 | IronOCR |
|---|---|---|
| 일반 문서 OCR | 지원되지 않음 | 전체 지원 |
| MRZ 추출 | 특수화된 (원문) | 파싱된 필드가 내장되어 있습니다. |
| 네이티브 PDF 입력 | 지원되지 않음 | 예 |
| 바코드 판독 | 별도 제품 (다이나소프트 바코드 리더기) | 내장 (ReadBarCodes) |
| 검색 가능한 PDF 출력 | 지원되지 않음 | 예 |
| 언어 지원 | 리미티드(라틴어 MRZ) | 125개 이상의 언어 |
| 라이센싱 모델 | 연간 구독만 가능 | 영구 구독 옵션 |
| 완벽한 보장을 위해 필요한 제품 | 3세 이상 | 1 |
상세 기능 비교
| 기능 | Dynamsoft 라벨 인식기 | IronOCR |
|---|---|---|
| 인정 범위 | ||
| 일반 문서 OCR | 지원되지 않음 | 예 |
| MRZ 인식 | 전문화된 | 예 (ReadPassport) |
| VIN 인식 | 전문화된 | 예 (표준 OCR을 통해) |
| 산업 라벨 판독 | 전문화된 | 예 |
| 필기체 인식 | 지원되지 않음 | 예 |
| 테이블 추출 | 지원되지 않음 | 예 |
| 입력 형식 | ||
| 이미지 파일(JPG, PNG, TIFF) | 예 | 예 |
| PDF(네이티브) | 지원되지 않음 | 예 |
| 비밀번호로 보호된 PDF | 지원되지 않음 | 예 |
| 바이트 배열 / 스트림 | 예 | 예 |
| 여러 페이지로 구성된 문서 | 수동 집계 | 예 (원어민) |
| 출력 형식 | ||
| 일반 텍스트 | 예 (원본 라인) | 예 |
| 구조화된 필드(파싱됨) | 제공되지 않음 | 예 (페이지, 줄 수, 단어 수) |
| 검색 가능한 PDF | 지원되지 않음 | 예 |
| hOCR | 지원되지 않음 | 예 |
| 신뢰도 점수 | 줄당 | 단어당, 줄당, 페이지당 |
| 전처리 | ||
| 자동 전처리 | 기초적인 | 예 (지능형 파이프라인) |
| 기울기/회전 보정 | 제한적 | 예 |
| 노이즈 제거 | 제한적 | 예 |
| 명암 대비 강화 | 제한적 | 예 |
| DPI 정규화 | 제공되지 않음 | 예 |
| 통합 기능 | ||
| 바코드 판독 | 별도 제품 | 내장형 |
| 문서 정규화 | 별도 제품 | 필요하지 않음 |
| 영역 기반 OCR | 예 (템플릿을 통해) | 예 (CropRectangle) |
| 스레드 안전 병렬 처리 | 예 | 예 |
| 플랫폼 및 배포 | ||
| Windows | 예 | 예 |
| Linux | 예 | 예 |
| macOS | 예 | 예 |
| Docker | 예 | 예 |
| Azure / AWS | 예 | 예 |
| 에어갭/오프라인 | 예 | 예 |
| 라이선스 및 비용 | ||
| 연간 구독 | 예 (가격은 Dynamsoft에 문의) | 선택적 |
| 영구 라이선스 | 사용 불가 | 예 ($999 일회성) |
| 모든 기능을 하나의 패키지에 담았습니다. | 아니요 (3개 이상 제품) | 예 |
| 무료 체험 | 30일 | 예 |
전문 분야 vs. 일반 분야
Dynamsoft가 내린 가장 중요한 아키텍처적 결정은 범용적인 소프트웨어가 아닌 특정 분야에 특화된 소프트웨어를 구축하는 것이었습니다. 이 결정은 MRZ 또는 라벨 판독으로 시작하지만 결국 더 많은 기능을 필요로 하는 모든 애플리케이션에 직접적인 영향을 미칩니다.
Dynamsoft 접근 방식
Dynamsoft Label Recognizer는 JSON 템플릿에 설명된 내용만 처리하며 그 이상은 처리하지 않습니다. Dynamsoft를 기반으로 구축된 여권 처리 애플리케이션은 실제 문서 워크플로를 처리하기 전에 세 가지 제품이 필요합니다.
// Dynamsoft passport processing — MULTIPLE PRODUCTS REQUIRED
using Dynamsoft.DLR; // Label Recognizer — for MRZ (annual subscription)
using Dynamsoft.DBR; // Barcode Reader — for any barcodes (additional license)
// Plus: a separate OCR library — for full page text (more budget)
public class DynamsoftPassportProcessor : IDisposable
{
private readonly LabelRecognizer _mrzRecognizer;
private readonly BarcodeReader _barcodeReader;
// private readonly SomeOtherOcrLibrary _fullTextOcr; // third product
public DynamsoftPassportProcessor(
string mrzLicenseKey,
string barcodeLicenseKey)
{
// License each product independently
LabelRecognizer.InitLicense(mrzLicenseKey);
_mrzRecognizer = new LabelRecognizer();
// Configure MRZ template — JSON required before any recognition
string mrzTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""MRZ_Passport"",
""ReferenceRegionNameArray"": [""FullImage""],
""CharacterModelName"": ""MRZ""
}]
}";
_mrzRecognizer.AppendSettingsFromString(mrzTemplate);
// Second product, second license key
BarcodeReader.InitLicense(barcodeLicenseKey);
_barcodeReader = new BarcodeReader();
}
public PassportResult ProcessPassport(string imagePath)
{
// Step 1: MRZ 추출 — raw text only, no field parsing
var mrzResults = _mrzRecognizer.RecognizeFile(imagePath);
var mrzText = new StringBuilder();
foreach (var r in mrzResults)
foreach (var line in r.LineResults)
mrzText.AppendLine(line.Text);
// Step 2: Parse MRZ manually — your 150-line TD3 parser here
var parsedMrz = ParseMrzManually(mrzText.ToString());
// Step 3: Barcodes — second product, second API
var barcodeResults = _barcodeReader.DecodeFile(imagePath);
// Step 4: Full page text — THIRD library, no Dynamsoft option
// var fullText = _fullTextOcr.ReadImage(imagePath);
return new PassportResult
{
ParsedMrz = parsedMrz,
Barcodes = barcodeResults.Select(b => b.BarcodeText).ToList(),
FullPageText = null // requires a fourth product
};
}
public void Dispose()
{
_mrzRecognizer?.Dispose();
_barcodeReader?.Dispose();
}
}
// Dynamsoft passport processing — MULTIPLE PRODUCTS REQUIRED
using Dynamsoft.DLR; // Label Recognizer — for MRZ (annual subscription)
using Dynamsoft.DBR; // Barcode Reader — for any barcodes (additional license)
// Plus: a separate OCR library — for full page text (more budget)
public class DynamsoftPassportProcessor : IDisposable
{
private readonly LabelRecognizer _mrzRecognizer;
private readonly BarcodeReader _barcodeReader;
// private readonly SomeOtherOcrLibrary _fullTextOcr; // third product
public DynamsoftPassportProcessor(
string mrzLicenseKey,
string barcodeLicenseKey)
{
// License each product independently
LabelRecognizer.InitLicense(mrzLicenseKey);
_mrzRecognizer = new LabelRecognizer();
// Configure MRZ template — JSON required before any recognition
string mrzTemplate = @"{
""LabelRecognizerParameterArray"": [{
""Name"": ""MRZ_Passport"",
""ReferenceRegionNameArray"": [""FullImage""],
""CharacterModelName"": ""MRZ""
}]
}";
_mrzRecognizer.AppendSettingsFromString(mrzTemplate);
// Second product, second license key
BarcodeReader.InitLicense(barcodeLicenseKey);
_barcodeReader = new BarcodeReader();
}
public PassportResult ProcessPassport(string imagePath)
{
// Step 1: MRZ 추출 — raw text only, no field parsing
var mrzResults = _mrzRecognizer.RecognizeFile(imagePath);
var mrzText = new StringBuilder();
foreach (var r in mrzResults)
foreach (var line in r.LineResults)
mrzText.AppendLine(line.Text);
// Step 2: Parse MRZ manually — your 150-line TD3 parser here
var parsedMrz = ParseMrzManually(mrzText.ToString());
// Step 3: Barcodes — second product, second API
var barcodeResults = _barcodeReader.DecodeFile(imagePath);
// Step 4: Full page text — THIRD library, no Dynamsoft option
// var fullText = _fullTextOcr.ReadImage(imagePath);
return new PassportResult
{
ParsedMrz = parsedMrz,
Barcodes = barcodeResults.Select(b => b.BarcodeText).ToList(),
FullPageText = null // requires a fourth product
};
}
public void Dispose()
{
_mrzRecognizer?.Dispose();
_barcodeReader?.Dispose();
}
}
Imports Dynamsoft.DLR ' Label Recognizer — for MRZ (annual subscription)
Imports Dynamsoft.DBR ' Barcode Reader — for any barcodes (additional license)
' Plus: a separate OCR library — for full page text (more budget)
Public Class DynamsoftPassportProcessor
Implements IDisposable
Private ReadOnly _mrzRecognizer As LabelRecognizer
Private ReadOnly _barcodeReader As BarcodeReader
' Private ReadOnly _fullTextOcr As SomeOtherOcrLibrary ' third product
Public Sub New(mrzLicenseKey As String, barcodeLicenseKey As String)
' License each product independently
LabelRecognizer.InitLicense(mrzLicenseKey)
_mrzRecognizer = New LabelRecognizer()
' Configure MRZ template — JSON required before any recognition
Dim mrzTemplate As String = "{
""LabelRecognizerParameterArray"": [{
""Name"": ""MRZ_Passport"",
""ReferenceRegionNameArray"": [""FullImage""],
""CharacterModelName"": ""MRZ""
}]
}"
_mrzRecognizer.AppendSettingsFromString(mrzTemplate)
' Second product, second license key
BarcodeReader.InitLicense(barcodeLicenseKey)
_barcodeReader = New BarcodeReader()
End Sub
Public Function ProcessPassport(imagePath As String) As PassportResult
' Step 1: MRZ 추출 — raw text only, no field parsing
Dim mrzResults = _mrzRecognizer.RecognizeFile(imagePath)
Dim mrzText = New StringBuilder()
For Each r In mrzResults
For Each line In r.LineResults
mrzText.AppendLine(line.Text)
Next
Next
' Step 2: Parse MRZ manually — your 150-line TD3 parser here
Dim parsedMrz = ParseMrzManually(mrzText.ToString())
' Step 3: Barcodes — second product, second API
Dim barcodeResults = _barcodeReader.DecodeFile(imagePath)
' Step 4: Full page text — THIRD library, no Dynamsoft option
' Dim fullText = _fullTextOcr.ReadImage(imagePath)
Return New PassportResult With {
.ParsedMrz = parsedMrz,
.Barcodes = barcodeResults.Select(Function(b) b.BarcodeText).ToList(),
.FullPageText = Nothing ' requires a fourth product
}
End Function
Public Sub Dispose() Implements IDisposable.Dispose
If _mrzRecognizer IsNot Nothing Then _mrzRecognizer.Dispose()
If _barcodeReader IsNot Nothing Then _barcodeReader.Dispose()
End Sub
End Class
위 코드는 여전히 PDF 입력을 처리하지 못합니다. 여권 스캔 파일이 JPEG 형식이 아닌 PDF 형식으로 제공되는 경우, 이 모든 과정을 실행하기 전에 PDF 렌더링 라이브러리를 추가해야 합니다. 실제 여권 발급 워크플로우를 위한 완벽한 통합: 네 가지 제품, 네 가지 라이선스 키, 네 가지 유지 관리 인터페이스.
IronOCR접근법
IronOCR MRZ 구문 분석, 전체 페이지 OCR, 바코드 및 PDF 입력 등 여권 관련 워크플로를 하나의 패키지에서 처리합니다.
using IronOcr;
public class IronOcrPassportProcessor
{
private readonly IronTesseract _ocr;
public IronOcrPassportProcessor()
{
_ocr = new IronTesseract();
_ocr.Configuration.ReadBarCodes = true; // barcodes included
}
public CompletePassportResult ProcessPassport(string imagePath)
{
// Structured MRZ fields — no manual parsing required
var mrzData = _ocr.ReadPassport(imagePath);
// Full page OCR + barcodes in the same call
var fullResult = _ocr.Read(imagePath);
return new CompletePassportResult
{
// MRZ fields are already parsed properties
DocumentType = mrzData.DocumentType,
IssuingCountry = mrzData.IssuingCountry,
Surname = mrzData.Surname,
GivenNames = mrzData.GivenNames,
PassportNumber = mrzData.DocumentNumber,
Nationality = mrzData.Nationality,
DateOfBirth = mrzData.DateOfBirth,
ExpiryDate = mrzData.ExpiryDate,
RawMrz = mrzData.MRZ,
// Full page text from same package
FullPageText = fullResult.Text,
// Barcodes alongside text — no separate product
Barcodes = fullResult.Barcodes.Select(b => b.Value).ToList(),
Confidence = fullResult.Confidence
};
}
}
using IronOcr;
public class IronOcrPassportProcessor
{
private readonly IronTesseract _ocr;
public IronOcrPassportProcessor()
{
_ocr = new IronTesseract();
_ocr.Configuration.ReadBarCodes = true; // barcodes included
}
public CompletePassportResult ProcessPassport(string imagePath)
{
// Structured MRZ fields — no manual parsing required
var mrzData = _ocr.ReadPassport(imagePath);
// Full page OCR + barcodes in the same call
var fullResult = _ocr.Read(imagePath);
return new CompletePassportResult
{
// MRZ fields are already parsed properties
DocumentType = mrzData.DocumentType,
IssuingCountry = mrzData.IssuingCountry,
Surname = mrzData.Surname,
GivenNames = mrzData.GivenNames,
PassportNumber = mrzData.DocumentNumber,
Nationality = mrzData.Nationality,
DateOfBirth = mrzData.DateOfBirth,
ExpiryDate = mrzData.ExpiryDate,
RawMrz = mrzData.MRZ,
// Full page text from same package
FullPageText = fullResult.Text,
// Barcodes alongside text — no separate product
Barcodes = fullResult.Barcodes.Select(b => b.Value).ToList(),
Confidence = fullResult.Confidence
};
}
}
Imports IronOcr
Public Class IronOcrPassportProcessor
Private ReadOnly _ocr As IronTesseract
Public Sub New()
_ocr = New IronTesseract()
_ocr.Configuration.ReadBarCodes = True ' barcodes included
End Sub
Public Function ProcessPassport(imagePath As String) As CompletePassportResult
' Structured MRZ fields — no manual parsing required
Dim mrzData = _ocr.ReadPassport(imagePath)
' Full page OCR + barcodes in the same call
Dim fullResult = _ocr.Read(imagePath)
Return New CompletePassportResult With {
' MRZ fields are already parsed properties
.DocumentType = mrzData.DocumentType,
.IssuingCountry = mrzData.IssuingCountry,
.Surname = mrzData.Surname,
.GivenNames = mrzData.GivenNames,
.PassportNumber = mrzData.DocumentNumber,
.Nationality = mrzData.Nationality,
.DateOfBirth = mrzData.DateOfBirth,
.ExpiryDate = mrzData.ExpiryDate,
.RawMrz = mrzData.MRZ,
' Full page text from same package
.FullPageText = fullResult.Text,
' Barcodes alongside text — no separate product
.Barcodes = fullResult.Barcodes.Select(Function(b) b.Value).ToList(),
.Confidence = fullResult.Confidence
}
End Function
End Class
하나의 패키지, 하나의 라이선스 키, 하나의 API. 여권 판독 가이드 와 바코드 판독 기능은 동일한 제품이기 때문에IronOCR문서에서 같은 제품 맥락에서 모두 다룹니다.
다중 제품 비용 및 복잡성
창고 재고 스캐너를 구축하는 것은 비용 모델의 차이를 가장 명확하게 보여줍니다. 해당 시스템은 제품 라벨(텍스트)을 읽고, 바코드(QR/EAN)를 스캔하고, 첨부된 배송 PDF 파일을 처리해야 합니다. Dynamsoft의 경우, 각각 별도의 라이선스를 보유하고 있으며 초기화 패턴도 서로 다른 세 가지 제품입니다.
Dynamsoft 접근 방식
// Dynamsoft warehouse scanner — THREE products, THREE license keys
using Dynamsoft.DLR; // Label Recognizer — product labels
using Dynamsoft.DBR; // Barcode Reader — product barcodes
using Dynamsoft.DDN; // Document Normalizer — document edge detection
public class DynamsoftWarehouseScanner : IDisposable
{
private readonly LabelRecognizer _labelRecognizer;
private readonly BarcodeReader _barcodeReader;
private readonly DocumentNormalizer _documentNormalizer;
public DynamsoftWarehouseScanner(
string labelLicenseKey,
string barcodeLicenseKey,
string documentLicenseKey)
{
LabelRecognizer.InitLicense(labelLicenseKey);
_labelRecognizer = new LabelRecognizer();
BarcodeReader.InitLicense(barcodeLicenseKey);
_barcodeReader = new BarcodeReader();
DocumentNormalizer.InitLicense(documentLicenseKey);
_documentNormalizer = new DocumentNormalizer();
}
public WarehouseItemResult ScanItem(string imagePath)
{
// Three separate API calls, three result types to aggregate manually
var labelResults = _labelRecognizer.RecognizeFile(imagePath);
var barcodeResults = _barcodeReader.DecodeFile(imagePath);
var docResults = _documentNormalizer.Normalize(imagePath);
// Merge three result sets into one model — your code
return AggregateResults(labelResults, barcodeResults, docResults);
}
public void Dispose()
{
_labelRecognizer?.Dispose();
_barcodeReader?.Dispose();
_documentNormalizer?.Dispose();
}
}
// Dynamsoft warehouse scanner — THREE products, THREE license keys
using Dynamsoft.DLR; // Label Recognizer — product labels
using Dynamsoft.DBR; // Barcode Reader — product barcodes
using Dynamsoft.DDN; // Document Normalizer — document edge detection
public class DynamsoftWarehouseScanner : IDisposable
{
private readonly LabelRecognizer _labelRecognizer;
private readonly BarcodeReader _barcodeReader;
private readonly DocumentNormalizer _documentNormalizer;
public DynamsoftWarehouseScanner(
string labelLicenseKey,
string barcodeLicenseKey,
string documentLicenseKey)
{
LabelRecognizer.InitLicense(labelLicenseKey);
_labelRecognizer = new LabelRecognizer();
BarcodeReader.InitLicense(barcodeLicenseKey);
_barcodeReader = new BarcodeReader();
DocumentNormalizer.InitLicense(documentLicenseKey);
_documentNormalizer = new DocumentNormalizer();
}
public WarehouseItemResult ScanItem(string imagePath)
{
// Three separate API calls, three result types to aggregate manually
var labelResults = _labelRecognizer.RecognizeFile(imagePath);
var barcodeResults = _barcodeReader.DecodeFile(imagePath);
var docResults = _documentNormalizer.Normalize(imagePath);
// Merge three result sets into one model — your code
return AggregateResults(labelResults, barcodeResults, docResults);
}
public void Dispose()
{
_labelRecognizer?.Dispose();
_barcodeReader?.Dispose();
_documentNormalizer?.Dispose();
}
}
Imports Dynamsoft.DLR ' Label Recognizer — product labels
Imports Dynamsoft.DBR ' Barcode Reader — product barcodes
Imports Dynamsoft.DDN ' Document Normalizer — document edge detection
Public Class DynamsoftWarehouseScanner
Implements IDisposable
Private ReadOnly _labelRecognizer As LabelRecognizer
Private ReadOnly _barcodeReader As BarcodeReader
Private ReadOnly _documentNormalizer As DocumentNormalizer
Public Sub New(labelLicenseKey As String, barcodeLicenseKey As String, documentLicenseKey As String)
LabelRecognizer.InitLicense(labelLicenseKey)
_labelRecognizer = New LabelRecognizer()
BarcodeReader.InitLicense(barcodeLicenseKey)
_barcodeReader = New BarcodeReader()
DocumentNormalizer.InitLicense(documentLicenseKey)
_documentNormalizer = New DocumentNormalizer()
End Sub
Public Function ScanItem(imagePath As String) As WarehouseItemResult
' Three separate API calls, three result types to aggregate manually
Dim labelResults = _labelRecognizer.RecognizeFile(imagePath)
Dim barcodeResults = _barcodeReader.DecodeFile(imagePath)
Dim docResults = _documentNormalizer.Normalize(imagePath)
' Merge three result sets into one model — your code
Return AggregateResults(labelResults, barcodeResults, docResults)
End Function
Public Sub Dispose() Implements IDisposable.Dispose
_labelRecognizer?.Dispose()
_barcodeReader?.Dispose()
_documentNormalizer?.Dispose()
End Sub
End Class
배송 PDF를 처리하려면 여전히 네 번째 제품이 필요합니다. Dynamsoft에는 자체 PDF OCR 기능이 없기 때문입니다. Dynamsoft 제품 3종에 대한 서버별 연간 라이선스 비용은 $5,997 이상입니다. PDF 라이브러리를 추가하면 비즈니스 로직을 한 줄도 작성하기 전에 연간 6,300달러 이상이 소요됩니다.
IronOCR접근법
using IronOcr;
public class IronOcrWarehouseScanner
{
private readonly IronTesseract _ocr;
public IronOcrWarehouseScanner()
{
_ocr = new IronTesseract();
_ocr.Configuration.ReadBarCodes = true; // barcodes in same pass
}
public WarehouseItemResult ScanItem(string imagePath)
{
// One call: text + barcodes + structured word positions
var result = _ocr.Read(imagePath);
return new WarehouseItemResult
{
AllText = result.Text,
Barcodes = result.Barcodes.Select(b => new BarcodeInfo
{ Format = b.Format.ToString(), Value = b.Value }).ToList(),
Confidence = result.Confidence
};
}
public string ScanLabelRegion(string imagePath, int x, int y, int width, int height)
{
// Target a specific label area — no template JSON required
var region = new CropRectangle(x, y, width, height);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
input.Deskew();
input.Contrast();
return _ocr.Read(input).Text;
}
public string ProcessShipmentPdf(string pdfPath)
{
// Native PDF — no external library, no page conversion loop
return _ocr.Read(pdfPath).Text;
}
}
using IronOcr;
public class IronOcrWarehouseScanner
{
private readonly IronTesseract _ocr;
public IronOcrWarehouseScanner()
{
_ocr = new IronTesseract();
_ocr.Configuration.ReadBarCodes = true; // barcodes in same pass
}
public WarehouseItemResult ScanItem(string imagePath)
{
// One call: text + barcodes + structured word positions
var result = _ocr.Read(imagePath);
return new WarehouseItemResult
{
AllText = result.Text,
Barcodes = result.Barcodes.Select(b => new BarcodeInfo
{ Format = b.Format.ToString(), Value = b.Value }).ToList(),
Confidence = result.Confidence
};
}
public string ScanLabelRegion(string imagePath, int x, int y, int width, int height)
{
// Target a specific label area — no template JSON required
var region = new CropRectangle(x, y, width, height);
using var input = new OcrInput();
input.LoadImage(imagePath, region);
input.Deskew();
input.Contrast();
return _ocr.Read(input).Text;
}
public string ProcessShipmentPdf(string pdfPath)
{
// Native PDF — no external library, no page conversion loop
return _ocr.Read(pdfPath).Text;
}
}
Imports IronOcr
Public Class IronOcrWarehouseScanner
Private ReadOnly _ocr As IronTesseract
Public Sub New()
_ocr = New IronTesseract()
_ocr.Configuration.ReadBarCodes = True ' barcodes in same pass
End Sub
Public Function ScanItem(imagePath As String) As WarehouseItemResult
' One call: text + barcodes + structured word positions
Dim result = _ocr.Read(imagePath)
Return New WarehouseItemResult With {
.AllText = result.Text,
.Barcodes = result.Barcodes.Select(Function(b) New BarcodeInfo With {
.Format = b.Format.ToString(),
.Value = b.Value
}).ToList(),
.Confidence = result.Confidence
}
End Function
Public Function ScanLabelRegion(imagePath As String, x As Integer, y As Integer, width As Integer, height As Integer) As String
' Target a specific label area — no template JSON required
Dim region = New CropRectangle(x, y, width, height)
Using input As New OcrInput()
input.LoadImage(imagePath, region)
input.Deskew()
input.Contrast()
Return _ocr.Read(input).Text
End Using
End Function
Public Function ProcessShipmentPdf(pdfPath As String) As String
' Native PDF — no external library, no page conversion loop
Return _ocr.Read(pdfPath).Text
End Function
End Class
지역 기반 OCR 문서 및 PDF 입력 가이드 의 경우,IronOCR추가 제품 없이 두 가지 모두를 지원합니다.
배포 모델
두 라이브러리 모두 사내에서 운영되며 문서 데이터는 클라우드로 전송되지 않습니다. 주요 배포 차이점은 초기화 패턴, 구성 파일 관리, 그리고 각 라이브러리가 배포 아티팩트에 포함하는 내용에 있습니다.
Dynamsoft 접근 방식
Dynamsoft는 인스턴스를 생성하기 전에 SDK 클래스에 대한 정적 초기화 호출을 요구합니다. 각 제품에는 고유한 초기화 패턴이 있으며, 라이선스 키는 해당 특정 제품만 활성화합니다. 템플릿 구성 파일 — MRZ, VIN, 또는 사용자 정의 레이블 패턴에 대한 JSON 설정 문서 — 는 런타임에 존재해야 하며 올바르게 참조되어야 합니다. 라벨 인식기 및 바코드 리더기를 포함하는 배포는 두 개의 활성화 흐름, 두 개의 템플릿 세트, 그리고 두 개의 Dispose 체인을 관리합니다.
창고 또는 키오스크 배포의 경우 구성 파일 종속성으로 인해 바이너리 외에 배포 아티팩트가 추가됩니다. JSON 템플릿은 패키지에 컴파일되지 않고 별도의 파일로 존재합니다. 새 서버에서 템플릿 경로를 잘못 구성하면, 인식은 조용히 빈 결과를 반환하거나 런타임 중 AppendSettingsFromString 호출에서 오류를 발생시킵니다.
IronOCR접근법
IronOCR 단일 NuGet 패키지로 배포됩니다. 라이선스 활성화는 한 줄짜리 문자열 할당으로 이루어집니다.
// Application startup — one line, works for all features
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
// Application startup — one line, works for all features
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
' Application startup — one line, works for all features
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
템플릿 파일이 없습니다. 네이티브 바이너리 관리 기능이 없습니다. tessdata 폴더가 없습니다. Docker 배포 가이드는 Linux에서 오직 libgdiplus만 요구하며 — Dockerfile의 한 줄인 apt-get install를 필요로 합니다.
FROM mcr.microsoft.com/dotnet/aspnet:8.0
RUN apt-get update && apt-get install -y libgdiplus
COPY --from=build /app/publish /app
WORKDIR /app
ENTRYPOINT ["dotnet", "YourApp.dll"]
이 패키지는 플랫폼별 구성 없이 Linux , AWS Lambda 및 Azure App Service를 모두 지원합니다. CI/CD 파이프라인을 운영하는 팀의 경우, 버전 관리나 아티팩트 배포를 위해 별도로 관리해야 할 템플릿 파일이 없습니다.
API 매핑 참조
| Dynamsoft 라벨 인식기 | IronOCR에 상응하는 |
|---|---|
LabelRecognizer.InitLicense(key) |
IronOcr.License.LicenseKey = key |
new LabelRecognizer() |
new IronTesseract() |
_recognizer.AppendSettingsFromString(json) |
필요 없음 — 엔진 자동 구성 |
_recognizer.RecognizeFile(path) |
ocr.Read(path) |
_recognizer.RecognizeByFile(path, "") |
ocr.Read(path) |
result.LineResults[i].Text |
result.Lines[i].Text |
| 수동 TD3 MRZ 파서(150개 이상의 라인) | ocr.ReadPassport(path).Surname 등 |
BarcodeReader.InitLicense(key) (별도의 제품) |
ocr.Configuration.ReadBarCodes = true |
_barcodeReader.DecodeFile(path) |
result.Barcodes (OCR과 동일한 호출) |
barcode.BarcodeFormatString |
barcode.Format.ToString() |
barcode.BarcodeText |
barcode.Value |
DocumentNormalizer.InitLicense(key) (별도의 제품) |
필요하지 않음 |
| PDF를 지원하지 않습니다. | ocr.Read("document.pdf") |
| 검색 가능한 PDF 출력 없음 | result.SaveAsSearchablePdf(path) |
recognizer.Dispose() |
using var ocr = new IronTesseract() |
팀이 Dynamsoft에서IronOCR로 전환을 고려할 때
적용 범위가 MRZ 또는 라벨을 넘어 확장됩니다
대부분의 마이그레이션은 프로젝트가 "여권 MRZ만 읽으면 된다"와 같이 범위가 좁게 시작되었다가 나중에 제품 요구 사항이 추가될 때 발생합니다. 클라이언트는 스캔한 여권을 검색 가능한 PDF로 보관하기를 원합니다. 규정 준수팀은 비자 스탬프를 OCR로 분석하려고 합니다. 지원 대기열에는 Dynamsoft에서 인식할 수 없는 PDF 관련 문의가 있습니다. 현재 팀은 MRZ 파일 처리를 위해 Dynamsoft를 유지 관리하고 Plus 외 모든 파일 처리를 위해 별도의 OCR 라이브러리를 사용하고 있습니다. 동일한 코드베이스 내에 두 개의 라이선스 계약, 두 개의 유지보수 경로, 두 개의 API 패턴이 존재합니다. IronOCR는 처음 MRZ 요구사항을 ReadPassport()를 통해 처리하고, 확장된 요구사항을 동일한 IronTesseract 인스턴스를 통해 처리합니다. 일반적으로 두 개의 라이브러리 시스템에서 하나의 패키지로 전환하는 팀은 통합 계층 코드량이 30~40% 감소한다고 보고합니다.
연간 구독료는 지속 가능하지 않습니다.
다중 제품 Dynamsoft 라이선스 비용은 매년 복리로 증가합니다 — 현재 가격은 Dynamsoft에 문의하십시오. 여러 해에 걸쳐, 여러 제품의 연간 구독료를 합하면 IronOCR의 $999 일회 사용료를 크게 초과할 수 있습니다. 영구적 라이선싱 모델은 상업적 수명이 정해진 제품에는 매우 중요합니다 — 7년 동안 운영될 정부 문서 처리 시스템은 핵심 구성 요소에 대한 연간 갱신 의존성을 전문 벤더에게 원하지 않습니다.
PDF 입력이 필요합니다.
Dynamsoft Label Recognizer는 PDF를 기본적으로 지원하지 않습니다. PDF 형식으로 제공되는 모든 문서는 전처리 단계를 거쳐야 합니다. 각 페이지를 이미지로 렌더링하고, Dynamsoft를 통해 이미지를 처리하고, 결과를 수집 및 재조립하는 과정입니다. 해당 파이프라인은 PDF 렌더링 종속성, 페이지 반복 루프, 그리고 인식 결과를 원래 PDF 형상과 연관시켜야 할 경우 좌표 매핑 문제를 추가합니다. IronOCR는 PDF를 기본적으로 읽습니다 — ocr.Read("passport-scans.pdf")는 모든 페이지를 처리하며, result.Pages을 통해 각 페이지에 대한 텍스트, 단어, 신뢰도 점수를 제공합니다. 입력 데이터의 20% 이상이 PDF 형식인 팀의 경우, Dynamsoft의 해결 방법은 PDF 렌더링 라이브러리가 업데이트될 때마다 상당한 유지 관리 부담을 추가합니다.
다중 제품 통합에 대한 세금이 너무 높습니다.
모든 추가적인 Dynamsoft 제품은 별도의 정적 초기화 호출, 별도의 Dispose 체인, 그리고 별도의 JSON 구성 파일 관리를 필요로 합니다. Dynamsoft 제품 3개를 통합한 팀들은 통합 표면이 주요 유지 관리 비용이지, 인식 품질이 주요 유지 관리 비용이 아니라고 보고합니다. 라이선스 키 순환, SDK 버전 업그레이드 및 템플릿 파일 배포는 세 가지 제품 모두에서 동시에 조정되어야 합니다. IronOCR의 단일 패키지 모델은 애플리케이션에서 사용하는 OCR 기능의 수와 관계없이 업그레이드할 버전 하나, 교체할 라이선스 키 하나, 유지 관리할 API 인터페이스 하나만 있으면 된다는 것을 의미합니다.
국제 문서 유형이 필요합니다
Dynamsoft Label Recognizer는 ICAO Doc 9303에 따른 라틴 문자 MRZ 형식을 기반으로 구축되었습니다. CJK 문자로 된 신분증, 아랍어 여권 또는 다국어 배송 라벨을 처리하는 애플리케이션은 언어 지원 한계에 빠르게 도달합니다.IronOCR아랍어, 중국어 간체, 중국어 번체, 일본어, 한국어 등을 포함한 125개 이상의 언어 팩을 개별 NuGet 패키지로 제공합니다. 각각은 인식 코드를 변경하지 않고 dotnet add package IronOcr.Languages.Arabic을 통해 설치됩니다. 다국어 지원 가이드에서는 몇 줄의 설정만으로 여러 언어를 동시에 인식하는 방법을 설명합니다.
일반적인 마이그레이션 고려사항
MRZ 파서 교체
즉각적인 마이그레이션 단계는 Dynamsoft RecognizeFile + 수동 TD3 파서 결합을 ReadPassport으로 대체하는 것입니다. Dynamsoft 추출 경로는 P<GBRSMITH<<JOHN<<<<<<<<<<<<<<<<<<<<<<<<<<과 같은 원본 텍스트를 반환하며 TD3 형식을 위해 150줄 이상의 문자 오프셋 구문 분석이 필요합니다.IronOCR대체 프로그램:
// Before: Dynamsoft raw extraction + manual 150-line parser
var results = _recognizer.RecognizeFile(imagePath);
var rawMrz = string.Join("\n", results.SelectMany(r => r.LineResults).Select(l => l.Text));
var parsed = MyTd3Parser.Parse(rawMrz); // delete this file
// After:IronOCR parsed output directly
var passportData = new IronTesseract().ReadPassport(imagePath);
string surname = passportData.Surname;
string docNum = passportData.DocumentNumber;
DateTime? dob = passportData.DateOfBirth;
// Before: Dynamsoft raw extraction + manual 150-line parser
var results = _recognizer.RecognizeFile(imagePath);
var rawMrz = string.Join("\n", results.SelectMany(r => r.LineResults).Select(l => l.Text));
var parsed = MyTd3Parser.Parse(rawMrz); // delete this file
// After:IronOCR parsed output directly
var passportData = new IronTesseract().ReadPassport(imagePath);
string surname = passportData.Surname;
string docNum = passportData.DocumentNumber;
DateTime? dob = passportData.DateOfBirth;
Imports System
Imports System.Linq
' Before: Dynamsoft raw extraction + manual 150-line parser
Dim results = _recognizer.RecognizeFile(imagePath)
Dim rawMrz = String.Join(vbCrLf, results.SelectMany(Function(r) r.LineResults).Select(Function(l) l.Text))
Dim parsed = MyTd3Parser.Parse(rawMrz) ' delete this file
' After: IronOCR parsed output directly
Dim passportData = New IronTesseract().ReadPassport(imagePath)
Dim surname As String = passportData.Surname
Dim docNum As String = passportData.DocumentNumber
Dim dob As DateTime? = passportData.DateOfBirth
수동 파서가 완전히 삭제되었습니다. TD1 (신분증), TD2 (비자), TD3 (여권) 형식 탐지는 ReadPassport 내부에서 자동으로 이루어집니다. 여권 판독 방법 안내 문서에는 반환된 모든 항목이 포함되어 있습니다.
다중 제품 초기화 통합
Dynamsoft 다제품 응용 프로그램은 초기 시작 시 여러 정적인 InitLicense 호출을 가지고 있으며 각자의 키가 필요합니다. 이들을 하나의IronOCR라이선스 라인으로 통합하고 제품별 초기화 블록을 제거하십시오.
// Before: three static initializations
LabelRecognizer.InitLicense(mrzKey);
BarcodeReader.InitLicense(barcodeKey);
DocumentNormalizer.InitLicense(documentKey);
// After: one line, all capabilities enabled
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
var ocr = new IronTesseract();
ocr.Configuration.ReadBarCodes = true; // barcodes included automatically
// Before: three static initializations
LabelRecognizer.InitLicense(mrzKey);
BarcodeReader.InitLicense(barcodeKey);
DocumentNormalizer.InitLicense(documentKey);
// After: one line, all capabilities enabled
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE");
var ocr = new IronTesseract();
ocr.Configuration.ReadBarCodes = true; // barcodes included automatically
Imports System
' Before: three static initializations
LabelRecognizer.InitLicense(mrzKey)
BarcodeReader.InitLicense(barcodeKey)
DocumentNormalizer.InitLicense(documentKey)
' After: one line, all capabilities enabled
IronOcr.License.LicenseKey = Environment.GetEnvironmentVariable("IRONOCR_LICENSE")
Dim ocr As New IronTesseract()
ocr.Configuration.ReadBarCodes = True ' barcodes included automatically
서비스 클래스의 기존 Dynamsoft Dispose 호출을 IronTesseract 인스턴스에 대한 표준 using 블록으로 대체하거나 DI 컨테이너에 등록된 단일 재사용 인스턴스로 대체해야 합니다. IronTesseract 설정 가이드는 두 가지 패턴 모두를 다룹니다.
PDF 지원 추가
마이그레이션 과정에서 팀이 가장 많이 새롭게 확보하는 기능은 네이티브 PDF 입력 기능인데, 이는 Dynamsoft에서는 제공하지 않던 기능입니다. PDF를 이미지로 변환하는 반복문을 제거한 후에는 입력 경로 외에는 네이티브 PDF 읽기를 위한 코드 변경이 필요하지 않습니다.
// Before: PDF rendering loop (50+ lines with external library)
var pdfDoc = PdfDocument.Load(pdfPath);
foreach (var page in pdfDoc.Pages)
{
var bitmap = page.RenderAsBitmap(150);
var results = _labelRecognizer.RecognizeFile(SaveBitmapToTemp(bitmap));
// aggregate...
}
// After: native PDF — no loop, no external library
var result = new IronTesseract().Read(pdfPath);
string fullText = result.Text;
result.SaveAsSearchablePdf("searchable-output.pdf");
// Before: PDF rendering loop (50+ lines with external library)
var pdfDoc = PdfDocument.Load(pdfPath);
foreach (var page in pdfDoc.Pages)
{
var bitmap = page.RenderAsBitmap(150);
var results = _labelRecognizer.RecognizeFile(SaveBitmapToTemp(bitmap));
// aggregate...
}
// After: native PDF — no loop, no external library
var result = new IronTesseract().Read(pdfPath);
string fullText = result.Text;
result.SaveAsSearchablePdf("searchable-output.pdf");
Imports IronOcr
' Before: PDF rendering loop (50+ lines with external library)
Dim pdfDoc = PdfDocument.Load(pdfPath)
For Each page In pdfDoc.Pages
Dim bitmap = page.RenderAsBitmap(150)
Dim results = _labelRecognizer.RecognizeFile(SaveBitmapToTemp(bitmap))
' aggregate...
Next
' After: native PDF — no loop, no external library
Dim result = New IronTesseract().Read(pdfPath)
Dim fullText As String = result.Text
result.SaveAsSearchablePdf("searchable-output.pdf")
스캔된 입력물로부터 검색 가능한 PDF 아카이브를 생성해야 하는 팀의 경우, SaveAsSearchablePdf는 단일 메서드 호출입니다. 검색 가능한 PDF 설명서에는 출력 옵션에 대한 자세한 내용이 나와 있습니다.
산업용 라벨 품질을 위한 전처리
Dynamsoft의 템플릿 엔진은 제어된 레이블 조건에 최적화되어 있습니다. 손상된 이미지(닳은 라벨, 저대비 포장, 왜곡된 산업 스캔 이미지 등)의 경우, IronOCR의 전처리 파이프라인이 이러한 문제를 해결합니다. 이미지 품질 보정 가이드 에서 각 필터에 대한 자세한 내용을 확인할 수 있습니다. 라벨 특화 워크플로에 있어서는 Deskew 와 Contrast가 가장 유용합니다:
using var input = new OcrInput();
input.LoadImage(labelImagePath);
input.Deskew(); // correct rotation from handheld scanner
input.Contrast(); // recover faded label text
input.DeNoise(); // remove packaging texture interference
var labelText = new IronTesseract().Read(input).Text;
Console.WriteLine($"Confidence: {new IronTesseract().Read(input).Confidence}%");
using var input = new OcrInput();
input.LoadImage(labelImagePath);
input.Deskew(); // correct rotation from handheld scanner
input.Contrast(); // recover faded label text
input.DeNoise(); // remove packaging texture interference
var labelText = new IronTesseract().Read(input).Text;
Console.WriteLine($"Confidence: {new IronTesseract().Read(input).Confidence}%");
Imports IronOcr
Using input As New OcrInput()
input.LoadImage(labelImagePath)
input.Deskew() ' correct rotation from handheld scanner
input.Contrast() ' recover faded label text
input.DeNoise() ' remove packaging texture interference
Dim labelText = New IronTesseract().Read(input).Text
Console.WriteLine($"Confidence: {New IronTesseract().Read(input).Confidence}%")
End Using
IronOCR의 추가 기능
위에서 다루지 않았지만 마이그레이션 후 팀에서 자주 사용하는 기능은 다음과 같습니다.
- 필기 인식 : 인쇄된 텍스트와 함께 손으로 쓴 메모 및 주석을 처리할 수 있습니다. 이는 Dynamsoft에서 제공하지 않는 기능입니다.
- 스캔 문서 처리 : 여러 페이지로 구성된 스캔 PDF 파일을 페이지별로 자동 전처리합니다.
- 표 형식 데이터 추출 : 송장, 운송장 및 데이터 시트에서 표 형식 데이터를 감지하고 추출합니다.
- hOCR 내보내기 : 하위 레이아웃 분석을 위해 경계 상자 좌표가 포함된 인식 결과를 HTML 형식으로 내보냅니다.
- 비동기 OCR : ASP.NET 및 고처리량 서버 애플리케이션을 위한 비차단 인식 기능
- 진행 상황 추적 : 진행 상황 콜백을 통해 여러 페이지로 구성된 배치 작업을 모니터링합니다.
- 125개 이상 언어 색인 : 라틴어 이외의 문자를 포함한 지원되는 언어 NuGet 팩의 전체 목록
- MICR/수표 판독 : 금융 문서 처리를 위한 자기 잉크 문자 인식 — 하나의 패키지로 처리되는 또 다른 특수 사용 사례입니다.
- 단어별 신뢰도 점수 : 자동 문서 검토 파이프라인을 위한 세분화된 품질 신호
.NET 호환성 및 미래 준비
IronOCR .NET 8 및 .NET 9를 주요 지원 런타임으로 삼고 있으며, .NET Framework 4.6.2 및 .NET Core 3.1과의 완벽한 하위 호환성을 제공합니다. 이 라이브러리는 단일 NuGet 패키지로 제공되며, NuGet의 런타임 식별자 그래프를 통해 Windowsx64, Windowsx86, Linuxx64, macOSx64 및 macOSARM에 맞는 플랫폼 바이너리를 자동으로 찾아줍니다. 조건부 패키지 참조나 플랫폼별 프로젝트 파일이 필요하지 않습니다. Dynamsoft 라벨 인식기 역시 최신 .NET 런타임을 지원하지만, 여러 제품으로 구성된 모델 때문에 각 제품의 .NET 호환성은 개별적으로 검증하고 업데이트해야 합니다. IronOCR은 활발한 개발 주기를 통해 각 .NET 릴리스 주기에 맞춰 NuGet 패키지 업데이트를 제공하며, 단일 패키지 모델을 통해 2026년 말에 출시될 예정인 .NET 10과의 호환성이 제품별 추적 없이 모든 기능에 균일하게 적용됩니다.
결론
Dynamsoft Label Recognizer는 기술적으로 뛰어난 전문 소프트웨어입니다. 여권 MRZ만 처리하는 키오스크나 차량 식별 번호(VIN)만 읽는 조립 라인 스테이션과 같은 특정 용도에 적합한 템플릿 기반 인식 엔진을 통해 안정적인 작업을 수행할 수 있습니다. 문제는 실제 적용 사례들이 드물게 특정 분야에만 국한된다는 점입니다. 여권은 모든 데이터 페이지를 OCR로 인식해야 합니다. 배송 라벨은 PDF 파일로 제공됩니다. 재고 관리 시스템은 바코드와 텍스트 정보를 동시에 처리해야 합니다. 범위가 확장될 때마다 새로운 Dynamsoft 제품, 새로운 연간 라이선스, 그리고 유지 관리해야 할 새로운 API 표면이 발생합니다.
비용 모델은 이를 구체화합니다. MRZ 및 바코드 판독을 위한 다년간의 개발 팀에서 Dynamsoft의 연간 구독 모델을 사용한 비용은 상당히 증가합니다. IronOCR는 두 기능 모두를 포함합니다 — 기본 PDF, 검색 가능한 PDF 출력, 전체 문서 OCR, 125개 이상의 언어 및 사전 처리 — $999 일회 사용료로 제공합니다. 마이그레이션 자체는 크게 기계적입니다: RecognizeFile을 ocr.Read로 대체하고, 수동 TD3 MRZ 파서를 삭제하고, ReadBarCodes = true을 활성화하며 외부 PDF 렌더링 루프를 제거합니다.
아키텍처상의 차이점은 단순히 비용에만 있는 것이 아닙니다. Dynamsoft의 설계 방식은 팀이 기능이 아닌 제품이라는 관점에서 생각하도록, 즉 코드를 작성하기 전에 "어떤 Dynamsoft 제품이 이 기능을 지원하는가?"라고 질문하도록 유도합니다. IronOCR의 설계 방식은 이와 정반대입니다. 문서 내용과 관계없이 하나의 인스턴스, 하나의 구성, 하나의 결과 객체만 존재합니다. 프로젝트가 진행됨에 따라 요구사항이 증가하면서 그러한 차이는 더욱 커집니다.
MRZ 인식, 바코드 판독, 일반 문서 OCR 또는 PDF 처리 등 다양한 기능을 조합하여 새로운 애플리케이션을 개발하는 팀의 경우, IronOCR의 올인원 모델은 처음부터 여러 제품을 조율해야 하는 문제를 해결해 줍니다. 현재 여러 Dynamsoft 제품과 별도의 OCR 라이브러리를 함께 사용하는 팀의 경우, 마이그레이션 경로를 통해 이러한 모든 요소가 단일 종속성으로 통합됩니다. IronOCR 문서 허브는 여기에서 설명한 모든 기능에 대한 자세한 내용을 작동 코드 예제 및 배포 가이드와 함께 제공합니다.
자주 묻는 질문
Dynamsoft OCR SDK란 무엇인가요?
Dynamsoft OCR SDK는 개발자와 기업이 이미지와 문서에서 텍스트를 추출하는 데 사용하는 OCR 솔루션입니다. 이 솔루션은 .NET 애플리케이션 개발용 IronOCR과 함께 평가된 여러 OCR 옵션 중 하나입니다.
IronOCR은 .NET 개발자를 위한 Dynamsoft OCR SDK와 어떻게 비교되나요?
IronOCR은 IronTesseract를 핵심 엔진으로 사용하는 NuGet 네이티브 .NET OCR 라이브러리입니다. Dynamsoft OCR SDK에 비해 배포가 간편하고(SDK 설치 프로그램 없음), 정액제 요금이 적용되며, COM 상호 운용 또는 클라우드 종속성이 없는 깔끔한 C# API를 제공합니다.
IronOCR이 Dynamsoft OCR SDK보다 설정이 더 쉬운가요?
IronOCR은 단일 NuGet 패키지를 통해 설치됩니다. SDK 설치 프로그램, 복사할 라이선스 파일, 등록할 COM 구성 요소 또는 관리해야 할 별도의 런타임 바이너리가 없습니다. 전체 OCR 엔진이 패키지에 번들로 제공됩니다.
Dynamsoft OCR SDK와 IronOCR 사이에는 어떤 정확도 차이가 있나요?
IronOCR은 표준 비즈니스 문서, 송장, 영수증, 스캔 양식에 대해 높은 인식 정확도를 달성합니다. 품질이 많이 저하된 문서나 일반적이지 않은 스크립트의 경우 정확도는 소스 품질에 따라 달라집니다. IronOCR에는 이미지 전처리 필터가 포함되어 있어 저품질 입력에 대한 인식률을 향상시킵니다.
IronOCR은 PDF 텍스트 추출을 지원하나요?
예. IronOCR은 한 번의 호출로 원본 PDF와 스캔한 PDF 이미지 모두에서 텍스트를 추출합니다. 또한 여러 페이지의 TIFF 파일, 이미지, 스트림도 지원합니다. 스캔한 PDF의 경우 OCR은 페이지별 결과 개체를 사용하여 페이지별로 적용됩니다.
Dynamsoft OCR SDK 라이선싱은 IronOCR과 어떻게 비교되나요?
IronOCR은 페이지당 또는 스캔당 요금이 없는 정액제 영구 라이선스를 사용합니다. 대량의 문서를 처리하는 조직은 문서 양에 관계없이 동일한 라이선스 비용을 지불합니다. 자세한 내용과 볼륨 가격은 IronOCR 라이선스 페이지에서 확인할 수 있습니다.
IronOCR 어떤 언어를 지원하나요?
IronOCR은 별도의 NuGet 언어 팩을 통해 127개 언어를 지원합니다. 언어를 추가하려면 '닷넷 추가 패키지 IronOcr.Languages.{Language}' 명령 하나만 있으면 됩니다. 수동으로 파일을 배치하거나 경로를 구성할 필요가 없습니다.
.NET 프로젝트에 IronOCR 설치하는 방법은 무엇인가요?
NuGet을 통해 설치합니다: 패키지 관리자 콘솔에서 '설치-패키지 IronOcr' 또는 CLI에서 '닷넷 추가 패키지 IronOcr'을 실행합니다. 추가 언어 팩도 같은 방법으로 설치됩니다. 기본 SDK 인스톨러가 필요하지 않습니다.
IronOCR은 Dynamsoft OCR과 달리 Docker 및 컨테이너화된 배포에 적합하나요?
예. IronOCR은 NuGet 패키지를 통해 Docker 컨테이너에서 작동합니다. 라이선스 키는 환경 변수를 통해 설정됩니다. OCR 엔진 자체에는 라이선스 파일, SDK 경로 또는 볼륨 마운트가 필요하지 않습니다.
Dynamsoft OCR과 비교하여 구매하기 전에 IronOCR을 사용해 볼 수 있나요?
예. IronOCR 평가판 모드는 문서를 처리하고 출력물에 워터마크 오버레이가 포함된 OCR 결과를 반환합니다. 라이선스를 구매하기 전에 자신의 문서에서 정확성을 확인할 수 있습니다.
IronOCR은 텍스트 추출과 함께 바코드 판독을 지원하나요?
IronOCR은 텍스트 추출과 OCR에 중점을 둡니다. 바코드 판독을 위해 Iron Software는 동반 라이브러리로 IronBarcode를 제공합니다. 두 가지 모두 개별적으로 또는 Iron Suite 번들의 일부로 사용할 수 있습니다.
Dynamsoft OCR SDK에서 IronOCR로 쉽게 마이그레이션할 수 있나요?
Dynamsoft OCR SDK에서 IronOCR로 마이그레이션하려면 일반적으로 초기화 시퀀스를 IronTesseract 인스턴스화로 대체하고, COM 수명 주기 관리를 제거하며, API 호출을 업데이트해야 합니다. 대부분의 마이그레이션은 코드 복잡성을 크게 줄여줍니다.

