Logo

新人日誌

首頁關於我部落格

新人日誌

Logo

網站會不定期發佈技術筆記、職場心得相關的內容,歡迎關注本站!

網站
首頁關於我部落格
部落格
分類系列文

© 新人日誌. All rights reserved. 2020-present.

OCR(光學字元辨識)到底在做什麼?

最後更新:2026年7月20日基礎概念

你有沒有用手機拍過一張發票,結果 App 自動幫你把金額填進記帳表格?

或是掃描一份合約,馬上就能複製貼上裡面的文字?

這背後的技術就是 OCR。

但你有想過,電腦看到的明明只是一堆像素點,它是怎麼「讀懂」文字的?

為什麼有些掃描檔辨識得又快又準,有些卻整段亂碼?

這篇文章就從零開始,帶你搞懂 OCR 是怎麼運作的。

什麼是 OCR

OCR 全名是 Optical Character Recognition(光學字元辨識),簡單說就是「把圖片裡的文字,轉換成電腦看得懂、可以編輯的文字資料」的技術。

白話一點解釋:一張照片對電腦來說,本質上只是一堆數字(每個像素的顏色數值)。

OCR 要做的事,就是從這堆數字裡面,找出哪些區塊「長得像文字」,然後判斷這些文字到底是「A」還是「8」、是「O」還是「0」,最後輸出成一串你可以複製、搜尋、編輯的文字字串。

你可以把這個過程想成兩個階段:

  • 輸入:一張圖片(掃描檔、照片、螢幕截圖都算)
  • 輸出:一段純文字(string),電腦知道這是「文字」而不是「圖案」

影像前處理:讓文字更容易被找到

在電腦真正開始「認字」之前,通常會先對圖片做一連串的前處理(preprocessing)。

這一步非常關鍵,因為原始圖片常常有雜訊、傾斜、光線不均等問題,直接拿去辨識準確率會很差。

白話解釋:這就像你在幫一份潦草的手寫筆記拍照之前,會先把紙攤平、調整角度、開燈拍清楚一樣。

電腦也需要類似的「整理」步驟,才能看得更清楚。

常見的前處理步驟包括:

  • 灰階化(grayscale):把彩色圖片轉成黑白,減少不必要的顏色資訊干擾
  • 二值化(binarization):把圖片變成只有黑跟白兩種顏色,讓文字和背景的界線更明顯
  • 去雜訊(denoising):去掉圖片上的雜點,避免被誤判成文字的一部分
  • 傾斜校正(deskew):如果拍照角度歪了,把文字「轉正」

這四個步驟通常是照順序做下去的,我們一個一個來看。

灰階化:先把顏色簡化掉

灰階化是第一步,也是最基本的一步。

彩色圖片每個像素其實存了三個數值(紅、綠、藍),但對辨識文字來說,顏色本身不重要,重要的是「這裡亮還是暗」。

把三個數值合併成一個亮度數值,資料量少了三分之二,後面的運算也會快很多。

二值化:消除灰色地帶

二值化是在灰階化之後做的,目的是把「灰色地帶」全部消除掉。

灰階圖片雖然只剩亮度,但亮度還是有從 0 到 255 這麼多種可能值,文字邊緣常常會有模糊的灰色過渡。

二值化會設定一個門檻值(threshold),亮度超過門檻的像素直接變全白,沒超過的直接變全黑,這樣文字和背景就會是非黑即白,邊界非常清楚。

去雜訊:清掉不該存在的雜點

去雜訊處理的是圖片上一些不該存在的小黑點或小白點,這些雜點通常來自掃描機的灰塵、照片的雜訊、或是紙張本身的紋理。

如果不處理,這些雜點很容易被誤判成標點符號或文字的一部分,導致辨識出奇怪的字元。

傾斜校正:把歪掉的文字轉正

傾斜校正處理的則是「角度」問題,如果拍照或掃描的時候紙張沒有擺正,文字整排會是歪的。

大部分辨識演算法都是假設文字是水平排列的,歪斜會讓辨識率大幅下降,所以需要先偵測傾斜角度,再把整張圖片轉正。

動手做:用 OpenCV 實作前處理

在寫程式碼之前,先說明一下 OpenCV 是什麼。

OpenCV 全名是 Open Source Computer Vision Library,是一個開源的電腦視覺函式庫。

裡面包了大量處理圖片和影片的現成功能,像是轉灰階、二值化、偵測邊緣、辨識形狀等等,都不用自己從頭寫演算法。

白話解釋:如果說前處理是「整理照片」的一連串動作,OpenCV 就是一個裝滿整理工具的工具箱。

你只要呼叫對應的函式(例如 cvtColor 用來轉灰階、threshold 用來二值化),就能直接套用這些現成的處理邏輯,不用自己重新發明演算法。

我們用 Python 搭配 OpenCV 來看一個簡單的二值化範例:

import cv2

# 讀取圖片並轉成灰階
image = cv2.imread("invoice.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 二值化:把圖片變成只有黑白兩色
# threshold 值以上的像素變白色,以下變黑色
_, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)

cv2.imwrite("processed.jpg", binary)

這段程式碼做了兩件事:先把彩色圖片轉成灰階(cvtColor),再用 threshold 把灰階圖片變成純黑白。

這樣一來,文字的邊緣會變得非常清晰,方便後續的辨識步驟。

文字偵測:圖片裡哪裡有字?

前處理完之後,電腦還不知道文字「在哪裡」。

這時候需要文字偵測(text detection),也就是在整張圖片裡,框出哪些區域是文字、哪些是背景或圖案。

白話解釋:這就像你拿到一頁報紙,你的眼睛會很自然地掃過去,知道哪裡是標題、哪裡是內文、哪裡是廣告圖片。

電腦沒有這種直覺,所以需要演算法幫它「畫出」這些文字區塊的邊界框(bounding box)。

什麼是邊界框(bounding box)

邊界框其實就是一個長方形的座標範圍,通常用「左上角座標」加上「寬度、高度」這幾個數字來表示。

舉例來說,如果一行文字在圖片裡從左上角(50, 100)開始,寬 200 像素、高 30 像素,這個邊界框就會被記錄成 (50, 100, 200, 30) 這樣的一組數字。

文字偵測的輸出,通常就是一張圖片裡所有文字區塊的邊界框清單,而不是文字內容本身。

也就是說,這個階段電腦只知道「這裡有一團看起來像文字的東西」,還不知道那團東西寫的是什麼字,真正判斷內容是下一階段(辨識)的工作。

傳統方法:連通元件分析

傳統方法會用像是「連通元件分析(connected components)」這類技術,找出圖片中顏色連續、形狀像文字筆畫的區塊。

具體來說,這個方法會先把圖片二值化(前一節提到的黑白處理),然後把彼此相鄰、顏色相同的黑色像素「連」成一塊,視為同一個元件。

如果這些連通的區塊,形狀符合文字筆畫該有的比例(例如寬高比不會太誇張、面積不會太大或太小),就會被判定為文字候選區域。

這種方法的優點是運算速度快、不需要訓練模型,缺點是遇到手寫字、藝術字、或是文字彼此黏在一起的情況,準確率會明顯下降。

深度學習方法:EAST、CRAFT 這類模型

現代的做法則多半用深度學習模型(例如 EAST、CRAFT 這類文字偵測模型),直接訓練模型去預測文字的位置。

這類模型的做法跟傳統方法完全不同:不是靠人工設計的規則去判斷「這塊像不像文字」,而是先準備大量標註好文字位置的圖片,讓模型自己從資料中學習「文字通常長什麼樣子」。

訓練好之後,模型可以直接輸出整張圖片中每一塊文字的邊界框,即使文字是彎曲的、傾斜的、或是跟複雜背景混在一起,也能有不錯的偵測效果。

這也是為什麼路牌、招牌這類複雜場景的文字辨識,現在多半會採用深度學習方法的原因。

字元辨識:這個形狀是哪個字?

找到文字區塊之後,真正的重頭戲來了:辨識(recognition)。

這一步要判斷「這個框框裡的形狀,對應到哪一個字元」。

白話解釋:想像你在玩一個「猜字遊戲」,你看到一個模糊的形狀,要從 26 個英文字母(或幾千個中文字)裡面猜出最像的那一個。

電腦做的事情本質上一樣,只是它是用數學方式去「比對」。

傳統方法:特徵比對

傳統 OCR(例如早期的 Tesseract)會用「特徵比對」的方式:先把每個字元的筆畫特徵(有幾條線、線的角度、封閉區域數量等)抽取出來,再跟資料庫裡已知字元的特徵做比對,找出最相似的那個。

現代方法:CNN 加 RNN/Transformer

現代 OCR 則多半用深度學習,最常見的組合是 CNN(卷積神經網路)加上 RNN 或 Transformer。

白話解釋:這兩個部分做的事情不太一樣,可以想成是分工合作。

CNN 負責「看懂形狀」,你可以把它想成一雙很會看圖的眼睛,它會先掃過圖片中每一個字元的區域,把筆畫、邊角這些視覺特徵抽取出來,變成一組數字,這組數字就代表這個字元長什麼樣子。

RNN/Transformer 負責「串成合理的句子」,你可以把它想成是幫這些數字排隊、互相討論的角色。

因為文字是有順序性的,前一個字通常會影響後一個字該猜成什麼(例如看到「蘋」,下一個字猜「果」的機率就比猜「狗」高很多),RNN/Transformer 就是利用這種前後關係,讓辨識結果更準確、更合理。

簡單來說:CNN 先看懂「每一個字長什麼樣子」,RNN/Transformer 再負責把這些字「串成一句看得懂的話」。

動手做:用 pytesseract 實作辨識

我們直接用現成的 OCR 套件 pytesseract 來看整個流程串起來長什麼樣子:

import pytesseract
from PIL import Image

# 開啟前面處理好的圖片
image = Image.open("processed.jpg")

# 執行 OCR,lang="chi_tra" 代表用繁體中文模型辨識
text = pytesseract.image_to_string(image, lang="chi_tra")

print(text)

這段程式碼呼叫了 Tesseract 引擎(pytesseract 只是 Python 的包裝),把圖片丟進去,指定用繁體中文的辨識模型(chi_tra),然後拿到辨識出來的文字字串。

你會發現,前面提到的偵測、辨識這些步驟,其實都被包在 image_to_string 這個函式裡面,對使用者來說是一次呼叫就完成的。

常見誤區:直接丟原圖辨識

❌ 有問題的寫法:

text = pytesseract.image_to_string(Image.open("invoice.jpg"))

直接把手機拍的原始照片丟進去辨識,沒有做任何前處理。

如果照片有陰影、角度歪斜、解析度不夠,辨識結果常常會出現大量錯字或亂碼。

✅ 改善後的寫法:

image = cv2.imread("invoice.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)
cv2.imwrite("processed.jpg", binary)

text = pytesseract.image_to_string(Image.open("processed.jpg"), lang="chi_tra")

先做灰階跟二值化前處理,把文字邊緣變清楚,再送進辨識引擎。

這樣可以大幅降低雜訊對辨識結果的干擾,提升準確率。

實務應用:什麼時候該用 OCR?

了解原理之後,我們來看實際場景中 OCR 會怎麼被用到,以及使用時要注意什麼取捨。

常見使用場景

  • 發票、收據自動記帳:像是拍照記帳 App,拍完照自動抓出金額、日期、店家名稱,不用自己手動輸入
  • 證件辨識:身分證、護照、駕照上的號碼、姓名欄位自動填表,常見於銀行開戶、機場報到這類需要快速核對身分的場景
  • 掃描文件數位化:把紙本合約、公文、書籍掃描後,變成可以搜尋、複製、編輯的電子檔,方便長期保存跟查找
  • 車牌辨識:路口監視器、停車場管理系統用來自動辨識車牌號碼,計算停車時間或比對違規車輛

這些場景的共通點是:都需要把「紙本或畫面上的資訊」快速轉換成「系統可以直接使用的資料」,省下大量人工輸入的時間。

選擇工具時的取捨

如果你的需求是辨識乾淨、字體工整的印刷體文件(像是掃描的 PDF),用 Tesseract 這類開源引擎通常就很夠用,而且免費、可以離線執行。

不需要把資料傳到外部伺服器,對隱私敏感的文件(例如合約、病歷)也比較安心。

如果你要處理的是手寫字、歪斜嚴重的照片、或是背景複雜的招牌文字,開源引擎的準確率會明顯下降。

這時候可能需要用商用 API(例如 Google Cloud Vision、Azure Computer Vision)或是自己訓練深度學習模型。

選擇商用 API 的代價是需要按用量付費,而且圖片要上傳到雲端處理,如果文件內容敏感,就要額外考慮資料隱私的問題。

自己訓練模型則需要準備大量標註資料跟運算資源(通常要用到 GPU),前期投入的時間成本會比較高,但長期下來如果辨識量很大,可能比持續付費使用商用 API 更划算。

實務上常見的做法,是先用開源工具(如 Tesseract)做原型驗證,確認辨識準確率是否符合需求,如果不夠用,再評估要導入商用 API 還是自己訓練模型。

另外要注意的是,OCR 的準確率也跟語言有很大關係。

中文字因為字型結構複雜、常用字數量龐大(比英文 26 個字母多很多),辨識難度通常會比純英文文件高一些。

實務上常常需要針對特定字型或特定文件類型去微調模型,才能達到可以實際上線使用的準確率。

重點整理

  • OCR(光學字元辨識)是把圖片中的文字,轉換成電腦可編輯文字資料的技術
  • 整個流程大致分成三步驟:前處理 → 文字偵測 → 字元辨識
  • 前處理(灰階化、二值化、去雜訊)的目的是讓文字更清晰,直接影響後續辨識準確率
  • 文字偵測負責「定位」文字在圖片中的位置
  • 字元辨識負責「判斷」框出來的形狀對應哪個文字,傳統方法靠特徵比對,現代方法靠深度學習
  • 印刷體、乾淨背景的文件用開源工具(如 Tesseract)通常足夠;手寫字、複雜背景則需要更強的模型或商用服務
  • 中文因字型結構複雜、常用字量大,辨識難度通常高於純英文

目前還沒有留言,成為第一個留言的人吧!

發表留言

留言將在審核後顯示。

基礎概念

目錄

  • 什麼是 OCR
  • 影像前處理:讓文字更容易被找到
  • 灰階化:先把顏色簡化掉
  • 二值化:消除灰色地帶
  • 去雜訊:清掉不該存在的雜點
  • 傾斜校正:把歪掉的文字轉正
  • 動手做:用 OpenCV 實作前處理
  • 文字偵測:圖片裡哪裡有字?
  • 什麼是邊界框(bounding box)
  • 傳統方法:連通元件分析
  • 深度學習方法:EAST、CRAFT 這類模型
  • 字元辨識:這個形狀是哪個字?
  • 傳統方法:特徵比對
  • 現代方法:CNN 加 RNN/Transformer
  • 動手做:用 pytesseract 實作辨識
  • 常見誤區:直接丟原圖辨識
  • 實務應用:什麼時候該用 OCR?
  • 常見使用場景
  • 選擇工具時的取捨
  • 重點整理