일본어 손글씨 메모를 잘 전사해 주는 OCR을 찾기 위해 API 모델과 OSS 모델 26개를 비교 평가한 결과를 정리합니다. Hungarian NLS, Bag-of-Characters F1, CER로 성능을 측정하고, Gemini·Claude·GPT·전용 OCR API·오픈소스 모델의 정확도와 속도를 함께 살펴봅니다.
안녕하세요! 역세가와짱 (@gyakuse) 입니다!
오늘은 일본어 손글씨 메모를 꽤 괜찮게 전사해 주는 OCR을 찾기 위해, 26개 모델을 모조리 비교해 본 이야기를 정리해 보려고 합니다.
저는 아직도 손글씨 메모를 자주 씁니다. 회의 중에 재빨리 적기도 하고, 아이디어를 정리할 때 펜으로 도표를 그리기도 하죠. 손을 움직이면서 생각하는 건 정말 즐겁고, 타이핑과는 다른 방식으로 사고가 확장됩니다.
다만 문제는 전자화입니다. 노트에 적은 메모를 나중에 Slack이나 Notion으로 옮겨 적는 일이 정말 괴롭습니다. 내 글씨를 내가 다시 읽는 작업만으로도 이미 힘든데, 그걸 다시 타이핑하는 건 이중고입니다.
OCR로 자동화하고 싶지만, 일본어 손글씨는 기존 OCR 모델에게 꽤 어려운 과제입니다. 활자라면 어떤 모델이든 높은 정확도를 내지만, 손글씨가 되면 정확도가 뚝 떨어집니다. 게다가 최근에는 OCR 전용 모델이 폭발적으로 늘어나서, HunyuanOCR, DeepSeek-OCR, olmOCR-2, Chandra... 대체 무엇을 써야 할지 모르겠습니다. Claude, Gemini, GPT 같은 범용 VLM도 OCR 능력이 빠르게 올라가고 있고, LayerX의 테크 블로그나 GENSHI AI의 검증 기사에서도 다루고 있습니다.
그렇다면 전부 시험해 보고 비교해 보자, 라는 생각으로 실제로 해 봤습니다.
제대로 비교하려면 먼저 “어떻게 측정할지”를 정해야 합니다. 손글씨 메모는 읽는 순서가 모호한 경우가 많아서(세로쓰기와 가로쓰기가 혼재, 화살표 참조, 둘러싼 문자...) 단순히 CER(Character Error Rate)만 쓰면 읽는 순서가 다르다는 이유만으로 점수가 처참해집니다.
그래서 서로를 보완하는 3개의 지표를 사용했습니다.
| 지표 | 대략적으로 말하면 | 주요 용도 |
|---|---|---|
| Hungarian NLS (primary) | 각 영역의 최적 매칭으로 채점 | 읽는 순서에 의존하지 않는 본질적 정확도 |
| Bag-of-Characters F1 | 문자 집합으로 비교, 어순 무시 | 순수한 문자 인식 정확도 |
| CER | 전체 텍스트의 Levenshtein 거리 | 읽는 순서를 포함한 종합 품질 |
주 지표인 Hungarian NLS는 정답 데이터를 영역 단위로 가지고, 각 영역마다 최적 매칭을 찾는 방식입니다. 자세한 내용은 Appendix: 평가 지표 설계에 적어 두었습니다.
정답 데이터 작성에는 어노테이션 도구도 직접 만들었습니다. 이미지를 업로드하면 대략적인 전처리(용지 검출·기울기 보정·그림자 제거)가 실행된 뒤 어노테이션 화면으로 넘어갑니다. 전처리 로직은 충분히 검증하지 못해서 정확도를 보장할 수는 없지만, 없는 것보다는 낫다 정도의 수준입니다. 자세한 내용은 Appendix: 이미지 전처리에 적어 두었습니다.
이번에는 손글씨 메모 이미지 6장으로 평가했습니다(적긴 하지만 우선 경향을 보고 싶었습니다). 평가 기반 코드는 ocr-comparison에서 공개하고 있습니다.
API로 호출할 수 있는 모델 13개와, GPU 위에서 실행하는 OSS 모델 13개를 비교했습니다.
OSS 모델은 Modal이라는 서버리스 GPU 플랫폼에서 실행했습니다. T4, L4, A100 같은 GPU를 Python 데코레이터 하나로 사용할 수 있어서, 로컬에 GPU가 없어도 평가할 수 있습니다.
| 카테고리 | 모델 | 라이선스 | 비고 |
|---|---|---|---|
| API | Gemini 3.5 Flash | Proprietary | |
| API | Gemini 3.1 Pro Preview | Proprietary | Deep thinking |
| API | Gemini 3 Flash Preview | Proprietary | |
| API | Gemini 3.1 Flash Lite Preview | Proprietary | |
| API | Claude 4.7 Opus | Proprietary | Adaptive thinking |
| API | Claude 4.6 Opus | Proprietary | Adaptive thinking |
| API | Claude 4.5 Sonnet | Proprietary | Extended thinking |
| API | GPT-5.5 | Proprietary | Reasoning effort: high |
| API | GPT-5.4 | Proprietary | Reasoning effort: high |
| API | Google Cloud Vision | Proprietary | |
| API | Azure AI Vision | Proprietary | |
| API | Mistral OCR | Proprietary | mistral-ocr-latest |
| API | Qwen VL OCR | Proprietary | DashScope API |
| Modal (L4) | HunyuanOCR | Apache-2.0 | 1B |
| Modal (L4) | DeepSeek-OCR | MIT | |
| Modal (A100) | Chandra | Apache-2.0 | |
| Modal (L4) | Nanonets-OCR-s | Apache-2.0 | 4B |
| Modal (L4) | olmOCR-2 | Apache-2.0 | 7B FP8 |
| Modal (T4) | GOT-OCR 2.0 | Apache-2.0 | |
| Modal (T4) | PaddleOCR | Apache-2.0 | |
| Modal (T4) | YomiToku | CC-BY-NC-SA-4.0 | 일본어 특화 |
| Modal (T4) | GLM-OCR | MIT | 0.9B |
| Modal (CPU) | NDLOCR-Lite | CC-BY-4.0 | 국립국회도서관 |
| Modal (A10G) | NDLOCR v2 | CC-BY-4.0 | 국립국회도서관 |
| Modal (L4) | Sarashina2.2-OCR | MIT | 3B, 일본어 활자 특화 |
| Modal (L4) | Nemotron OCR v2 | NVIDIA Open Model License | 84M, 전통적 파이프라인 |
이 가운데 DeepSeek-OCR, GOT-OCR 2.0은 일본어를 지원하지 않고, Nanonets-OCR-s는 공식적으로 손글씨를 학습하지 않았다고 명시한 모델입니다. olmOCR-2 역시 공식적으로는 영어 PDF 중심이며 일본어 지원을 명기하지 않았습니다. OCR 벤치마크에서 이름을 자주 보게 되어서 일단 전부 넣어 보았습니다. 무리한 입력을 던진 결과가 어떻게 되었는지는 뒤에서 설명하겠습니다.
YomiToku는 CC-BY-NC-SA-4.0이므로 상업적 이용에는 주의가 필요합니다. 그 외 OSS 모델은 Apache-2.0 또는 MIT라서 상업적으로도 사용할 수 있습니다.
손글씨 메모 6장에 대한 평가 결과입니다(Hungarian NLS 내림차순).
| Rank | 모델 | 카테고리 | NLS | BoC-F1 | CER | Avg Time |
|---|---|---|---|---|---|---|
| 1 | Gemini 3.5 Flash | API | 0.927 | 0.928 | 0.192 | 14.8s |
| 2 | Gemini 3.1 Pro Preview | API | 0.924 | 0.929 | 0.205 | 67.9s |
| 3 | Gemini 3 Flash Preview | API | 0.918 | 0.910 | 0.221 | 18.7s |
| 4 | Gemini 3.1 Flash Lite Preview | API | 0.899 | 0.917 | 0.207 | 13.7s |
| 5 | Claude 4.6 Opus | API | 0.897 | 0.896 | 0.225 | 74.9s |
| 6 | Claude 4.7 Opus | API | 0.858 | 0.883 | 0.276 | 9.5s |
| 7 | Azure AI Vision | API | 0.830 | 0.845 | 0.332 | 4.2s |
| 8 | Google Cloud Vision | API | 0.820 | 0.783 | 0.509 | 2.2s |
| 9 | YomiToku | Modal | 0.770 | 0.768 | 0.400 | 12.0s |
| 10 | GPT-5.5 | API | 0.755 | 0.830 | 0.301 | 98.1s |
| 11 | GLM-OCR | Modal | 0.738 | 0.792 | 0.387 | 29.7s |
| 12 | Chandra | Modal | 0.734 | 0.780 | 0.361 | 29.2s |
| 13 | olmOCR-2 | Modal | 0.723 | 0.786 | 0.370 | 45.4s |
| 14 | Sarashina2.2-OCR | Modal | 0.718 | 0.727 | 0.450 | 24.7s |
| 15 | GPT-5.4 | API | 0.714 | 0.814 | 0.331 | 123.4s |
| 16 | Qwen VL OCR | API | 0.706 | 0.713 | 0.491 | 17.7s |
| 17 | HunyuanOCR | Modal | 0.698 | 0.754 | 0.367 | 30.3s |
| 18 | Claude 4.5 Sonnet | API | 0.640 | 0.709 | 0.465 | 16.4s |
| 19 | Mistral OCR | API | 0.589 | 0.645 | 0.563 | 7.3s |
| 20 | Nanonets-OCR-s | Modal | 0.557 | 0.597 | 0.615 | 69.1s |
| 21 | DeepSeek-OCR | Modal | 0.446 | 0.530 | 0.671 | 35.4s |
| 22 | Nemotron OCR v2 | Modal | 0.413 | 0.562 | 0.705 | 13.0s |
| 23 | PaddleOCR | Modal | 0.353 | 0.394 | 0.784 | 12.8s |
| 24 | NDLOCR-Lite | Modal | 0.271 | 0.394 | 0.915 | 10.5s |
| 25 | GOT-OCR 2.0 | Modal | 0.194 | 0.250 | 0.888 | 10.2s |
| 26 | NDLOCR v2 | Modal | 0.064 | 0.087 | 0.958 | 28.7s |
Avg Time은 이미지 1장당 평균 처리 시간입니다. Modal 모델은 배치 처리 총 시간을 이미지 수로 나눈 값이므로 콜드 스타트를 포함한다는 점에 주의해 주세요.
가장 놀라웠던 점은 Gemini 계열의 안정적인 강세입니다. 1위부터 4위까지를 Gemini 계열이 모두 차지했고, 신모델 Gemini 3.5 Flash가 NLS 0.927로 1위를 기록하며 Gemini 3.1 Pro Preview (0.924)를 근소하게 앞섰습니다. 게다가 처리 시간은 14.8s로 Pro의 67.9s보다 1/4 이하입니다. Flash Lite(가장 가벼운 모델)조차 NLS 0.899로 Claude 4.6 Opus와 동급 수준이어서, 일본어 손글씨 OCR에 관해서는 Gemini가 한 단계 앞서 있습니다.
Claude 4.6 Opus는 5위로 NLS 0.897이라 충분히 높지만, 신세대 Claude 4.7 Opus는 6위(NLS 0.858)로 이전 세대보다 0.04포인트 낮아졌습니다. 반면 Avg Time은 4.6 Opus의 74.9s에서 4.7 Opus는 9.5s로, 무려 약 8배 빨라졌습니다. adaptive thinking이 “굳이 오래 생각하지 않아도 답할 수 있다”고 판단한 것인지, 추론 시간을 크게 줄인 결과 정확도도 조금 떨어진 것으로 보입니다. 실용적으로는 4.7 Opus 쪽이 속도와 정확도의 종합적인 균형을 맞추기 쉬운 경우가 많아 보입니다. Claude 4.5 Sonnet이 18위(NLS 0.640)까지 크게 떨어지는 것도 흥미로운데, 같은 Claude 계열이라도 모델 세대에 따라 차이가 큽니다.
GPT-5.5는 10위(NLS 0.755), GPT-5.4는 15위(NLS 0.714)로, API 모델 중에서는 중위권입니다. 더 최신 세대인 GPT-5.5가 이전 세대보다 0.04포인트 개선되긴 했지만, 그래도 Gemini 계열과 Claude Opus 계열과는 0.10 이상 차이가 납니다. 영어 OCR 벤치마크에서는 강한 모델군이지만, 일본어 손글씨 메모라는 조건에서는 고전하고 있습니다. BoC-F1은 GPT-5.5가 0.830, GPT-5.4가 0.814로 상당히 높은 편인데도 NLS가 낮으므로, 문자는 읽고 있지만 영역 매칭에서 점수를 잃고 있을 가능성이 있습니다. GPT-5.5는 처리 시간도 98.1s로 길어서, reasoning에 들인 시간에 비해 정확도가 충분히 나오지 않는 상황입니다.
OSS 모델 중에서는 YomiToku(9위, NLS 0.770)가 가장 높았고, API인 GPT-5.5 (NLS 0.755)보다도 앞섰습니다. 일본어 특화 설계가 효과를 내고 있습니다. Chandra(12위)도 NLS 0.734로 선전했습니다.
반면 PaddleOCR, NDLOCR 계열은 손글씨 문자에 꽤 약합니다. NDLOCR v2는 국립국회도서관이 공개한 모델로 활자 인쇄 문서에는 강하지만, 손글씨 메모는 범위 밖인 듯합니다.
앞서 말했듯 일본어 비대응 또는 손글씨 미학습 모델에도 무리하게 입력을 던져 봤는데, 각자의 반응이 재미있어서 소개합니다.
olmOCR-2는 영어 PDF 중심 모델이라 일본어 지원이 명시되어 있지 않습니다. 그런데 막상 열어 보니 NLS 0.723으로 GPT-5.4(0.714)를 넘어 13위에 올랐습니다. 베이스 모델이 Qwen2.5-VL이라서, 다국어 능력이 워낙 높다 보니 영어 특화 튜닝이 되어 있어도 일본어 손글씨를 읽어 버리는 듯합니다. VLM의 기본 체급이 무섭다는 걸 느끼게 합니다. A100이 필요한 Chandra와 달리 olmOCR-2는 L4에서 돌아가므로 가성비도 좋습니다.
DeepSeek-OCR은 일본어를 지원하지 않는데, 단순히 에러를 내는 대신 일본어 손글씨를 중국어로 “번역”해서 출력해 오는 점이 특징적이었습니다. “SDKを”가 “SD卡”(SD카드의 중국어)가 되고, “permission mode auto対応”는 “自动权限模式”가 됩니다. 모르는 일본어 손글씨를 문맥으로 추측하고, 자기 모국어로 출력해 버리는 VLM 특유의 할루시네이션입니다.
GOT-OCR 2.0은 580M의 초경량 모델로 영어와 중국어만 지원합니다. 일본어 손글씨 메모를 보여 준 결과는 NLS 0.194였고, 로그를 보면 숫자와 극히 일부 영숫자만 주워서 Cadi g/ Agent Bif f Application y 같은 출력을 만들고 있습니다. 비지원 언어에 대해서는 기호나 숫자만 집어내려 하는, 전통적 OCR에 가까운 거동입니다.
Nanonets-OCR-s는 공식적으로 손글씨를 학습하지 않았다고 밝힌 모델입니다. 손글씨 메모를 보여 준 결과, 일부 이미지에서 패닉을 일으켜 > > > > > > 나 1111... 같은 무의미한 문자를 수천 자에 걸쳐 계속 출력하는 생성 루프에 빠졌습니다. 이 이미지에서는 문자 오류율(CER)이 2100%(21배)라는 이상치를 기록했습니다. repetition_penalty를 올려서 대응했지만, 미학습 입력에 대한 VLM의 취약성이 드러난 순간이었습니다.
Avg Time을 보면 흥미로운 경향이 보입니다. Google Cloud Vision이 2.2s, Azure AI Vision이 4.2s로, 전용 OCR API는 역시 빠릅니다. 정확도도 NLS 0.82〜0.83이므로 속도를 중시한다면 이 둘은 충분히 선택지에 들어갑니다.
정확도와 속도의 균형에서 압도적으로 강한 것은 신모델 Gemini 3.5 Flash로, 14.8s에 NLS 0.927을 기록합니다. Pro의 정확도를 1/4 이하 시간에 달성하고 있으므로, 현재로서는 이 모델이 거의 최적해입니다. Gemini 3.1 Flash Lite도 13.7s에 NLS 0.899로 잘 버티고 있어서, 3.5 Flash를 쓸 수 없는 환경에서는 대체 후보가 됩니다. Pro는 67.9s가 걸려서 Flash Lite보다 5배 느리지만, 정확도 차이는 NLS 0.025에 불과합니다.
GPT-5.4는 123.4s, GPT-5.5도 98.1s로 압도적으로 느립니다. reasoning effort: high로 추론시키고 있으니 어쩔 수는 없지만, 그만큼 시간을 들여도 NLS 0.71〜0.76이라면 가성비가 좋지 않습니다.
OSS 모델에서는 YomiToku가 12.0s로 최속급이면서 정확도도 가장 높아(NLS 0.770), 속도·정확도·비용의 삼박자를 갖추고 있습니다. 다만 Modal의 콜드 스타트를 포함한 시간이므로, 상시 기동 환경이라면 더 빨라질 것입니다.
숫자만으로는 감이 잘 오지 않으므로, 실제 손글씨 메모 이미지와 각 모델의 출력을 Appendix: 이미지별 OCR 출력 예시에 전부 실어 두었습니다.
현재 시점에서 가장 좋은 선택은 Gemini 3.5 Flash(NLS 0.927, 14.8s)입니다. 정확도는 Pro를 넘어섰고, 처리 시간은 Pro의 1/4 이하입니다. NLS 0.927은 “대체로 읽고 있다”는 수준으로, 다소의 오독은 있어도 대략적으로 전자화하기에는 충분히 쓸 만합니다. Flash 계열이 한계에 부딪히기는커녕 오히려 Pro를 넘어선 것은 예상 밖이었습니다.
정확도를 조금이라도 더 끌어올리고 싶다면 Gemini 3.1 Pro Preview(NLS 0.924, 67.9s)도 선택지이지만, 차이는 NLS 0.003이라 체감상 거의 같습니다.
속도를 중시한다면 Google Cloud Vision(NLS 0.820, 2.2s)이나 Azure AI Vision(NLS 0.830, 4.2s)도 선택지에 들어갑니다. 정확도는 상위 모델에 못 미치지만, 대량의 메모를 한꺼번에 처리해야 하는 경우에는 현실적입니다.
OSS 모델을 직접 실행하고 싶다면 YomiToku(NLS 0.770, 12.0s)가 정확도·속도·비용의 삼박자를 갖추고 있습니다.
다만 주의할 점으로, 이번 평가는 손글씨 메모 6장이라는 소수 표본이므로 이미지 수를 늘리면 순위가 바뀔 가능성은 충분합니다. 평가 기반은 공개되어 있으니, 자신의 메모로 시험해 보는 것이 가장 확실합니다.
기사 공개 후 GLM-OCR을 넣는 것을 잊었다는 걸 깨달아서 추가했습니다(당시 19개 모델, 현재는 20개 모델).
GLM-OCR은 CogViT (0.4B) + GLM-0.5B로 총 0.9B 파라미터인 초경량 모델로, OmniDocBench V1.5에서 1위 점수를 기록하고 있습니다. vLLM에서는 glm_ocr 아키텍처가 아직 지원되지 않아, transformers를 소스 빌드해서 직접 추론했습니다.
결과는 NLS 0.738로 11위에 올랐습니다. 0.9B로 이 정도 정확도는 상당히 우수합니다. T4 GPU에서 돌아가므로 Modal 비용도 저렴하고, A100이 필요한 Chandra(NLS 0.734)와 거의 같은 정확도를 T4에서 낼 수 있다는 점에서 가성비가 돋보입니다.
OSS 모델의 파라미터 수를 나열하면 olmOCR-2가 7B, Nanonets가 4B, HunyuanOCR가 1B인데, GLM-OCR의 0.9B는 최경량급입니다. 그런데도 NLS 0.738이니 파라미터 효율이 상당히 높다고 할 수 있습니다.
출력을 보면 “比較”가 “比较”(간체자)로 나오기도 하는 등 DeepSeek-OCR과 비슷한 중국어 누출이 보입니다. 베이스 모델인 GLM이 중국어에 강하므로, 일본어 한자를 간체자로 출력해 버리는 경우가 있는 듯합니다. 한편 “Agent skill が Web App を wrap” 같은 영어 혼합 부분은 제법 잘 읽고 있어서, 0.9B치고는 꽤 분발하고 있습니다.
위 결과 테이블과 모델 목록은 갱신해 두었습니다.
Mistral의 전용 OCR API (mistral-ocr-latest) 를 추가했습니다. VLM의 채팅 API가 아니라 OCR 전용 엔드포인트를 사용했습니다.
결과는 NLS 0.589로 19위입니다. Claude 4.5 Sonnet (0.640)보다는 아래, Nanonets-OCR-s (0.557)보다는 위라는 위치입니다. 전용 OCR API로서는 Google Cloud Vision (0.820)이나 Azure AI Vision (0.830)에 크게 뒤집니다.
출력을 보면 일본어 손글씨 부분에서 중국어 번체자가 섞이는 경향이 있습니다. “仕様書の腐敗について”가 “代理人 → 國際計算機”로, “リアルタイム対話”가 “1910914 科法”으로 나오는 등 DeepSeek-OCR(간체자 누출)이나 GLM-OCR(간체자 누출)과 비슷한 패턴이지만, Mistral은 번체자가 나온다는 점이 특징적입니다. 반면 영어 부분은 비교적 잘 읽고 있어서 Coding Agent, SDK, Harmony 같은 영단어는 거의 정확히 집어냅니다.
처리 속도는 이미지 1장당 평균 7.3s로, API 계열 모델 가운데서는 Google Cloud Vision (2.2s), Azure (4.2s) 다음으로 빠릅니다. 다만 503 에러가 자주 발생하는 불안정함이 있어서, 재시도 없이 실행하면 6장 중 2〜4장이 실패하는 경우가 있었습니다.
위 결과 테이블과 모델 목록은 갱신해 두었습니다.
Alibaba Cloud의 DashScope API로 제공되는 Qwen VL OCR를 추가했습니다. VLM 채팅 API가 아니라 OCR 전용 모델이며, DashScope의 OpenAI 호환 엔드포인트를 통해 호출했습니다.
결과는 NLS 0.706으로 16위입니다. GPT-5.4 (0.714)와 거의 같은 수준이며, HunyuanOCR (0.698)을 근소하게 앞섰습니다.
출력을 보면 샘플 1에서는 “仕様書の腐敗について”가 “仕様書の商談について”가 되고, “うまくいかん”이 “31Cへ”가 되는 등 일본어 손글씨 흘림체에서 고전하는 경향이 있습니다. 반면 샘플 2에서는 “Agent skill を Web App に wrap する”라는 거의 올바른 구조를 잡아내고 있어, 영어 혼합 부분 읽기는 제법 안정적입니다.
처리 속도는 이미지 1장당 평균 17.7s로, API 모델 중에서는 Claude 4.5 Sonnet (16.4s)과 비슷한 수준입니다.
위 결과 테이블과 모델 목록은 갱신해 두었습니다.
SB Intuitions의 Sarashina2.2-OCR를 추가했습니다. SigLIP2 + Sarashina2.2-3B-Instruct 기반의 일본어 특화 VLM OCR 모델로, 3B 파라미터입니다.
결과는 NLS 0.718로 14위입니다. olmOCR-2 (0.723) 바로 아래, GPT-5.4 (0.714)와 거의 같은 수준입니다.
이 모델은 Markdown 구조가 있는 출력을 전제로 설계되었습니다. 제목(#), 굵게(**), 리스트(-)를 사용해 문서 구조를 재현해 주므로, 구조화된 문서로 손글씨 메모를 가져오고 싶은 용도에는 적합합니다. 이번 평가 지표는 플레인 텍스트 기반 비교라서, 이 Markdown 출력은 솔직히 불리하게 작용하고 있습니다. 구조화 출력을 살리는 평가를 한다면 점수가 더 올라갈 수도 있습니다.
참고로 모델 카드 권장값인 repetition_penalty=1.2로는 일부 이미지에서 숫자 카운트다운(120→0)을 끝없이 생성하는 루프가 발생했습니다. repetition_penalty=1.3으로 올리자 루프가 사라지고 모든 이미지에서 안정적인 출력이 나와, BoC-F1이 0.623→0.727로 크게 개선되었습니다. VLM 기반 OCR 모델은 생성 파라미터 튜닝에 따라 점수가 꽤 달라지므로, 이런 조정이 중요합니다.
위 결과 테이블과 모델 목록은 갱신해 두었습니다.
NVIDIA의 Nemotron OCR v2를 추가했습니다. 이번 비교에서 유일하게 VLM이 아닌 모델입니다. RegNetX 검출기 + Transformer 인식기 + 관계 모델이라는 전통적인 3단 파이프라인이며, 총 84M 파라미터로 가장 작습니다. 텍스트 프롬프트 없이 이미지만 넣으면 동작합니다.
v2_english와 v2_multilingual 두 가지 버전이 있고, v2_multilingual은 영어·중국어·일본어·한국어·러시아어를 지원합니다. model card에 일본어 지원이 명시되어 있어서 이번에는 v2_multilingual을 사용했습니다. 14,244자 문자 집합을 가지고 있으며, 행 단위 인식을 수행합니다.
결과는 NLS 0.413으로 22위입니다. DeepSeek-OCR (0.446) 아래, PaddleOCR (0.353) 위라는 위치입니다. 일본어를 지원한다고는 하지만 활자·인쇄 문서용 설계이므로, 손글씨는 역시 범위 밖인 듯합니다.
출력을 보면 날짜 패턴 (3/11, 3/13, 3/15)이나 영단어 (Harmony, ASR, VSR)는 어느 정도 집어내고 있어 검출기 자체는 제대로 동작하고 있습니다. 반면 일본어 손글씨는 중국어 간체자(“投资家”, “绝” 등)로 출력되는 경우가 많아, DeepSeek-OCR의 중국어 누출과 비슷한 경향을 보였습니다. 다국어 문자 집합에 중국어가 포함되어 있으니, 판별이 모호한 손글씨 문자를 중국어 쪽으로 기울여 버리는 것일지도 모릅니다.
같은 전통형 파이프라인인 PaddleOCR (NLS 0.353)과 비교하면 Nemotron 쪽이 더 낫고, BoC-F1도 0.562 vs 0.394로 문자 인식 정확도에 차이가 있습니다. 84M 파라미터로 이 결과이니, 활자 문서 평가도 해 보면 재미있을 것 같습니다.
위 결과 테이블과 모델 목록은 갱신해 두었습니다.
Google의 Gemini 3.5 Flash를 추가했습니다. Flash 계열의 최신 세대입니다.
결과는 NLS 0.927로 당당한 1위입니다. 그동안 1위였던 Gemini 3.1 Pro Preview (0.924)를 근소하게 제쳤고, 처리 시간도 14.8s로 Pro의 67.9s보다 1/4 이하입니다. Flash 계열이 Pro를 넘는 것은 예상하지 못했기에 꽤 놀라웠습니다. BoC-F1은 0.928로 2위인 Pro의 0.929와 거의 같고, CER은 0.192로 전 모델 중 최고 값입니다.
샘플별로 봐도 안정적이어서, 6장 중 NLS가 0.92 아래로 내려간 것은 2장뿐입니다. 샘플 1의 “VSR → うまくいかん”은 “VSR -> うごかん”으로 아깝게 틀렸고, 샘플 2에서는 “permission mode auto対応”를 “permission mode auto だが”로 읽는 등 뉘앙스를 헷갈리는 경우는 남아 있지만, Pro가 “外でいかん”이라고 읽은 부분을 “うごかん”으로 읽어낸 점을 보면 흘림체 추정의 자연스러움에서는 오히려 Pro보다 나은 장면도 있습니다.
정확도·속도·(아마도)비용의 삼박자에서 현재로서는 이것이 손글씨 메모 전사의 거의 최적해입니다. 실서비스에 쓴다면 우선 이것부터 시험해 보는 것을 추천합니다.
위 결과 테이블과 모델 목록, 결론 섹션도 갱신해 두었습니다.
OpenAI의 GPT-5.5를 추가했습니다. reasoning effort: high로 평가했습니다.
결과는 NLS 0.755로 9위입니다. 이전 세대 GPT-5.4 (0.714)보다 0.04포인트 개선되었고, YomiToku (0.770) 바로 아래, GLM-OCR (0.738) 위라는 위치입니다. BoC-F1은 0.830으로 전체 모델 중에서도 높은 편이라 문자 단위 인식 능력은 상당히 올라왔습니다. 한편 CER은 0.301인데, 영역 매칭(NLS)과의 간극을 보면 문자는 읽고 있지만 행 구조 대응이 무너지는 경우가 많다고 추정할 수 있습니다.
처리 시간은 이미지 1장당 평균 98.1s로, GPT-5.4 (123.4s)보다는 빨라졌지만 Gemini 계열 Flash 모델군이 10〜20초대에 동작하는 것과 비교하면 여전히 느립니다. reasoning effort: high로 시간을 들여도 Gemini 3.5 Flash (0.927)와의 차이는 무려 0.17포인트나 있어, 일본어 손글씨 OCR 영역에서는 GPT 계열이 Gemini 계열을 따라잡기 쉽지 않아 보입니다.
샘플 1에서는 “VSR -> うまくいかん”이 “USR -> HLDを書く”가 되고, “仕様書の腐敗について”가 “(仕様書の確認->?)”가 되는 등 의미 자체를 잘못 파악하는 경향이 남아 있습니다. 이전 세대와 마찬가지로 일본어 흘림체를 영어 문맥에 끌려 읽는 습관이 있는 듯합니다.
위 결과 테이블과 모델 목록은 갱신해 두었습니다.
Anthropic의 Claude 4.7 Opus를 추가했습니다. adaptive thinking으로 평가했습니다.
결과는 NLS 0.858로 6위입니다. Claude 4.6 Opus (0.897)와 Azure AI Vision (0.830) 사이에 위치하며, 이전 세대보다 0.04포인트 정확도가 내려갔습니다. 한편 처리 시간은 4.6 Opus의 74.9s에서 4.7 Opus는 9.5s로 약 8배 빨라졌습니다. CER도 4.6 Opus 0.225 → 4.7 Opus 0.276으로 조금 악화했지만, 그래도 상위권 수준은 유지하고 있습니다.
그동안 Claude Opus는 GPT 계열보다 확실히 강한 위치에 있었는데, 4.7 세대에서는 “정확도는 조금 낮추되 대폭 빠르게 한다”는 방향으로 선회한 듯 보입니다. adaptive thinking이 “굳이 오래 생각하지 않아도 답이 나온다”고 판단해 추론을 일찍 끊는 것인지, 결과적으로 정확도와 속도의 트레이드오프가 크게 이동했습니다. 실용적인 처리 속도를 생각하면 4.7 Opus 쪽이 현실적인 유스케이스에는 더 맞추기 쉬워 보입니다.
샘플별로 보면, 샘플 3(Manus Clone 계열 정리 메모)에서는 NLS 0.976으로 4.6 Opus와 동급 수준을 유지하는 반면, 흘림체가 심한 샘플 1(NLS 0.751)에서는 “VSR つよくなる”, “自作キーの腐敗について”처럼 추측 위주의 출력을 내고 있습니다.
위 결과 테이블과 모델 목록, 결론 섹션도 갱신해 두었습니다.
실제 손글씨 메모 이미지와 각 모델의 OCR 출력을 나란히 살펴보겠습니다. 모델별 강점과 약점이 잘 드러납니다.

정답 텍스트:
CodingAgent時代のApplication考
麻雀AIをCodingAgentで
VSR → うまくいかん
仕様書の腐敗について
Gemini 3.5 Flash (NLS=0.876)
- CodingAgent 時代の Application/s
- 麻雀 AI と Coding Agent で
- VSR -> うごかん
- 仕様書の腐敗について.
Gemini 3.1 Pro Preview (NLS=0.890)
・ Coding Agent 時代の Application/S
・ 麻雀 AI を Coding Agent で
・ VSR -> 外でいかん
- 仕様書の腐敗について.
Gemini 3 Flash Preview (NLS=0.840)
Coding Agent 時代の Application/s
麻雀 AI を Coding Agent で
VSR -> 外でかく
仕様書の腐敗について.
Gemini 3.1 Flash Lite Preview (NLS=0.865)
・CodingAgent時代のApplication/s
・麻雀AIをCodingAgentで
・VSR→外注とか
・仕様書の腐敗について
Claude 4.7 Opus (NLS=0.751)
・CodingAgent時代のApplicationら
・麻雀AIとCodingAgentで
・VSR つよくなる
・自作キーの腐敗について
Claude 4.6 Opus (NLS=0.890)
· Coding Agent 時代の Applications
· 麻雀 AI を Coding Agent で
, USR → みていかん
· 仕様書の腐敗について。
Claude 4.5 Sonnet (NLS=0.656)
CodingAgent の Applications
麻雀 A I と CodingAgent で
VSR -> 外に出る
仕事, 商談について
GPT-5.5 (NLS=0.596)
- CodingAgent系のApplications
- 麻雀AIをCodingAgentで
- USR -> HLDを書く
- (仕様書の確認->?)
GPT-5.4 (NLS=0.589)
CodingAgent with Applications
麻雀 AIと CodingAgentで
VSR -> みじかく
仕事を簡略化って?
Google Cloud Vision (NLS=0.782)
Coding Agent mit Application's
麻雀
AI & Coding Agent
VSRろぐかん
仕様の腐敗について
で
Azure AI Vision (NLS=0.807)
Coding Agent af Applications
麻雀AL CodingAgentで
USR →引くいかん
仕様書の肩題について
Mistral OCR (NLS=0.488)
Coding Agent with Applications
麻雀 AI & Coding Agent
VSR → 計算機
代理人 → 國際計算機
Qwen VL OCR (NLS=0.747)
、CodingAgent は代わり Application's
、麻雀 AI と CodingAgent で
、VSR → 31C へ
→ 仕様書の商談について
HunyuanOCR (NLS=0.636)
CodingAgent 時代の Applications
麻雀 AI と CodingAgent の
VSR → 3 人が 1 人
任務者の腐敗の 2 人
Chandra (NLS=0.722)
・ Coding Agent の Application/S
・ 麻雀 AI と Coding Agent で
・ VSR -> 31C がん
・ 仕様書の修正についと
olmOCR-2 (NLS=0.681)
・ CodingAgent 以外の Application/s
・ 麻雀 AI と CodingAgent で
・ VSR → 31C が人
・ 任課者の発表について
YomiToku (NLS=0.608)
S/mairmoi day 6 yha zuag (aipe).
、麻雀AZをCodingAgutで
VSR →31C、かん
、仕様もの周防について
GLM-OCR (NLS=0.690)
、Coding Agent 時代のApplication
、麻雀 AIをCoding Agentで
、VSR、トリックが人
、任作きの商談について。
Sarashina2.2-OCR (NLS=0.663)
CodingAgent refのApplications
- 麻雀AIをCodingAgentで
- USRスクリプトから
- 信頼性の評価について.
DeepSeek-OCR (NLS=0.468)
CodingAgent 应用 Application's
麻省 A2z CodingAgent
VSR -> 31C -> 7C
在线考,有改 -> 7C
GOT-OCR 2.0 (NLS=0.220)
Cadi g/ Agent Bif f Application y
Nemotron OCR v2 (NLS=0.307)
•CodigAAgent iitt Appplicatiinns
。
-VSR.-3-346、
-
PaddleOCR (NLS=0.000)
X
享
E
はトイ
NDLOCR v2 (NLS=0.010)
Ta
〓
〓〓
〓
“VSR → うまくいかん” 부분이 흥미로운데, 거의 모든 모델이 잘못 읽고 있습니다. Gemini 3.5 Flash가 “うごかん”으로 가장 근접했지만, Gemini Pro조차 “外でいかん”이 되고, GPT-5.4는 “みじかく”, HunyuanOCR는 “3 人が 1 人”, DeepSeek-OCR은 중국어까지 섞여 있습니다. 손글씨 흘림이 심한 부분은 역시 어렵습니다.
반면 “仕様書の腐敗について”는 상위 모델들이 거의 정확하게 읽고 있는데, GPT-5.4나 Claude 4.5 Sonnet이 “仕事を簡略化って?”, “仕事, 商談について”처럼 전혀 다른 내용으로 읽은 것은 의외입니다.

정답 텍스트:
permission mode auto対応
作り直すのもありかも
SDKを
比較したい
HarmonyとSDKを渡して
AgentSkillがWebAppをwrapするべきか
webAppがAgentをwrapするべきか
(及びSkill)
Gemini 3.5 Flash (NLS=0.867)
permission mode auto だが
作りながらのもありかも
↳ SDKを
比較したい...
Harmony と SDKを渡して、
Agent skill が Web App を wrap するのか
Web App が Agent を wrap するのか
(Agent skill)
Gemini 3.1 Pro Preview (NLS=0.833)
・permission mode auto 化
・作りかたのわかりやすさ
↳ SDKで
比較したい。
Harmony と SDK を通して。
Agent skill が Web App を wrap するべきか
Web App が Agent を wrap するべき
(Agent skill)
Gemini 3 Flash Preview (NLS=0.823)
permission mode auto 以外
作りながら切りだす
↳ SDKを
比較したい…
Harmony と SDK を並べて、
Agent skill が Web App を wrap するべきか
web App が Agent を wrap するべきか
(Agent skill)
Gemini 3.1 Flash Lite Preview (NLS=0.811)
permission mode auto みたいな
作り方のちがいとか
↓ SDK
比較したい
Harmony と SDK を抜いて
Agent skill が Web App を wrap するのか
Web App が Agent を wrap するのか
(Agent Skill)
Claude 4.7 Opus (NLS=0.762)
・permission mode auto だと
・作り方のしおりなど
└ SDKと
et 検したい
Harmony と SDK を渡して
Agent skill が Web App を wrap するか
Web App が Agent を wrap するか
(ためしたい)
Claude 4.6 Opus (NLS=0.833)
・permission mode auto対応
・割り方のとりまとめ。
→ SDKを。
比較したい。
Harmony と SDK を抜いて。
Agent skill が Web App を wrap するのか
Web App が Agent を wrap するのなら
(及びskill)
Claude 4.5 Sonnet (NLS=0.633)
paralyzion mode auto 4k
/1140/10/24/3'4
⊂ SDK
etkizh...
Harmony と SDK を抜いて
Agent stall & Web App を wrap したい
Web App が Agent を wrap (7/22名
(AgShell)
GPT-5.5 (NLS=0.667)
permission mode auto 付与
/etc/thio/thy's y
↳ SDKを
etc使えて...
Harmony と SDKを使って.
Agent skill が Web App を wrap すること
Web App が Agent を wrap するもの
(AI Skills)
GPT-5.4 (NLS=0.624)
permission mode auto化
権限まわりとか
↳ SDKを
etc etc...
Harmony と SDK を使って。
Agent skill が Web App を wrap するだけ
Web App が Agent を wrap するなら
(API Shield)
Google Cloud Vision (NLS=0.699)
pernission mode
auto kitin
作物ものもありかも
SDKE
ettech...
HarmonyとSDKを渡して、
Agent stall & Web App & wrap 18-246'
Web App 6° Agent & wrap 17-925-
(Ari Skild)
Azure AI Vision (NLS=0.669)
permission mode auto .
倒なものもありがと
→ SDKE
比較したい、
HarmonyとCDKを渡して、
Ageat full of Web App 2 wrap is it!
Web App t" Agail & wrap 11 22.6
(Anislil)
Mistral OCR (NLS=0.519)
poralysion mode auto kth
1994/1995/1996
→ SDK
elkcon.
Harmony × SDK × 3kcc
Aged Skill 5 Web App 2 wrap 11 725
Web App 5 Agenc × wrap 11 725
(42 Skill)
Qwen VL OCR (NLS=0.665)
permission mode auto kit
倒物の skill skill サイズ
SDK
比較して...
Harmony x SDK を使って
Agent skill を Web App に wrap する
Web App で Agent skill を wrap する
(Agentskill)
HunyuanOCR (NLS=0.695)
・permission mode auto kill
・倒すのがやすい
・<SDK>
・比較したい
・HarmonyとCDKを使う
・Agent skill とWeb App をwrap 行う
・Web App とAgent をwrap 行う
・(Agent skill)
GLM-OCR (NLS=0.666)
permission mode auto talk
徘行の比較式。
→ SDKを。
比较。
HarmonyとSDKを接って。
Agent skill 6 Web Appを wrap 13 でか
Web App 6 Agentを wrap 11 でか
(Agent skill)
Chandra (NLS=0.693)
permission mode auto kill
例のインテリゲンス
↳ SDK
比較した...
Harmony & SDK と比較して...
Agent Skill は Web App と wrap する
Web App は Agent と wrap する
(AniSkill)
olmOCR-2 (NLS=0.767)
・permission mode auto
・例物のおります。
→ SDK
・比較した。
Harmony と SDK を渡して。
Agent Skill が Web App と wrap に渡す
Web App が Agent と wrap に渡す
(外部Skill)
YomiToku (NLS=0.626)
perallsilon mode auto khi.
1.4/14761.4/13/ .
3/45 m
比較したい.
Marmony と SDKを推して、
Ageal skall 6' Wob App ? wrap li t'b'
Web App bi Ageil e wrap Ti 325
(Azislall)
Sarashina2.2-OCR (NLS=0.686)
permission mode auto kill
- 1945のctrl + c, | SDKe
接続したい...
HarmonyとSDKを渡して...
Agent skill b→Web App z wrap 1326b
Web app b→Agent e wrap Tl78a (zuiSkill)
DeepSeek-OCR (NLS=0.503)
permission mode auto 优先
自动权限模式
SD卡
etc...
Harmony 和 SDK 接口
Agent shell 6 Web App 2 wrap 11.2.6
Web App 6 Agent 2 wrap 11.2.6
(A2shell)
GOT-OCR 2.0 (NLS=0.140)
per a is ton model eau to Hi
Nemotron OCR v2 (NLS=0.299)
LokS
etteci..
Harmony - spK iu .
Appar delllo wb Appp waa p ttttt
web App on Agene wrap 11 222
by
(AriShidd)
PaddleOCR (NLS=0.083)
S
i
영어와 일본어가 섞여 있고, AgentSkillがWebAppをwrapするべきか 같은 코드 용어가 섞인 손글씨 텍스트입니다. Gemini Pro와 Claude Opus는 “Agent skill が Web App を wrap するべきか”를 거의 정확하게 읽고 있습니다.
하위 모델에서는 wrap이 숫자 나열로 바뀌거나(Google Cloud Vision: wrap 18-246'), 완전히 다른 문장이 되기도 합니다(Azure: Ageat full of Web App 2 wrap is it!). DeepSeek-OCR이 일본어 부분을 중국어로 출력하는 것 역시 특징적입니다(自动权限模式, SD卡).
정답 데이터의 각 영역에 대해, 예측 텍스트 안에서 가장 잘 맞는 줄을 찾아 Normalized Levenshtein Similarity를 계산합니다.
正解領域: ["東京都", "渋谷区", "恵比寿1-2-3"]
予測テキスト: "渋谷区\n東京都\n恵比寿1-2-3"
→ 読み順が違っても各領域が正しく認識されていれば高スコア
VLM이 정답 영역을 합쳐서 출력하는 경우(“東京都渋谷区”처럼 한 줄로 합침)나, 반대로 정답 영역을 분할하는 경우(“恵比寿”, “1-2-3”으로 나눔)에도 대응하기 위해, 인접 줄 병합 후보와 부분 문자열 매칭도 포함했습니다.
이름의 유래는 본래 Hungarian Algorithm에 의한 최적 할당이지만, 구현상으로는 각 정답 영역에 대해 전체 예측 줄 가운데 최고 점수를 취하는 Greedy 매칭입니다. 정답 영역 간 중복 매칭을 허용함으로써, VLM이 여러 영역을 합쳐 출력하는 경우에 대응하고 있습니다.
CC-OCR의 접근을 참고한 지표입니다. 텍스트를 문자 다중집합(multiset)으로 취급하고, 어순과 줄바꿈을 완전히 무시한 채 Precision/Recall/F1을 계산합니다.
gt_chars = Counter("東京都渋谷区") # {'東':1, '京':1, '都':1, '渋':1, '谷':1, '区':1}
pred_chars = Counter("東京都渋谷区恵比寿")
matched = sum((gt_chars & pred_chars).values()) # 6
precision = 6/9, recall = 6/6
VLM이 Markdown 표기나 설명문을 덧붙이는 경우 Precision이 떨어지므로, 노이즈 검출에도 사용할 수 있습니다.
전체 텍스트를 평탄하게 연결해 Levenshtein 거리를 계산하는 고전적인 지표입니다. CER은 정답 텍스트 길이로 가중 집계합니다.
세 지표 모두에 공통으로 같은 정규화 파이프라인을 적용합니다.
## 제목, **굵게**, 리스트 기호 등을 제거・나 ☆ 같은 장식 문자, (丸で囲まれている) 같은 메타 서술, 이모지를 제거이 정규화가 없으면 VLM 출력이 몹시 불리해집니다. Markdown 표기를 붙였다는 이유만으로 “텍스트는 제대로 읽었는데” 표기법 때문에 점수가 내려가는 것은 불공평하니까요. 다만 지나친 정규화는 모델 간 차이를 지워 버리므로, “명백히 OCR 대상이 아닌 기호”만 제거하도록 규칙을 신중하게 설계했습니다.
어노테이션 도구에 이미지를 업로드하면, OCR에 넘기기 전에 다음과 같은 전처리 파이프라인이 실행됩니다. 솔직히 말해 로직 검증은 충분하지 않아서 잘 듣지 않는 경우도 있을 것 같습니다. 없는 것보다는 나은 정도의 대충 만든 구현입니다.
minAreaRect로 네 점을 잡아 원근 변환으로 잘라냅니다. 용지가 이미지 면적의 15% 미만이면 검출 실패로 간주하고 원본 이미지를 그대로 사용합니다medianBlur로 배경을 추정하고 나눗셈으로 조명 불균일을 제거한 뒤, CLAHE로 대비를 높입니다특히 1번 용지 검출은 배경과 종이의 대비가 낮거나 종이가 구겨진 경우 실패할 수 있습니다. 실패하더라도 원본 이미지로 폴백하므로 망가지지는 않지만, 여백이 많은 상태로 OCR에 전달되게 됩니다.
OSS 모델 평가에는 Modal을 사용했습니다. 서버리스 GPU 플랫폼으로, T4, L4, A100 같은 GPU를 Python 데코레이터 하나로 쓸 수 있습니다.
각 모델의 Modal 스크립트는 통일된 인터페이스를 따릅니다.
@app.function(gpu="L4", image=image, timeout=1800)
def run_ocr(images_b64: list[str]) -> list[str]:
# base64 이미지를 받아 OCR 결과 텍스트 리스트를 반환한다
...
@app.local_entrypoint()
def main(input: str, output: str):
from _common import load_input, save_output
data = load_input(input)
results = run_ocr.remote(data["images"])
save_output(output, results)
입력은 base64 인코딩한 이미지의 JSON, 출력은 OCR 텍스트의 JSON입니다. 이 규약만 지키면 새 모델을 쉽게 추가할 수 있습니다. 자주 막히는 지점(PaddlePaddle의 GPU 버전 지정, libgl1 의존성, CUDA 버전 등)은 AGENTS.md에 정리해 두었습니다.
벤치마크
모델
관련 기사
인프라