1. Greatest notes format 平常我就有作筆記的習慣,其中大部份的筆記都是非結構化的文字檔,部份是 markdown 格式,這樣在任何平台只要有文字編輯器,就能很方便檢視及編輯,而不必依賴特定的應用程式。 久了就慢慢累積了不少資料,有日記、工作日誌、筆記、雜記等等。為了方便檢視,我也作了一個小 app,可以讓我在一個畫面內快速檢視我的筆記列表,再點入去作進一步的檢視各別資料或統計資訊等。 雖說這些筆記幾乎是非結構化的,但其實還是有少量的規則,這樣我的程式才能作簡單的解析。例如日記或工作日誌基於日期的資料,至少有個日期標題和不定長度的內文,或是筆記類的資料至少也有個標題和不定長度的內文,等等。 漸漸的我盡量把類似性質的筆記的格式統一起來,最後我發現其實可以用一個很簡單的格式全部統一。它就是 Greatest notes 格式。 Greatest notes 文件是文字檔。內容由不定數量的項目組成,每個項目由一個標題和不定長度的內文組成。每一個項目由每一行開頭的">>> "開始,直到下一個">>> "或者是檔尾,就是一個項目。 例如: >>> 這是一則筆記 內文 內文 內文 ... >>> 另一則筆記 內文 內文 ... 格式很簡單,要寫一個解析器也很簡單。因為只需要 re 以 ">>> " 對整個檔案切割,再從每個項目的第一行取出標題,其餘為內容。 例如下面就是一段可以解析 Greatest notes 文件的 javascript 程式。 // javascript let notes = raw.split( /^>>> /gm ).map( note => { let i = note.indexOf( '\n' ); let title = note.substring( 0 , i); let content = note.substring(i + 1 ); return { title : title !== '' ? title : '未命名筆記...
( 試試看 ) 在手機上看漫畫時,有一個體驗上的問題: 漫畫原本是「整頁設計」 手機最適合的是「一格一格往下滑」 與其強迫使用者縮放、拖曳、放大,更直覺的做法是: 直接把一頁漫畫自動切成多個分鏡,轉成瀑布流閱讀。 這篇文章分享一個不靠深度學習、完全在前端完成的實作方式: 使用 OpenCV.js 做分鏡偵測 輸出 rect list 再用 全畫面 Canvas 把每個分鏡當成一個「閱讀單位」 整個系統可以拆成三層: 漫畫圖片 ↓ 影像處理(找出 rects) ↓ 排序後的 rect list ↓ 全畫面 Canvas 逐格呈現(瀑布流) Step 1:灰階化 漫畫的資訊 90% 都在線條上,顏色反而是干擾。 cv.cvtColor(src, grayImage, cv.COLOR_RGBA2GRAY); 灰階化的好處: 降低維度 對邊緣偵測更穩定 對黑白漫畫特別有效 Step 2:邊緣偵測,抓出「分鏡的邊」 接下來用最經典、也最夠用的 Canny Edge Detection: cv.Canny(grayImage, edges, 50, 150); 在漫畫中,分鏡外框通常就是最明顯的邊界。 Step 3:形態學操作,把破碎邊框「補起來」 真實漫畫的線條並不完美,常常有斷線、陰影、留白。 所以要做一個很重要的步驟:膨脹(Dilation) const kernel = cv.Mat.ones( 5 , 5 , cv.CV_8U); cv.dilate(edges, dilatedEdges, kernel); 直覺理解就是: 把細線「抹粗一點」, 讓本來斷掉的邊界連成封閉區域。 這一步直接決定後面能不能成功抓到「一整格分鏡」。 Step 4:找輪廓,轉成矩形框(rect) 有了封閉區域之後,就可以找輪廓: cv.findContours( dilatedEdges, contours, hierarchy, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE ); 每一個 contour,代表一個「可能的分鏡區塊」。 接著轉成矩形: const rect = cv.boundingRect(contour); rects.push([rect.x, rect.y, rect.widt...