久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

博客專欄

EEPW首頁 > 博客 > 結構光相移法-多頻外差原理+實踐(上)

結構光相移法-多頻外差原理+實踐(上)

發布人:計算機視覺工坊 時間:2020-12-22 來源:工程師 發布文章

01 相移法原理

02 雙頻外差原理

03 多頻率外差原理

04 代碼實踐

01 相移法原理

結構光法原理其實是跟雙目視覺一樣的,都是要確定對應“匹配點”,利用“視差”三角關系計算距離,所不同的是:

  • 雙目視覺通過“被動”匹配唯一特征點

  • 相移法作為結構光法中的一種,通過主動投影多副相移圖案來標記唯一位置。

說明:雖然大多數結構光系統是單目的,但我們可以將其“雙目”的,因為投影儀可以看做是一個“逆向”的相機,明白了這點,對于結構光系統一些公式推導就容易很多。

對于“雙目”系統來說,最重要的工作是通過唯一標記來標記某一點,假設我們只投射一個周期的數據,我們從投影儀投出去的光柵公式如下:

17.png

其中:

16.png

比如說四步相移公式:

15.png

我們主要關心的是求解出相位主值,因為它對每個像素點是唯一的,假設我們從相機中獲取了這四副圖像,那怎么反過來求解相位主值?

需要說明的是,雖然這個公式對整副相移圖像的,但是這公式對每個像素都是獨立的,所以即使我們拿從相機拍攝到經過調制變形的圖像來求解,依然可以得到單個像素點唯一的相位主值。

聯立4個方程,得到:

14.png

無論:

  • 哪臺相機

  • 拍攝到什么圖像

我們要得到某個像素點的唯一“標記”,也就是這個相位主值,代回這個公式即可,都可以得到唯一值。得到了唯一值,建立匹配關系,就可以利用三角公式進行重建。

13.png12.png

其中:橫坐標為任意一行的像素,這張圖中使用周期為11的像素條紋作為正弦光柵。

02 雙頻外差原理

解決的方法有很多,分為空域和時域展開兩種:

  • 空域展開:依靠空間相鄰像素點之間的相位值恢復絕對相位,如果重建表面不連續,則出現解碼錯誤。

  • 時域展開:將每個像素點的相位值進行獨立計算,有格雷碼和多頻外差兩種,其中格雷碼方法對物理表面問題敏感,并且多投影的圖并不能用來提升精度,多頻外差精度更高。

當然目前還有更多精度更高、效率更快的相位展開方法,在這里暫時不予討論,這里主要討論多頻外差原理。

多頻外差原理:通過多個不同頻率(周期)正弦光柵的相位做差,將小周期的相位主值轉化為大周期的相位差,從而使得相位差信號覆蓋整個視場,然后再根據相位差來得到整副圖像的絕對相位分布。

這里以雙頻外差為例,原理如圖1所示:

11.png10.png

注:通常我們說的相位函數的周期,代表的是一個周期正弦函數所占的像素單位個數。

03 多頻率外差原理

9.png8.png

其可以完成整個視場的無歧義標記。

04 代碼實踐

7.png

依據相移法得到的包裹相位圖如下圖所示,不同顏色代表不同頻率的相位主值:

6.png

我們進行疊加后的效果:

5.png

在這里,我們可以看到,由兩個周期小的相位可以合成一個周期更大的編碼圖案。

18.png

4.png

其中:

3.png

明白了原理,我們來代碼實踐一下,需要注意的是,求解出來的相位我們要進行歸一化到區間操作:

import numpy as np

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 用來正常顯示中文標簽

plt.rcParams['axes.unicode_minus'] = False    # 用來正常顯示負號

def phase_simulation(WIDTH, T1, T2, T3):

    pha1, pha2, pha3 = np.zeros(shape=WIDTH), np.zeros(shape=WIDTH), np.zeros(shape=WIDTH)

    t1, t2, t3 = 1, 1, 1

    for idx in range(WIDTH):

        if t1 > T1: t1 = 1  # 重置一下

        pha1[idx] = (t1 / T1) * 2 * np.pi

        if t2 > T2: t2 = 1

        pha2[idx] = (t2 / T2) * 2 * np.pi

        if t3 > T3: t3 = 1

        pha3[idx] = (t3 / T3) * 2 * np.pi

        t1 += 1; t2 += 1; t3 += 1

    return pha1, pha2, pha3

def parse_phase(pha1, pha2, T1, T2):

    pha12 = np.zeros_like(pha1)

    # 計算Delta(如果滿足條件,輸出左側,否則右側)

    pha12 = np.where(pha1 >= pha2, pha1 - pha2, pha1 - pha2 + 2 * np.pi)

    # # 跟下面這段代碼等價

    # for idx in range(0, pha12.shape[0]):

    #     if pha1[idx] >= pha2[idx]:

    #         pha12[idx] = pha1[idx] - pha2[idx]

    #     else:

    #         pha12[idx] = pha1[idx] - pha2[idx] + 2 * np.pi

    T12 = T1 * T2 / (T2 - T1)

    # 方法1

    pha12 = T2 / (T2 - T1) * pha12

    # # 方法2

    # m = np.round((T2 / (T2 - T1) * pha12 - pha1) / (2 * np.pi))

    # pha12 = 2 * np.pi * m + pha12

    # 歸一化到[0,2π]

    min_value, max_value = np.min(pha12), np.max(pha12)

    pha12 = (pha12 - min_value) * (2 * np.pi / (max_value - min_value))

    return pha12, T12

if __name__ == '__main__':

    # 視場寬度

    WIDTH = 854

    # 條紋周期

    T1 = 11

    T2 = 12

    T3 = 13

    pha1, pha2, pha3 = phase_simulation(WIDTH, T1, T2, T3)

    X = np.arange(0, WIDTH)

    plt.plot(X, pha1, label="pha1")

    plt.plot(X, pha2, label="pha2:")

    plt.plot(X, pha3, label="pha3")

    plt.title("相移主值圖(仿真)")

    plt.xlabel("像素")

    plt.ylabel("w/rad")

    plt.legend()

    plt.show()

    # 解相位

    pha12, T12 = parse_phase(pha1, pha2, T1, T2)

    pha23, T23 = parse_phase(pha2, pha3, T2, T3)

    pha123, T123 = parse_phase(pha12, pha23, T12, T23)

    plt.plot(X, pha12, label="pha12")

    plt.plot(X, pha23, label="pha23")

    plt.plot(X, pha123, label="pha123")

    plt.title("解出絕對相位")

    plt.xlabel("像素")

    plt.ylabel("w/rad")

    plt.legend()

    plt.show()

2.png1.png

可以看出,最終解出的絕對相位線單調遞增,每個相位值時唯一的,雖然在一些交界處會有些許誤差。

結構光多頻外差的原理很簡單,而精度這塊,其實很大程度依賴于標定、高反處理這些地方。這一期內容將分為上下兩期,為了便于理解,不再講述更多內容,更多我們下一期再講!怎么拿實際投影拍攝到的光柵圖片來還原絕對相位!

備注:作者也是我們「3D視覺從入門到精通」特邀嘉賓:一個超干貨的3D視覺學習社區

本文僅做學術分享,如有侵權,請聯系刪文。

*博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



關鍵詞:

相關推薦

技術專區

關閉