跳到主要內容

發表文章

MyTime 雙向關聯的個人行為圖譜系統

  [ Android ] MyTime 是一套個人生活資料庫(Personal Life Database)與行為分析引擎(Behavior Analytics Engine)。 透過簡單的時間記錄與標籤系統,將日常生活中的每一個行為轉化為可分析的資料。 無論是閱讀、飲食、運動、通勤、購物、休閒或睡眠,都可以被長期累積與追蹤。 隨著資料增加,MyTime 會從你的生活紀錄中建立統計、關聯與趨勢分析,幫助你看見: 你的時間都花在哪裡 哪些習慣正在形成或改變 哪些地點、人物或事件與你的生活最相關 過去一年、數月或數週的行為模式變化 MyTime 不只是記錄時間。 它是一套用資料理解自己的工具。 特色 ✓ 秒速開始記錄 ✓ 自由的活動與標籤系統 ✓ 日、週、月、年與全期間分析 ✓ 行為與標籤雙向關聯分析 ✓ 長期趨勢與統計洞察(Insights) ✓ 本機資料儲存,重視隱私 記錄生活。 累積資料。 理解自己。 把人生變成可以探索的資料庫。 隨著年紀增長,我越來越喜歡把許多東西紀錄下來。像上次發表的 Greatest Notes Compiler 知識蒸餾流程 ,就是我對於自己的各種文字記錄所得到的一個成果。 而 MyTime,則是另一塊拼圖。 某天我突然想到:自己每天都在作的事情,到底做了幾次?總共做了多久?我想要知道這些資訊。 這個 APP 我已經連續兩年半每天都使用,到現在才 Release。老實說,MyTime 並不太適合一般大眾,而是針對像我這種有強迫症傾向的數據控。否則我怎麼會連續兩年半,每天記,隨時記。幾乎把每天裡面可以記錄的大小事都紀錄下來,除了晚上睡覺不記(不過白天小睡午睡我也會記)。 不管怎樣,在這個紀錄和開發的過程中,我學到很多。所以在這裡作一些心得分享。 1. 為什麼選擇 SQLite? 之前我己經使用 SQLite 作為資料庫儲存我的書籍和讀書等資料(這也是一類記錄),但我是使用第3方的 app / tool 來維護。 而這次正好有機會讓我直接在應用程式裡面讀寫 DB,選擇使用 SQLite 可以讓我學到新東西。 SQLite 用來儲存幾萬、幾十萬、甚至上百萬筆這種關聯式的小資料完全沒問題,效能也沒問題。備份維護都很容易。 2.每天都在使用(Eat Your Own Dogfood) 每天都要使用,而且大量使用。 使用的過程中,才會發現有...
最近的文章

Greatest notes compiler 知識蒸餾流程

  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 : '未命名筆記...

窮人的 AI:自動漫畫分鏡切割

  ( 試試看 ) 在手機上看漫畫時,有一個體驗上的問題: 漫畫原本是「整頁設計」 手機最適合的是「一格一格往下滑」 與其強迫使用者縮放、拖曳、放大,更直覺的做法是: 直接把一頁漫畫自動切成多個分鏡,轉成瀑布流閱讀。 這篇文章分享一個不靠深度學習、完全在前端完成的實作方式: 使用 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...

Python的Package和Module

最近有時會使用Python作些簡單的後端或工具的開發,這對許多人來說可能很熟悉了,不過在此就讓我這個不熟的新手作些基本觀念的記錄。 在Python中,Package(包)和Module(模組)是用來管理程式碼的結構。 1. 模組 Module Module是包含Python程式碼的檔案,簡單來說就是一個.py的Source Code檔案,裡面可以包含函數、變數、類別等等。或者是一個己經編譯過的.pyc檔案也是一個Module。 如下定義一個a.py的模組。 # a.py a= 1 在其它的Python程式碼檔案裡面可以使用import語句來使用a.py這個模組內定義的函數、變數、類別等等。 如下測試引用a.py裡定義的a。 D:\temp\test>python Python 3.12.3 (tags/v3.12.3:f6650f9, Apr 9 2024, 14:05:25) [MSC v.1938 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__'] >>> import a >>> dir() ['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a'] >>> a <module 'a' from 'D:\\temp\\test\\a.p...