分類: CV

  • ZLUDA 收官之戰 – 它還只是個孩子啊!

    ZLUDA 收官之戰 – 它還只是個孩子啊!

    承上文:

    ZLUDA 拓荒之路 – 榨乾 Intel CPU 算力的中短期方案

     

    先說結論:

    ZLUDA 目前在我的環境測試起來並不支援一些好棒棒框架,

    像是 PyTorch、Numba 之類的,雖然我沒有測試,但是有足夠信心認為 Tenserflow 也不支援。

    先附上我的環境:

    OS: Ubuntu 22.04

    Intel GPU: UHD 770

    我的測試方式是下載 ZLUDA 的 Releases 2 的版本

    這個解開會有一個資料夾內含兩個 .so 檔,

    將想執行的檔案放在與 .so 檔同個資料夾下執行即可。

    但是像作者一樣測試 GeekBench 5.2.3 的話是會過的,

    數據差別不大,至於為什麼測出沒有 Sobel 測項?

    因為要有那個測項要付錢啊啊啊啊啊!
    GeekBench 5.2.3 官網下載點

    接著我要勘誤上篇關於 CUDA 與 ZLUDA 的引用關係,

    後來發現 ZLUDA 使用上應該是要完全取代 CUDA 的,

    所以你不裝 CUDA 它也會跑得起來。

    但由於 ZLUDA 並沒有支援 CUDA 的所有功能,

    加上我猜測它是針對某版的 CUDA 來開發的,

    所以 API 串接那邊也會報錯,而 CUDA 本家會動態連結這些函式,

    導致 ZLUDA 的支援性很低。

    最後來談談這東西的未來性還有有志之士可以怎麼發展下去?

    我認為這東西會踩到 Intel 把拔的 oneAPI 計畫,

    短時間內應該就這樣了。

    所以除非有誰與 Nvidia, Intel 同時具有競爭關係又做 CPU + GPU?

    ZLUDA 才會復活。

    (望向蘇媽)

    有志之士的話可以接著試試看,

    因為我曾經在 Python 3.7 及上述環境中讓 Numba 呼叫到 Intel UHD 770 的硬體。

    以下是給有志之士的簡易指南:

    1.確認自己手上有(消費級 Intel CPU 超過 8代 或  Intel XE CPU)且 (有內顯)

    2.裝 Intel 內顯驅動(Ubuntu 20.04 可以參考這篇, 22.04 也可以參考但記得不用降內核)

    3.確認內顯驅動有裝好xD

    4.裝 Python3.7 + Numba 0.49 – 0.58 版本,我印象當時是裝這區間。

    5.下載 ZLUDA 的 Releases 2 的版本 來測試

    裝驅動的時候要特別注意,

    我在那邊卡很久,不一定第一次會裝好,

    重複裝的時候不要反安裝到這個 gawk libc6-dev udev,

    這套件就算你不 –purge 都會幫你把 Gnome 還有一拖拉庫東西 拆掉 :)

    最後講一下 Intel 的 oneAPI,

    我用過裡面的 Intel® oneAPI Base Toolkit + Intel® AI Analytics Toolkit(PyTorch 最佳化)

    用同一台機器來計算同一份呼叫到 PyTorch 的檔案,

    用 Intel 方案的環境會算得比純 PyTorch 版本還要慢。

    就是大家可以收一收回家了,感謝各位。

    如果有志之士想討論 or Intel 官方想維護一下自己的東西(#。

    歡迎聯絡我:

    wuyiulin@gmail.com

  • Repulsion Loss 利用三項之力改善物件重疊問題

    Repulsion Loss 利用三項之力改善物件重疊問題

    最近小弟接到公司派的任務,
    主要負責解決物件重疊的問題。

    這篇算是我的物件重疊解法啟蒙之作,提筆紀錄一下。
     Repulsion Loss 主要是作者看到磁力作動所併發的想法, 
    (這說法跟牛頓他老爺子被林檎砸到有 87%像)
     所以 Repulsion Loss 主要有三個力(Loss)組成:

    • L_Attr          – 使 BBOX_pred 與配對到的 GT BOX 相近。
    • L_RepGT     – 使 BBOX_pred 遠離其他 GT BOX 。
    • L_RepBOX  – 使 BBOX_pred_i 遠離預測其他出不同類別的 BBOX_pred_i,
                               可以避免因為距離太近,NMS 把框砍掉的問題。

    (至於 NMS 機制可以看這篇,我認為他講得很好。)

    Alpha 與 Beta 就有點 Focal Loss 的味道了,

    兩數和被一所約束。

    L_Attr

    L_Attr 的物理意義是使預測的框(BBOX_pred)與配對到的 GT BOX 接近。
    要算 L_Attr 就要先定義兩項集合:
    {G} = 所有的 GT BOX 集合
    {P}  = 所有正樣本的 Anchor 集合
    這裡簡單解釋一下 {P},就是所有包含前景的 Anchor 們,
    或是所有有物件、不是背景的 Anchor 們集合。
    這邊我也疑惑了一下什麼正樣本,有 BBOX 不就代表有物件了嗎?
    接下來用 G, P 集合造 G^P_Attr:
    G^P_Attr = argmax_G∈G IOU(G, P)
    這個意義在於讓偵測到物件的每個 Anchor 都有一個家(GT BOX)。

    但是 G^P_Attr 畢竟還是一個對應關係,
    一個是 Anchor 、一個是 BBOX 還是不能算 Loss,
    所以利用 P 去做 B^P,也就是基於 P 的 BBOX。 
    接著用 L1_Smooth 造 L_Attr:

    L_Attr 結案!

    L_RepGT

    L_RepGT 的物理意義是使預測的框(BBOX)遠離其他不屬於自己的 GT BOX。
    要算 L_RepGT 也要先求一個 G^P_Rep ,
    G^P_Rep 的物理意義是:
    對於該 BBOX_pred 來說 IOU 第二大的 GT BOX(最有機會的外遇對象)。
    我們為了阻止 BBOX_pred 外遇(#,
    所以把 G^P_Rep 算出來之後拿去與 B_P 做 IOG,
    再給它一個重疊度太高的懲罰權重。

    至於這邊為什麼是用 Smoothln 而不是 SmoothL1
    綠色為Smoothln; 紅色為 SmoothL1;

    以下個人猜測:

    因為 IOG 的值域是 0-1,越趨近於 1 ,Loss 應該要越大。
    Smoothln 看起來比 SmoothL1還好調整懲罰權重(調整 Alpha),
    而且驗證 IOG 會不會出錯的時候也比較好用。

    至於 Alpha 作為一個超參, Alpha 的值與對 outlier 的敏感度成正比。 

    L_RepBOX 



    這個 Loss 就比較直覺,主要提一下 1,想像成乘上步階函數,把小於零的地方除值。
    比較不同的是 x 為零時的定義為零。
    至於 epsilon 則是一個不為零的極小值,
    目的是為了抵抗分母為零造成數值 NaN 的梯度爆炸問題。
    以上,大概講一下我對於 Repulsion Loss 的理解。

    如果有問題歡迎聯絡我:
    wuyiulin@gmail.com

  • The Devil is in the Pose: Ambiguity-free 3D Rotation-invariant Learning via Pose-aware Convolution 論文導讀

     
    本文建議有點雲特徵的先驗知識者閱讀,

    我會盡量講得平易近人,

    但仍建議請先參考此篇,先了解基本點雲處理如何處理特徵。

    這篇論文的重點在於改變了底層特徵方法。

    論文中由這張圖來解釋:

    因為現行解決 Rotation Invariant 的方法都是乘上一個矩陣去收集數據,

    並沒有考慮點與點之間的結構關係(i.e.上圖笑臉)。

    但是我覺得這個例子呈述得很容易誤導,

    聽起來很像在解決高低解析度、上下採樣的問題,

    實際上在點雲裡面應該是解決類似 KNN 特徵的問題才對。

    像是那三個有黑色像素的點,間隔距離、彼此夾角之類的結構關係所產生的資訊。

    作者認為現在的 CNN 都沒有抓到結構關係 (Pose) 的精華

    (e.g. 點雲中點與點的區域關係 AKA 底層特徵),

    所以要提出解決方法稱為 PaRI 的新架構來解決問題

    (我猜是 Pose: Ambiguity-free 3D Rotation-invariant 的縮寫)。

    舊有的底層特徵方法:

    好,那要改進一定得知道改哪裡嘛?

    之前別人是怎麼做這種結構特徵的?

    答案是:Point Pair Feature(PPF)

    Point Pair Peature

    Pr 是參考點,想像成 KNN 的目標點;
    Pj 是 Pr 附近的鄰居點,有 K 個;

    ∂n_r 是相較於 r 的三維座標軸,用  gram-schmidt orthogonalization 算出來的,

    忘記的同學可以去複習一下 GSO

    所以經過 PPF 計算,我們會得到一組四個特徵如下圖:

    這樣會出個小問題,各位想想好的底層特徵應該要具備什麼特性?

    應該要具備獨特性嘛!
    因為這樣訓練起來才不會與其他特徵混淆。

    仔細觀察 αn 的方程式我們會發現,沒有一條能分辨在這個半徑為 d 的圓圈上,

    有若干個法向量相同的  Pj 的辦法。 

    (∂1_r, ∂1_j 分別代表各自的法向量,ModelNet40資料集會給定。)

    改善方法:

    在改善之前,我們先想想舊有方法遇到什麼問題?

    問題是缺少 Pr 與 Pj 間的獨特特徵,對吧?

    所以我們希望新的方法最好讓每個 Pj 對 Pr 有獨特性。

    Local Reference Frame(LRF) +   Augmented Point Pair Feature(APPF)

    就能解決這個問題。

    LRF


    Local Reference Frame


    左邊那個飛機圖,是為了說明使用 Global Feature 會有問題而存在的,

    有興趣可以深入論文研究。

    LRF 這裡我們要先建三軸,首先要拿到 e^2_r;

    e^2_r = Pr – mr 的座標向量,mr 是 Pj 們的重心。

    接著根據公式建三軸:


    APPF

    Augmented Point Pair Feature

    接著把 d 投影到 π_d 上。

    什麼?你說 π_d 是什麼?

    論文這裡沒有寫得很清楚,

    我也看了很久,最後是對照著官方程式碼看才看出來。

    其實 π_d 就是座標向量 e^2_r! 

    投影上去,然後用 arctan 取角度回來。

    不知道為什麼用 arctan 而不用 tan 的同學,這裡有兩個理由:

    1.對應域

    i.e. tan(45°) = 1 = tan(225°)

    但是 arctan 只會給你 45°

    2.極值

    tan(89.9°) ≈ 5729.58,但 tan(90.1°) ≈ -5729.58。 

    arctan(5729.58) ≈ 89.9°,但 arctan(-5729.58) ≈ -90.1°。

    以上。

    若有任何錯誤請聯絡我xD

  • OpenCV AI Kit 1 (OAK-1)從零開始的傻瓜式教學

     

    起因是因為主管塞了兩盒工程機包裝的東西給我,

    叫我趕快做點東西出來。

    :大勾請問這兩盒是什麼?

    "窩也不是很清楚,應該是攝影機吧?"

    "上禮拜才送來的,就交給你好好幹了!(瞇眼。"

    回到座位拆開包裝,奇妙的字眼映入眼簾 – OAK-1?橡樹一號?

    乖乖隆叮咚?

    我的業務範圍上從先進飛彈制導,下至林業技術輔導了嗎?

    看來下一任臺灣隊長就是我了對吧?

    現在應該抓緊時間去曬太陽之類的?

    Anyway 這的確是攝影機,不是什麼先進的橡樹、農業技術輔導。

    OAK-1 的全名是 OpneCV AI Kit

    會出現這東西,我猜是 OpenCV 覺得大家用的環境太混帳了,

    導致沒辦法發揮我們程式的實力,所以自己跳出來賣攝影機的概念。

    (我看過學弟拿沒 GPU 的文書機配 WEBCAM 在那邊掃口罩偵測,FPS 著實感人。)

    做影像辨識是這個樣子:

    影像辨識是需要算的,就算你模型都訓練好,

    還是要有一個地方可以判斷(計算),像是我學弟那個例子就是把影像丟回電腦用 CPU 算,

    結果就是出來的影像 FPS 感人。

    這麼感人的 FPS 肯定是不行的,畢竟未來要用在載具上,

    任務時間來到毫秒級,FPS 必須提高,下游任務的準確度才會提高。

    (才不會上演街頭人肉保齡球。)

    但是 OpenCV 左想右想,總不可能在每臺載具上面塞一張很貴的 GPU 對吧?

    為了教育我們這些只用 CPU 算的弱智兒童(X)

    為了讓貪財產業鏈侵入學生生活(O)

    (OpenCV 後面是 Intel,Intel 最近重新出了自己的 GPU 你知道的。)

    就出了 OAK 系列,裡面幫你塞了一張 VPU。

    VPU 是一種介於 CPU 與 GPU 中的東西,

    可以想像成沒那麼強的 GPU ,但是可以負責簡單的判斷。

    總之有這張 VPU 塞進去以後捏,好處有兩個:

    1.後端(伺服器端)可以不用塞 GPU,這種 Camera 又比 GPU 便宜很多,省錢!

    2.判斷直接在 Camera 直接做完,理論上比較省傳輸的 latency。

    好,前面廢話那麼多,來裝環境。

    首先這篇環境是 for Windows 10 ,因為我在公司被分配到 Windows 10 的機子,

    順便做個紀錄,聽起來以後要交報告的,多塞點廢話(X)。

    首先用管理員權限打開你的 Windows Shell (藍底白字的那個)

    Windows Shell

    Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
    

    如果你沒有喜歡的編輯器 加上 還沒有安裝 Python 

    就下這行,幫你裝 PyCharm + Python-least:

    choco install cmake git python pycharm-community -y
    

    然後你可能會發現阿幹怎麼 GIT 裝失敗?

    下這行:

    winget install --id Git.Git -e --source winget

    然後就裝起來了,一整個正確!

    去載這包:

    https://github.com/luxonis/depthai-python

    啟動 example/Yolo/tiny_yolo.py

    偵測結果

    好欸!

    你也可以說自己會偵測物件了(ㄍ。

    之後應該會做其他東西吧?(望天。

    Ref. 

    官網教學:https://docs.luxonis.com/projects/api/en/latest/install/#installation

    輔助影片教學:https://www.youtube.com/watch?v=ekopKJfcWiE&ab_channel=BrandonGilles

  • 何謂利用語義分割(semantic segmentation)分類三維點雲?

    前言:

     因為左岸的論文導讀只有一份,而且抄來抄去跟大學生做畢業專題一樣。
     所以我打算自己來幫自己讀的 paper 下註解。

    這篇文章要告訴你兩件事:


    一、語義分割在幹嘛、原理是什麼?


    二、語義分割怎麼用在分類點雲?

    我這篇不會講太多關於 NLP 實務上怎麼做、怎麼實現…

    只會概念式的讓你知道:語義分割與點雲的關係






    一、語義分割在幹嘛、原理是什麼?



     講語義分割就要稍微介紹一下 NLPNatural Language Processing

     NLP 就是把 自然語言(人類講的話:英文、中文、德文…)轉成機器可以用的東西,
     基本上這就是 NLP 在做的事情。

     口說無憑,舉個例子:

     假設"Costco"這個詞在電腦眼裡看起來是"0100" ;

     "IKEA"在電腦眼裡看起來是"1111"
     (BTW 這邊的字串代表向量)

     兩個差了 3  bits
     那麼這兩個詞在做 NLP 的時候就不會視為同義詞
     電腦不會跟你說:IKEA?我都念 Costco ლ(´ڡ`ლ)

     如果是"Ben"與"Benny"的話,因為"Ben"是"Benny"的縮寫,
     所以電腦做 NLP 的時候 這兩個詞的向量就會很接近

     簡單來語義分割的用途就是把句子裡面的詞一個一個切出來看向量,
     比較資料庫裏面的向量找出使用者到底想要表達什麼意思?
     通常語音辨識、輸入會大量用到這個功能

     NLP 裡面還有很多東西可以講,這只是大概介紹要用到的功能。

    二、語義分割怎麼用在分類點雲?


     首先我要引用這張圖片:

     

    (ftrom https://arxiv.org/abs/1801.07829 , Yue WangYongbin SunZiwei LiuSanjay E.SarmaMichael M. BronsteinJustin M. Solomon

     我們可以看到機身的顏色不一樣(廢話)

     黃色代表與選取的紅點關係相近的點

     其實這是一張利用"語義分割"做"飛機部件分割"的訓練過程,
     你可以看見由左至右,原本我們找的 紅點 只跟物理距離相近的點有關;

     但是越訓練越往右走,你會發現與 紅點 有關的逐漸像是相同的部件而不是物理距離。
     最後飛機被分為:機翼、渦輪、機身…等各部件。

     在這裡的原始檔案可能是 .ply 或是 .off 都可以
     原理就是把頂點的 x,y,z 拿出來去做部件分割

     然後我們就會把被語義分割出來的各部件拿去做訓練,這樣就可以取得更好的結果。
     (譬如說有些機掰的倒三角翼飛機就不是乖乖的長這樣,但我們可以辨識成飛機。)

     你會問為什麼飛機兩邊的翼明明絕對位置不一樣,還能訓練出來?

     因為其中利用到 NLP 的句子的語義分割,類似"Ben是我"、"我是Ben"
     為同義句,在數學中就是 幾何變換 geometric transformation)

     可以寫矩陣轉換過去,至於怎麼寫就那又是一門學問了
     先交給我們電信仔就行惹 ლ(´ڡ`ლ)
     
     有時間再來談談實作,或許先從怎麼 initial data 開始是不錯的選擇?

  • 自己寫全景處理程式 之 在 python 下 把 opencv 裝起來

    前情提要:

    中興煙火王子開的影像處理課,要我們自己手寫全景拼接三張圖片
    苦於實驗室配發的電腦開 matlab 開不起來,只好用 opencv 做

    python 下裝  opencv 有兩種方法,第一種是下 pip 或 conda 指令;第二種是去載.whl

    不過我用這台下 pip 裝不起來,本人認為 conda 邪教,所以在這邊我們要去載.whl

    什麼是 .whl 檔?

    就是一個給 python 吃的壓縮包,有點 .gz 的感覺

    通常只要下 pip install XXX.whl 就能裝起來了
    (但是 pytorch、PCL 例外)

    網址:https://pypi.org/project/opencv-python/#files

    裝完了 你好棒棒噢

    好棒棒個屁_(:3 」∠ )_

    因為全景處理要用 SIFT 或是 SURF 演算法

    所以我們要裝另外一個 DLC

    opencv-contrib-python
    如果不裝,call SURF 與 SIFT fun.的時候就會出現:
    cv2.cv2' has no attribute 'xfeatures2d'
    所以請下 
    
    pip install opencv-contrib-python
    
    
    好 恭喜你完成了全景的第一步 σ`∀´)σ
  • 【論文導讀】Deep Closest Point: Learning Representations for Point Cloud Registration(理論篇)

    這是一篇今年五月八號才發的文章,
    發表在計算機視覺最猛的 CVPR 期刊,文章來自大神集散地 MIT

    內容大抵是在講 Deep Closest Point(DCP),
    也就是修正迭代最近點(ICP)的點雲對齊算法。

    Abstract 說了:這篇文章是要利用 DCP 解決 ICP 的 Local optimal 問題

    什麼是 Local optimal 呢?

    利用爬山演算法(Hill-Climbing Algorithm)來解釋:

    借用別人的圖

    來自 www.itread01.com/content/1544182326.html

    就是當搜索點從 C 開始搜尋最高點時,A點會被認為最佳解。
    但 A點 並不一定是全域最佳解(Global optimal

    讓我們來看看為什麼 DCP 可以解決 Local optimal 問題

    首先看到 DCP 的結構圖

    X 與 Y 是同一張點雲圖,但 Y 被做過 「旋轉」 及 「平移」
    X = {x1, . . . , xi
    , . . . , xN } ⊂ R3 
    Y = {y1
    , . . . , yj
    , . . . , yM} ⊂ R3 
    這兩行分別表示 X 與 Y 點雲 的 "點集合"
    作者用了兩個網路來擷取特徵值並比較
    一個是她自己幹的 DGCNN(PointNet改良版)、一個則是 PointNet
    簡單的來說,為什麼 DGCNN 會能夠解決 Local optimal 的問題,要從 DGCNN 的結構來看。
    (欲看一個立委如何做立委,丟係愛看伊怎樣做立委。)
    (DGCNN(上圖)、PointNet(下圖))
    我們可以觀察到 DGCNN 與 PointNet 的架構 只差在 DGCNN 把 PointNet 的 MLP 單元置換掉成 
    什麼是 EdgeConv?
    EdgeConv 就是 取一點 對鄰近的"K"個點做 Convolution ,這樣就能得到那個區域的特徵。
    (KNN)
    得到 Local 特徵的情況下
    我們拉回 DGCNN 的 DG(Dynamic Graph)
    為什麼 DGCNN 能夠解決 Local optimal 是因為每次計算下一層特徵的時候都會重新計算,
    像這樣:
    由右至左是計算次數的多寡,能看見經過多次計算後,
    局部特徵的關係會越來越像圖形中其他同樣特徵,物理距離卻比較遠的部分。
    所以我們得到局部特徵 
    FX={x1L,x2L,, 

    把這兩組特徵塞進 Transformer 裡面


    NLP 的部份請參考我寫的這篇文章
    下一篇即將進入實作