我們量度數獨相片讀取器時學到的事
更新於 2026年11月5日
怎樣才算讀對
只有81格全部正確,一道謎題才算讀對:錯了一個數字,就成了另一道謎題。所以我們計算的是整道謎題,而不是格子。兩者可以說出很不同的故事,本頁正好說明這一點:在印刷相片上,讀取器現在能讀對98.9%的格子,但整道謎題的讀對比例幾乎沒有變動,因為大部分讀錯的格子集中在少數幾張難讀的圖片中。
我們亦計算最危險的錯誤:讀錯了但仍然恰好只有一個答案的謎題。真正的數獨只有一個答案,所以無解或有多個解的讀取結果會即時被發現。只有一個答案的錯誤謎題看起來沒有問題,因此解題器會標出每一個它沒有把握的格子,並請你在解題前把這些格子與你的謎題對照。
只有200張圖片,結果的精確度有限。主要結果我們會附上95%範圍(Wilson區間):200張圖片中的89.5%,表示真實比率最有可能介乎84.5%至93.0%之間。
我們用來測試的圖片
我們從兩個公開數據集入手。Lexski的Sudoku Image Recognition數據集(CC0)有1,400張圖片,大部分是網上分享的截圖和相片:各種風格的應用程式、深色主題、鉛筆標記、在紙上解了一半的謎題。Baptiste Wicht與Jean Hennebert的數據集(CC BY 4.0)收錄了用手機拍攝的報紙數獨,其中一些已用筆手寫完成。
在作出任何改動之前,我們先預留了三個測試集:200張Lexski圖片、40張報紙相片,以及40道手寫完成的報紙謎題。在工作期間,我們既沒有用它們訓練,也沒有查看它們。每個決定都是根據另外200張Lexski圖片(即調校集)作出的,而測試集只在最後讀取一次。
起點
10月31日的第一版,在200張Lexski圖片中完全讀對101張,在40張報紙相片中讀對34張,40道已完成的謎題則一道都沒有讀對。它的問題大多出現在讀取數字之前。它把最大的近似正方形墨跡當作盤面,而在截圖上,這個形狀往往把標題列或數字鍵盤也包括在內,深色主題中纖細的灰色線條則完全被忽略。在調校集上,它在200次中只有118次把網格定位在正確位置。
我們逐步作出的改動
表中每一行代表一項改動,數字是改動後200張調校圖片中完全讀對的數量。最後三行屬於第二輪。
| 改動 | 完全讀對的調校圖片(共200張) |
|---|---|
| 第一版,10月31日 | 99 |
| 靠線條找出網格:每個方向十條等距線 | 129 |
| 並排比較網格;嘗試偏移一格 | 136 |
| 利用淺淡的細線找出網格 | 138 |
| 完整切出格子;從真實格子學習數字 | 161 |
| 小型神經網絡標示盤面位置 | 162 |
| 在書頁彎曲處追蹤線條 | 163 |
| 更佳的數字神經網絡,鉛筆標記自成一類 | 173 |
| 三個數字神經網絡取平均 | 177 |
| 審慎的唯一解規則;已完成的盤面整體讀取 | 177 |
| 第二輪:原尺寸相片縮小前先減半 | 178 |
| 第二輪:矮而淡的墨跡視為鉛筆標記 | 179 |
| 第二輪:側放相片由全部三個神經網絡判斷 | 179 |
大部分進步來自三項改動。現在網格是靠其線條找出的:對盤面位置的每一個推測,都會被調整到每個方向十條等距的線上,再並排比較,而一個標示盤面位置的小型神經網絡也有一票。每一格都完整切出,因此鉛筆標記在其角落中仍然細小,深色方塊上的淺色數字看起來就像紙上的墨跡。此外,數字神經網絡是從Lexski訓練圖片中切出的真實格子學習的,鉛筆標記自成一類。現在由三個分開訓練的小型神經網絡讀取每一格,再取它們答案的平均,因為它們出錯的格子各不相同。
已完成的謎題會得到額外幫助。當盤面上有79個或以上數字時,讀取器會尋找最有可能的完整網格,當中每一橫行、每一直行和每一宮都包含1至9。逐格讀取時,40道手寫測試謎題中只有7道完全讀對;作為已完成的數獨讀取時,40道全部讀對。
第二輪加入了三項較小的改動。原尺寸的手機相片在縮小之前會逐步減半,令細線和鉛筆筆劃被平均計入,而不是被略過。如果某格的墨跡比盤面上有把握的數字既矮得多,也淡得多,就會被視為可能是鉛筆標記。另外,側放相片的旋轉方向改由全部三個神經網絡判斷,而不是只由一個判斷。

沒有幫助的做法
以下做法我們同樣在調校集上量度過,最後沒有採用:
- 較大的數字神經網絡:用59,000個權重取代42,000個,多讀對一張調校圖片,而在瀏覽器中的運行時間是原來的3.8倍。
- 3,000張帶有鉛筆標記和深色主題的生成應用程式截圖:加入與否,分數相同。
- 以彩色而非灰階讀取,令紅筆與黑色墨水一樣深:多讀對兩張調校圖片,但手寫字讀得更差。
- 把訓練用的數字扭曲,令它們更像手寫字:手寫字讀得更差。
- 讓唯一解規則更改更多格子:讀對的謎題增加了,但危險的、只有一個答案的錯誤謎題也增加了。
- 用新數據重新訓練三個神經網絡,或改用四個或六個:差別未超出隨機波動範圍,所以保留了原來的網絡。
- 對於被畫面邊緣截斷的盤面,把圖片邊緣當作盤面邊緣:新讀錯與新讀對的圖片一樣多。
第一批測試集的結果
第一版與現時讀取器在各測試集中完全讀對的謎題數量:
| 測試集 | 10月31日 | 現在 |
|---|---|---|
| 網上分享的截圖和相片(Lexski)圖片數: 200 | 10150.5% | 17989.5% |
| 報紙相片(Wicht與Hennebert)圖片數: 40 | 3485.0% | 40100.0% |
| 手寫完成的報紙謎題(Wicht與Hennebert)圖片數: 40 | 00.0% | 40100.0% |
在Lexski圖片上,讀取器由50.5%升至89.5%(84.5%至93.0%),讀錯但只有一個答案的謎題由7道減至4道。這4道之中有3道,多出的那一個數字正是該格應有的數字,因此謎題仍然會得出正確答案;第4道則是一個印得很清楚的1,而數據集把那一格留空。179道之中有177道在第一輪結束時已讀對。最後兩道是在第二輪、我們研究過失敗個案之後才讀對的,因此這個測試集已不再是未經觸碰的。
40道全部讀對聽起來很完美,但40張圖片只能顯示真實比率高於約91%。還有一項我們本應先做的檢查:40張報紙測試相片中有4張同時出現在該數據集的訓練集中,其中2張連每個像素都相同。撇除它們,結果是36張中讀對36張。
新測試:任何版本都未見過的200張相片
到了這個時候,第一批測試集已經讀過,失敗個案也研究過,因此它們已無法告訴我們讀取器在從未遇過的圖片上表現如何。我們在Hugging Face、Kaggle、GitHub、Zenodo、Figshare和AIcrowd上搜尋更多附有標註的數獨相片。大部分數據集都是生成的盤面、單個數字,或Wicht相片的副本。有三個GitHub收藏有真實的標註相片,全部是印刷謎題:一本公開謎題書的100張相片(NatalijaPetric/SudokuDataset)、80張主要是報紙的相片(mineshpatel1/sudoku-solver,已剔除49張屬於Wicht本人的相片和一張副本),以及布加勒斯特大學一個電腦視覺課程項目的20張印刷紙張(danielsociu/SudokuRecognition)。
這三個數據集都沒有註明授權,所以我們只用它們來量度:從不用來訓練,也不在此展示。圖片清單在任何改動之前已經確定並儲存,是按規則根據檔案雜湊值和標註選出的,而在第二輪最後一項改動完成之前,這些圖片都沒有被打開過。之後,讀取器的每個版本各讀取它們一次。下表計算的是完全讀對的謎題。
| 來源 | 10月31日 | 第一輪 | 現在 |
|---|---|---|---|
| 一本公開謎題書(NatalijaPetric)相片數: 100 | 7979.0% | 7676.0% | 7878.0% |
| 主要是報紙(mineshpatel1)相片數: 80 | 6581.3% | 6885.0% | 6986.3% |
| 印刷紙張(布加勒斯特大學課程)相片數: 20 | 20100.0% | 20100.0% | 20100.0% |
| 全部200張相片數: 200 | 16482.0% | 16482.0% | 16783.5% |
在讀取器從未見過的印刷謎題上,兩輪的所有工作都改變不大。第一版完全讀對其中82.0%,現行版本則為83.5%(77.7%至88.0%):多讀對了14道,但少讀對了11道。真正有改善的是格子:讀對的格子由94.2%升至98.9%,而網格現在在每張相片中都能找到,不再只是200張中的195張。讀錯但只有一個答案的謎題:以前5道,現在6道。
少讀對的謎題有明確原因。為了讀取鉛筆標記和深色主題,現在每一格都完整切出,淺淡的墨跡也會計算在內。在薄報紙上,背頁的內容會透出來,顏色淺淡而且呈鏡像,新讀取器會把這些影子讀成數字;第一版只看每格中最大的墨跡形狀,從來沒有看到它們。在捲曲的書頁上,盤面的外框線或宮線可能落在格子內,被讀成1。
其中兩道讀錯的謎題其實是標註出錯:一張相片顯示3和9的地方,標註寫的是9和8;另一張顯示4的地方,標註寫的是2。按正確標註計算,現行讀取器的讀對率為84.5%。
仍然出錯的地方
在200張新相片中,有33張沒有完全讀對。其中22張是那本公開謎題書的書頁:靠近書脊的地方,書頁的捲曲程度超出讀取器能追蹤的範圍,於是一條線落在格子內被讀成1,或某個角落的格子被切過一條線。7張是背頁透出來的報紙。其餘是一張出現摩爾紋的屏幕相片、一條被讀成1的盤面邊線,以及那兩個標註錯誤。
在200張Lexski圖片中,有21張沒有完全讀對:鉛筆標記被讀成數字,包括擦去後仍留下淡淡數字的鉛筆痕跡(7張);多出一個數字,大多是一個單獨的鉛筆標記被讀成填入的數字(5張);網格位置錯誤或找不到,出現在格子之間沒有線條的應用程式主題或手繪網格上(5張);以及不常見的方塊樣式和顏色(4張)。
為何未達97%,以及下一步
一切都在你的瀏覽器中運行:一個224 KB的模型和約850行JavaScript程式碼,在手提電腦上每張相片的處理時間中位數約為300毫秒,處理器減速4倍時(如同在速度較慢的手機上)則約為1.2秒。在這個限度內,較大的神經網絡沒有幫助。餘下的是一條長尾:捲曲的書頁、背頁透出、鉛筆標記和不常見的應用程式風格。我們找到的每個公開標註數據集現在都已用過或看過,所以下一輪需要我們自己拍攝和標註的相片,並在這些相片上修正和量度淺淡墨跡與捲曲書頁的問題。
取得最佳掃描效果的方法
- 把手機放在謎題正上方並保持平直,讓整個網格都在畫面之內。
- 把書本或報紙壓平:在印刷謎題上,大部分讀錯都是由捲曲的書頁造成的。
- 如果報紙很薄,在該頁後面墊一張白紙,以免背面的內容透出來。
- 在謎題上寫鉛筆標記之前先掃描。
- 解題之前,把解題器標出的格子與你的謎題對照。
數據與來源
- Lexski, Sudoku Image Recognition (Hugging Face), CC0 1.0
- Wicht, B. and Hennebert, J., Sudoku dataset (GitHub), CC BY 4.0; "Camera-based Sudoku recognition with deep belief network", SoCPaR 2014
- NatalijaPetric, SudokuDataset (GitHub), 未註明授權,僅用於量度
- mineshpatel1, sudoku-solver (GitHub), 未註明授權,僅用於量度
- danielsociu, SudokuRecognition (GitHub), University of Bucharest course project, 未註明授權,僅用於量度
- 逐步了解解題器怎樣讀取相片 (English)