這個頁面的程式碼沒跑起來。

直接從資料夾裡開啟 index.html,瀏覽器會攔下 JavaScript 模組,於是你選好一張紙的照片之後,頁面不會有任何反應。改用 http 把這個資料夾提供出去:

powershell -ExecutionPolicy Bypass -File serve.ps1

然後開啟 http://localhost:8080/。

文件掃描 把一張紙拍成掃描檔

把紙拍下來,回來的是一份看起來像掃描的東西。

語言: 繁體中文
檢視原始碼
你的文件不會上傳。這裡根本沒有伺服器。

照片的解碼、擺正、清理,以及寫成 PDF,全由你自己的瀏覽器完成,用的只是算術和它本來就帶著的編解碼器。這個工具沒有任何聯網功能,不取東西,也不發東西。這一點在這裡為什麼要緊,看看人們都拍些什麼紙就知道了:護照、工資單、租房合同,或者某個單位讓你「掃描後發回來」的表格。

即時檢查: 檢查中…

離線: 檢查中…

別聽我們說。開啟開發者工具,盯著網路面板,然後掃一張紙。沒有任何一條請求帶著照片、縮圖、檔名,連一個角的座標都沒有。或者乾脆斷網,照樣掃得了。

1 選照片

一頁一張照片,從上方拍。整張紙要在畫面裡,四個角看得見或者接近看得見。別的一切,傾斜、陰影、下面那張桌子,都是這個工具存在的理由。加進來好幾張,它們就按你加的順序變成一份文件的各頁。

2 把角對到紙上

在照片上隨便點一下,最近的那個角就到你手指這裡來,把它拖到紙的角上。用 Tab 可以從鍵盤選中一個角,方向鍵挪一個畫素,按住 Shift 挪十個。這些都不是不可挽回的,掃描的是四個角最後停在哪裡。

選一張照片,它會出現在這裡,四個角已經替你找好了。

3 清理

下面這個就是真結果,做它的和寫檔案的是同一段程式碼:擺正過,不勻的光也除掉了。你在挑的時候,螢幕上按螢幕的尺寸畫;檔案本身按照片的解析度做。

彩色,去掉不勻 把紙的亮度在整頁上量一遍再除掉,於是陰影消失、紙重新變白,而印章、藍墨水的簽字、熒光筆劃的那一行都保住自己的顏色。顏色本身屬於文件的時候,用這個。

灰階 同樣去掉不勻,只是不要顏色。比彩色小,對照片和簽字也比黑白溫和。

黑白 每個畫素是拿它自己的鄰域來判,而不是拿整頁一個數字,這正是陰影裡的字還看得清的原因。掃描檔小下來靠的就是它:二十頁的合同用這個模式在一兆以內,存成照片則要十五兆上下。這個模式沒有中間調,所以帶照片的頁面別選它。

保持原樣 只擺正,別的什麼都不做。給那種紙本身也要緊的頁面用:有年頭的、帶顏色的、或者一張照片。

一有照片可以擺正,擺正後的頁面就出現在這裡。

4 儲存文件

PDF 就在這裡、在這一頁的記憶體裡一頁一頁地做出來。這個工具的另一頭沒有伺服器可以接收工資單、護照或者合同,程式碼裡也沒有任何東西會去做這件事。

列印解析度 一張由這麼多畫素組成的紙,要管它叫多大,就這麼回事。它改的是文件列印出來的尺寸,掃描檔裡一個畫素也不會變。

最長邊 擺正後頁面的上限。一張紙的照片帶的畫素遠多於這張紙值得的,長邊 2400 在 A4 上大約是 200 DPI。

品質 用於存成 JPEG 的彩色和灰階模式。黑白頁面是精確儲存的,對它們這一項不起作用。

文件標題(可選) 除了頁面之外,寫進文件裡的只有這一樣。沒有日期,沒有作者,也沒有關於這臺裝置的任何東西。看 src/document.js。

82%

以 Markdown 檢視

怎麼用手機鏡頭掃描文件

  1. 把紙拍下來。從上方拍,讓整張紙都在畫面裡,四個角看得見或者接近看得見。不用正對,也不用光線均勻,傾斜和陰影正是這個工具存在的理由。要緊的是把畫面填滿:從房間那頭拍的一張紙,裡面根本沒有可以救回來的細節。
  2. 核對四個角。照片讀進來時就替你找好了,拿不準的時候頁面也會說。放在跟紙同色的桌子上的紙,邊緣確實很難看清。在照片上隨便按一下,最近的那個角就到你手指這裡來了;也可以用 Tab 選中一個角,再用方向鍵挪。
  3. 決定光怎麼處理。「彩色,去掉不勻」把紙的亮度在整頁上量一遍再除掉,於是陰影消失,而印章和簽字保住自己的顏色。「黑白」走得更遠,掃描檔能小到可以發郵件,靠的就是它。螢幕上看到的就是真結果,寫檔案的是同一段程式碼。
  4. 把其餘的頁加進來。每加一張照片,就是同一份文件的下一頁,順序就是列表裡的順序,每一頁各自保留自己的四個角。縮圖條上那一頁的箭頭可以把它往前或者往後挪。
  5. 存成 PDF,發出去之前先開啟看一眼。文件就在這裡、在這一頁的記憶體裡做出來。做它的過程沒有上傳任何東西,關於它也沒有向任何地方報告過什麼。

說得更細的版本

怎麼用手機掃描文件 一張紙的照片和這張紙的掃描檔之間差在哪裡:傾斜、不勻的光,還有檔案大小。照片怎麼拍,之後要修什麼,以及為什麼這些都不需要伺服器。

常見問題

我的文件會被上傳嗎?

不會。照片的解碼、擺正、清理,以及寫成 PDF,全都由你自己的瀏覽器在你自己的硬體上完成。這個工具沒有任何聯網功能,從不取東西,也從不發東西,頁面的 Content-Security-Policy 裡寫著它能聯絡的每一個地址,沒有一個屬於本站。把頁面載入一次,斷網,它照樣能用。

沒有模型,它怎麼找到紙的四個角?

靠找出組成一個四邊形的那四條又長又直的邊。照片先縮小,取梯度,也就是看影像在哪裡變、朝哪個方向變,然後每一個落在邊緣上的畫素都為自己應該落在的那條直線投一票。強的直線兩兩配成候選四邊形,每個候選再走一遍自己的四條邊打分:每條邊下面究竟有多少真的是邊緣,以及這四條邊是不是同一樣東西的邊界。紙要麼比周圍亮,要麼比周圍暗,但四條邊上是同一種關係,正是這一點讓一行字不會被當成紙的下邊緣。沒有權重,不下載任何東西,任何文件進來算的都是同一套算術。

它找的角不對,怎麼辦?

拖過去就行。四個角是起點,從來不是決定,掃描的是四個角最後停在哪裡。在照片上隨便按一下,最近的那個角就跳到你手指這裡來,比去戳一個小手柄容易得多;方向鍵每次把當前選中的角挪一個畫素。角是猜出來的而不是找出來的時候,頁面也會說,並在縮圖條上給那一頁做個標記。常見的原因是紙放在跟它顏色差不多的桌上,那裡確實幾乎沒有邊緣可找。

擺正之後的紙為什麼形狀是對的,不是被壓扁的?

因為形狀是從透視裡還原出來的,不是從邊緣量出來的。斜著拍的紙,遠端那條邊會被壓短,所以最順手的辦法,也就是取最長的一對對邊當成比例,會做出一張明顯偏矮胖的 A4,網上多數掃描工具給你的就是這個。其實一張四邊形的照片裡,只要相機是臺普通相機,資訊就足夠同時還原出這個四邊形的真實長寬比和相機的焦距。這是 Zhang 和 He 在 2003 年的結果,src/geometry.js 做的就是這個。正對著拍的照片沒有透視可用,也不需要,因為那時邊緣本來就是準的,於是它退回去用邊緣,並且頁面會說明是哪一種給出了答案。

「清理」到底對影像做了什麼?

把光除掉。紙自己的亮度在整頁上量一遍:分成一格一格的小塊,每塊取亮度的一個高分位數,文字太暗也太稀疏,動不了這個數;然後每個畫素都除以那一點估出來的紙的亮度。剩下的就是墨跡,光線均勻,陰影和邊角發暗都沒有了。這跟提高對比度不是一回事:把一張拍下來的紙提高對比度,亮的地方變白,暗的地方變黑,暗處寫的字也跟著看不見了。「自動色階」把這類圖片弄得更糟而不是更好,原因就在這裡。

黑白模式為什麼小那麼多?

因為只有兩種顏色的影像,資料量確實只是一千六百萬色影像的一個零頭,這裡也就真按那樣存:每畫素一位,八個一組塞進一個位元組,再精確壓縮,而不是把一張黑白圖片存成 JPEG。在同樣的頁面上,它比彩色模式小十八倍左右,於是二十頁的合同從十五兆左右降到一兆以內。閾值用的是 Sauvola 的方法,每個畫素是拿它自己鄰域的均值和離散程度來判,而不是拿整頁一個數字,這正是陰影裡的字還看得清的原因。它沒有中間調,所以帶照片的頁面應該換別的模式。

可以把好幾頁放進同一個 PDF 嗎?

可以。每加一張照片就是下一頁,順序就是列表裡的順序,每一頁各自保留自己的四個角,於是接連拍下來的一疊紙就成了一份文件。縮圖條上每一頁的箭頭可以把它往前或者往後挪。清理設定是所有頁共用的,這是故意的:同一份文件裡清理方式不同的頁面,看起來像兩份文件。

它會識別文字,讓 PDF 可以搜尋嗎?

不會。這裡沒有文字層,也沒有字元識別,出來的是一頁紙的影像放在一頁上。真要做好就得用 OCR 引擎,那是幾十兆的模型要下載,而一個在讀你的工資單之前先去取模型的文件掃描工具,就是一個有理由為工資單往家裡打電話的工具。你要是需要文字,黑白模式做出來的檔案,恰恰是你自己機器上的 OCR 軟體最好處理的那一種。

拍糊了,為什麼?

幾乎總是因為紙在照片裡太小。預覽下面那一欄會寫紙填滿了畫面的多少,以及在那個尺寸的紙上大致相當於每英寸多少點。低到 150 DPI 上下,列印出來的掃描檔就顯得發虛,而檔案裡本來就沒有的細節,任何工具都變不出來。別用變焦,直接走近;端穩;按下之前先讓相機在紙上對上焦。另一個原因是手抖,那也救不回來。

免費嗎?要註冊嗎?

免費,沒有帳號,不用登入,沒有試用期,不限頁數,也沒有水印。照片多大也沒有限制,因為根本沒有伺服器在為它掏錢,工作是在你自己的機器上乾的。本站靠廣告養活,廣告那邊拿不到關於你文件的任何東西。