pretty code

2023年9月30日 星期六

第一次結構光初嘗試

中秋節逛寶雅時,剛好看到兩個砧板架,思索了一下,配合束帶應該可以當我的土砲結構光系統架,於是便開始了第一次嘗試。

整個系統如下:


棋盤板也是很克難的用托盤來代替。


拿我最喜歡的美國隊長來當模特兒。


點雲成像品質,只有簡單用 z 當 filter,把雜點去掉。


當然少不了可愛的郭靜。


可惜 gray code + phase shift 不如我的預期,懷疑是照相機在左邊,故 3D 公式應該要改?


只能克難的在飯桌上架設環境,煮飯時又要清空,回復時還要小心不要讓校正好的投影機和相機跑掉,對於第一次的嘗試,我個人覺得至少有 70 分了吧?

繼續思考數學公式中…

2023/10/03 更新

土砲歸土砲,精度看起來還是有的,我的棋盤格橫格約為 17.5mm。


當初使用單目結構光架構是因為我只有一台 webcam,但投影機畢竟是投影機,兩個不同裝置的 model 不一定能完美 match,如果是雙目架構,投影機只是輔助,理論上精度會比現在好,故問題只剩下雙目相機拍照時要保持同步以避免看到的環境光不一致,看來我皮包的小朋友又要出走了?畢竟孩子的學習不能等呀XD

2023/10/04 更新

還是覺得相機擺哪一邊不應該影響數學公式,也就是投影機 y 座標的那個公式,畢竟是從 P1 和 P2 投影矩陣聯立後解 Ax = 0 來的。

再仔細看了一下《Calibration of fringe projection profilometry: A comparative review》 這篇論文,在公式 29 與公式 30 有這麼一段話:「Assume that the projector and camera are arranged horizontally and only vertical fringe images are projected, we can obtain the horizontal coordinate 𝑥 𝑝 by using the phase 𝜙𝑣 ( 𝑥, 𝑦 ) according to Eq. (23) .」


所以表示我的投影機和相機應該水平擺置?但對我這個土砲結構光系統來說,我很難做精細的微調!

在不讓小朋友出走的情況下,我能不能用純軟的方式來解決這個問題呢?

2023/10/05 更新

昨天晚上很克難的用書架把投影機架高,目測照相機和投影機鏡頭中心應該有接近水平?其實不應該用這樣不科學的方式,應該用投影圖案計算來確認兩者是否有水平,但以我這個土砲系統來說,我連找墊高投影機的東西都很難找到,故我就不花時間去計算了,畢竟下班還要搞這個對老人來說也是很累XD

(謎之音:我只是想拍拍可愛的郭靜, 老天爺不要搞我了,拜託XD)

除了墊高投影機外,這次想說把距離拉遠一點,看是否能讓反光影響變小,順便測試投影機 delay 是否可以縮短,之前因為黑條紋會變藍色橘色等不同顏色,故我使用 dealy 1s 的方式來解決這個問題,但拍照的張數越多,時間就會拉長,查了一下我的投影機延遲時間為 35ms,故先用 delay 100ms 的方式來測試,即使已經放大約 3 倍,但藍橘光的情況依舊,為了保險起見還是維持原本的 delay 1s。

這次一共拍了 29 組角度圖片作 calibration,但反光比之前還嚴重,這次可能連 17 組角度都不到,我也懶得算了,面朝下的所有角度都作廢了,導致我的 RMSE 從原本的 0.53 升高到 1.60。

不只如此,我連正常的 gray code 點雲都有問題,完全看不到我的待測物,但 gray code + shift method 反而有東西,雖然雜點是比之前多,但至少是有東東的?

理論上我可以拿之前校正好的參數來套用這次拍的圖片,除了 R, t 失真以外,測了一下,果然使用之前的參數加我這次拍的圖片是可以看到待測物的,當然雜點更多尚屬合理。

帶著一顆失望的心上床去了…

今天中午吃飯回來把絕對相位值畫出來參考,v 選擇解析度的一半 240,看起來果然有錯位,算有符合點雲看到的現象。


一不做二不休,k1、k2、wrapped phase 都一起來吧。


好像看出些什麼來了?

2023/10/07 更新

星期四下班後,做了幾個調整:

01. 架高照相機而不是投影機,之前眼殘,一直以為投影機比較矮。
02. 懷疑是投影機解析度 848 跟 T 無法 matched,改解析度為 1024。
03. 計算 T 時,使用 freq 16 而不是 stripe numbers 32。

我個人覺得 2, 3 才是之前錯位的原因,但我的土砲系統一動就要重新校正,校正時又容易因為反光而得不到好的校正參數,故我也懶得驗證了。

雖然互補格雷碼法與相移法已經搞定,但坦白說沒有比單純 gray code 好多少。

底下是連假前一天下班後的測試及隔天放假第一天的一些實驗。

克難的用書架墊高照相機

做實驗時隨手寫的筆記

上面左邊是 gray code,右邊是 gray code + phase shift。

使用 gray code + phase shift,開燈關燈也會影響點雲品質。

材質不同也會影響點雲品質。

2023/10/09 更新

前天趁著連假的第一天,想辦法搞定 two cameras + one projector 的環境,還好有寶雅,找到便宜的手機三腳架來架設相機,右相機都已經跨到投影機 HDMI 線上才勉強維持一個還過得去的雙目相機視角,整個結構光系統終於克難的架設完畢。


上面不管是 gray code 還是 phase shift,都比原來只有一個相機時差。

中間還遇到傳說中的 OpenCV detect corners bug。

大概想試的都試了,在不繼續看其他 papers 的情況下,我這隻老狗也變不出什麼新把戲了?

額外補充


想要加快開啟相機速度或是設定相機參數速度,可以調整 flags for VideoCapture class。
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
但是 cap.read() 可能就要配合相機的 fps 做 delay,不然會讀到舊的資料。

已經手動拿掉無法匹配的雜點,還是做不出我心目中可愛的點雲,殘念。


精度約差了 4 mm,當然我並沒有很認真 pick points,不過誤差還是 mm 級的,too bad。


2023/10/22 更新

這個假日都在搞管委會資料,趁著煮飯前,再來玩一下結構光,之前看了一篇論文,才恍然大悟為什麼我的點雲周遭雜點很多,我們既然要用結構光來輔助雙目視覺找對應點的難題,我們本來就應該只對投影機有投射的區域做點雲才對,之前都沒認真想過,哈。

即使只是純格雷碼,只關心投影範圍還是能做出不錯的結果,只剩上面哪一小塊匹配不好,以我之前經驗,有些奇怪的地方不一定就是出現在相片 2D 對應的區域,遇到這種問題要查找,只能邊解 3D 邊把點填上點雲,才能看出是在哪裡出錯。

2023年9月27日 星期三

9 又 4 分之 3 月台

結構光也研習了一陣子,反正家裡也有之前買的 webcam 和 projector,想要真的來跑看看結果,不然都只是紙上談兵,正所謂魔鬼就藏在細節裡,只有真的動手去做,才能知道理論與實務的差距,另外,有一些眉角,沒有真的動手做你永遠不會知道!

結構光第一件事就是要打 pattern,gray code 算是一個比較簡單,正確性也還不錯的編碼,很適合第一次嘗試。

原本以為要全螢幕投影 pattern 是件很麻煩的事,是不是要透過 OpenGL 之類的比較底層的控制,稍微 Google 了一下(Google 25歲生日了,時間過得好快,我算是看著他出生的XD),原來用 OpenCV 就可以了,一點都不困難,看起來不需要特別用 Linux 環境。

由於我的投影機很陽春只有幾千塊,故我本就打算解析度只用 640 x 480,沒想到用之前學習的專案產生投影 pattern 後,看著這些 pattern 就讓我不禁產生了疑問,結構光的第一張圖片不是應該黑白各半,為什麼我的白色只佔很小的一部份?

一開始以為是不是作者寫的 code 有問題,看了一下,都是用 OpenCV graycode class,理應沒問題才對,稍微看了下 OpenCV document,他是參考某篇論文實做 class,害我一直往光的二值化方向去思考?

沒關係我有之前寫的 decoder 的程式,一跑完看到 project x index 是從 0 ~ 639,我就馬上知道為什麼了,一開始不知道為什麼想不到?

640 取 log2 要 10 個 bit,故範圍是 0 ~ 1023,但我的投影機解析度是 640,當然只有這張圖前面的 8 分之 5 而已! 

2023年9月22日 星期五

KMODE_EXCEPTION_NOT_HANDLED

公司電腦從上星期安裝某個更新後,在自動時間內重開機安裝更新時就發生不明錯誤,接著便會一直在打完密碼進入桌面後發生 blue screen,因為沒有管理者權限,沒辦法做些修復的動作,只能選擇移除先前的更新,但還是會一直重開機,故最後選擇關機先去吃飯,過了一個多小時回來後開機便正常,接著將剛移除的兩個更新安裝回來,這次便不需重開機便可以安裝完畢。


昨天在 Youtube 看 RISC-V 訪談影片時電腦又無預警當機,一樣在重開機無數次後,選擇關機等待幾分鐘的方式來解決此問題。


從上面可以看到,dump file 位在 C:\Windows,我們需要 WinDbg 工具才可以看些東西,可以選擇在 Windows SDK 中只安裝 debug tool 的方式來取得工具。

開啟 WinDbg -> File -> Open Crash Dump,選擇檔案位置,然後在下面指令列中下!analyze -v 便可以做初步分析。


我這個錯誤的參數 1 如下所述,但我不是做底層的,即使 trace stack 對我來說也看不出什麼東東?目前先這樣吧,反正我會覺得比較像記憶體的問題,故使用冷開機的方式便可以恢復正常。


0x80000003:STATUS_BREAKPOINT
未將核心偵錯工具附加至系統時,遇到中斷點或 ASSERT。

剛試著在重開機時執行記憶體診斷工具,目前確實是有問題,等有空再來跑 MemTest86。


2023/09/22 下午更新

早上想想還是跑 MT86 確認好了,果不期然發生很多錯誤,錯誤都集中在 bit1, bit31。總共跑了快 4 個小時。


由於不是主機板廠商,也不確定 UEFI 的 memory mapping 是否可以看出錯誤位址屬於哪一根 DIMM,只好使用老辦法一根一根做測試,還好透過先前的 MT86,我們可以得知問題多半來自 Test 7, Test 8,這次就只針對這兩個選項跑即可。

原本認為是 9 年多前公司採購電腦那根 DIMM 有問題,但直到跑完一個錯誤都沒看到,幸好在跑我幾年前自己買的那根 DIMM 時真的會看到錯誤(2019/09/24 購買)。


解決方式也很簡單,先把有問題的 DIMM 移除即可。

2023/09/25 更新

MemTest86 v10 以上,配合支援的 chipset,可以 decode error DIMM(>= DDR4),簡言之,會告訴你是哪一個插槽的哪一個 rank 有問題,詳此處

2023年9月17日 星期日

人心難測

開車時需要專心,但人就是很容易分心。

與其說分心,我倒覺得是注意力被引開而集中到某處!

一般左轉時,我們會注意對向來車以及左側後視鏡看是否有不明物從你左邊竄出?

這時如果多了一個變數,我們就很容易將注意力集中到那個變數上,而忽略更多其他變數!

這是我開車上班時一定會碰到的一個小路口,我到這個路口時都必須左轉。


最近這個路口時常都會回堵,故有些時候路無法淨空,數字 2 的車剛好擋到左轉的入口大部份,故我看到數字 3 對向的車都在等待左轉也沒有其他摩托車時,想要快速的左轉,所以我必須小心不要刮到數字 2 的車,也要小心那支位在入口處馬路上的電線桿底座。

此時我已無餘力去注意是否會有白目逆向騎車過來,後來回想起來才覺得危險。

以後回堵最好的處理方式去下一個路口再左轉,雖然要多等 3 個紅綠燈,但這樣比較安全。

雖然我沒有騎車,我只是個行人以及開車的人,但不管那個身份在台灣上路都覺得很麻煩,永遠沒有舒服的感覺,每天走在路上都會遇到邊走邊抽菸的人,還要快速越過他避免菸害,台灣真是無間地獄無誤…

2023年9月13日 星期三

遺珠之憾的雞肋

這個標題下的有點誇張,但我的感覺還真是如此XD


上面是一個使用 binary code 的結構光專案,有趣的是作者使用 blender 軟體來建構所有物件資訊,並非由真實的照相機及投影機所產生。

純以 decode 來說,gray code 相臨數字只差一個 bit 的編碼特性會比 binary code 在找對應點時好很多,故實務上應該是比較少使用它來編碼,目前以我在大衛朗基羅的經驗來看,gray code + phase shift method 應該是有比較好的成像品質。

之前在開始學習結構光相關主題時,我就把 github 上的 700 多個專案看過一遍,坦白說這是個苦差事,在只知道結構光皮毛知識下,要如何分辨哪個專案能幫助學習確實有點困難!單純看 README.md 不太能得到有用資訊,除非專案作者很用心在寫文件XD

故我的 SOP 就是檢查 code 是否齊全,有沒有相機圖片,是否有給相機內參或 R、t,當然最重要的一點就是 code 是否能跑?

如果單純是 Python 還好辦,相關 modules 裝一裝就好;Matlab 沒有軟體就算了,只要有 code 可以 porting 就好;但遇到 C++ 類的就沒輒,我一定要先能成功編譯它才能夠去跑它! 

這個專案很不巧的就屬於這種,即使我有 vcpkg 的加持,還是要經歷邊報錯邊檢查少了什麼再繼續安裝的無限循環,這個專案為了平行處理還使用了 halide 的函式庫,故還需要 llvm 的相關工具,印象中當初為了這個專案,假日時常要遠端登入公司電腦好確保 vcpkg 安裝相關函式庫時有順利執行,沒有半途發生錯誤被中斷,因為 llvm 很吃硬碟空間,為了這個還要搬移資料分割區資料,並執行微軟硬碟工具內建動態擴充功能擴充 C 槽才能順利安裝。

我還記得當初因為硬碟空間不足,vcpkg 安裝常出現莫名錯誤,當時沒意會到是這個原因,故我在某一次的放假遠端登入中終於放棄,改使用家裡電腦安裝。雖然最後有成功安裝,但因為兩邊電腦發生過的安裝錯誤實在太多,故我也來不及寫筆記XD

好不容易順利執行,即使都是使用 blender 的假資料,binary code 的 dense match 還是很吃二值化設定,故成像品質也只是 so so,所以最後這個專案也沒有放進我安排的學習清單中,所以我才說它是一個遺珠之憾的雞肋XD

剛在電腦看到殘缺的筆記資料,還是把它記錄一下好了,凡走過必留下痕跡。

build llvm error
'atlbase.h': No such file or directory

印象中,這個 error 是 VS building tool 少裝 ATL 相關的套件,再 Google 一下應該就有答案?

-----------------------
vcpkg install halide:x64-windows
vcpkg install glm:x64-windows
vcpkg install glfw3:x64-windows
vcpkg install llvm[target-all,clang-tools-extra]:x64-windows

-----------------------
cmake . -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/src/vcpkg/scripts/buildsystems/vcpkg.cmake
msbuild xxx.sln /p:Configuration=Release

2023/09/14 更新

花了好幾個假日編譯好的東西還是想要留個記錄,於是在辦公室的電腦又做了一次XD

果然,憑著殘缺的筆記是不夠的,這次在 build halide 又遇到奇怪的問題,改先安裝 llvm,It is building …

2023/09/14 更新

llvm 遇到錯誤了,沉思中…

2023/09/27 更新

擴充記憶體到 16G 後,看起來記憶體不足的問題有解決,但在寫入檔案時會失敗。

mt.exe : general error c101008d: Failed to write the updated manifest of xxxxx.

試著將 C:\src\vcpkg 加到 Windows Defender 的例外掃瞄資料夾,但這個問題還是沒解決,可能真的必須關掉防毒軟體才行,我們可能沒有權限做此件事?

2023年9月8日 星期五

GCP VM 使用省錢小技巧

嚴格來說,GCP VM 的名字應該是 Computer Engine,但我還是喜歡 VM 這個稱呼,可能是習慣了吧?就不知道這個名詞是否有被 VMware 註冊就是了?

不論是公事還是私事,有需要時我就會開一台 VM 來做事,即使我新買的電腦已經夠強了,我還是習慣使用 VM,因為這樣電腦可以關機。

大部份要做的事都不是一天內可以做完,如果是可以一直跑的倒是沒差,反正就是一直聽到錢錢被吃的聲音XD

但是像我想開發 Kobo EInk-bro 的事就不是一件可以持續跑的工作,常常遇到問題就要停下來思索,故都只能利用下班時很零碎的時間來工作,為了保持工作狀態以及省錢,理論上不用時停機是比較好的選擇,這樣大概只會有以下支出:

01. 硬碟費用。

如果是 50 GB 的預設普通硬碟,一個月約莫是 US $5。

02. 靜態 IP 費用。

03. 額外監控費用。

一般來說只會遇到這幾種可能費用,以我來說,我應該只會有硬碟的費用。

這次是第一次這樣工作,記錄一下未出帳帳單狀況,看起來有符合我認為的情況,只是他的計算似乎有時間差,就不知道到底是雲端服務工作太多帳單伺服器無法即時計算,又或是單純時區時差的問題就不得而知了,以我的經驗大都是要到晚上才能看到昨天 NT $5.X 的完整數字(US 5 * 32 / 31),早上查詢時都只會看到 NT $2.X 的金額。

2023年9月6日 星期三

Coding is magic

軟體工程師是很幸福的一個職業,假設不要碰到硬體的話?當然跟數學比起來,硬體還是簡單多了(所謂的簡單只是站在韌體的角度來看,且要控制的硬體有清楚的 Spec 可以參考)

不論是公事還是私事,只要有一台電腦而且是可以寫 Code 解決的事,我們都可以開心的寫 Code 來幫助工作?

今天看到一個專案 wphpfpm,它主要用途是在 Windows 下管理 php-cgi 的行程,也就是類似 Apache server 的 mod_fcgid。

還記得我的第一個 Web 服務就是用 C 寫一個 cgi 程式並透過 FastCGI 的協定與 Apache 溝通,當時的我 Web 相關技能只會 PHP 且對後端矇矇矓矓,才會這樣繞一大圈做這種脫褲子放屁的事(PHP 本身就可以發 web request 給其他網站了,既然都要寄生在 Apache 下,何苦使用 C 語言找自己麻煩?雖然我因為這樣多學會了很多編譯第三方函式庫的小技巧就是XD)

當初在開發的過程中,發現 C 確實沒那麼好用,也因為如此認識並學會了 Go 這個語言,雖然後來幾乎沒在寫 Web 服務,但也多學會了一技傍身。

巧的是這個作者也是使用 Go 來開發專案,讓我不禁想到那段往事,雖然我也想不太到這個專案的用途就是?既然都會 Go 了,Apache Server + PHP 都可以直接用 Go 做掉,使用 Go 開發一個 FastCGI 管理程式確實意義不是很大?

不過,Just for fun 無價,正所謂 Coding is magic …