系列篇|結構光——格雷碼解碼方法

做者:書涵
Date:2020-03-16
來源:系列篇|結構光——格雷碼解碼方法
格雷碼是一種特殊的二進制碼,在結構光三維視覺中,經常被用於編碼。比起咱們常見的二進制碼,格雷碼具備相鄰數字的編碼只有一位不一樣的優勢,這個優勢對於解碼而言十分重要,能夠減小光解碼的錯誤率。下面咱們能夠看下如何對結構光用格雷碼編碼,並如何對編碼的結構光進行解碼
以5位格雷碼爲例,5位格雷碼能夠對32個像素位置進行編碼,由以前的文章能夠知道,咱們在計算結構光三維重建時,只須要對結構光圖片的一個方向編碼,以常見的列格雷碼爲例,如圖所示是5位列格雷碼編碼圖片集。
圖中咱們對每一個像素點進行了格雷碼編碼,每一張圖片都表明了格雷碼的某一位,以圖片第1列爲例,其格雷碼編碼爲00001,則前4張圖片中第一列的的格雷碼編碼的條紋都是黑色,表明0,而最後一張圖片第一列的格雷碼編碼是白色,表明1.
格雷碼的解碼很簡單,只要把投影的格雷碼結構光再還原回十進制數字,咱們就能知道相機中的像素點(uc,vc)對應的是投影圖片的哪一列(up)了。想要獲得一個好的三維重建結果,主要是對相機捕捉到的結構光進行準確的二值化操做,使得相機圖片中每一個像素點都可以正確解碼。
常見的二值化操做有不少,最簡單的是設一個全局灰度閾值,對灰度值高於閾值的像素點置1,對灰度值低於閾值的像素點置0。 或者利用局部自適應閾值對圖片進行二值化操做等·。常見的利用每一個像素點周邊灰度信息的二值化操做,每每不可以知足格雷碼結構光解碼的二值化需求。由於使用結構光的環境每每是未知且複雜的。好比一樣的結構光光強照在黑色物體表面的亮度比照射在白色物體表面的亮度要低。這意味着一樣的光條紋在不一樣物體上獲取的灰度值不一樣。因爲不能提早預知環境中的物體表面信息,僅僅靠簡單的利用像素點及其週週圍灰度值的分佈得出該像素點當前是來自結構光的亮條紋仍是暗條紋是及其不許確的。
雖然因爲環境光,以及物體表面材質的緣由,一幅圖像中像素的亮度(灰度值)一般是不均勻的,沒法直接利用一張圖片呈現的灰度信息對結構光解碼,可是咱們能夠利用結構光系列圖片來幫助獲取像素點當前是亮條紋仍是暗條紋的信息。以上圖的格雷碼編碼爲例,一個5位的格雷碼編碼須要投影5張結構光圖片,假設有一個編碼爲 11011的格雷碼條紋打在物體表面上,,在連續投影的5張格雷碼圖片中,物體表面被編碼照射的位置既經歷過暗條紋(編碼爲0)又經歷過亮條紋(編碼爲1)。不過因爲每張格雷碼編碼圖片的光源編碼不一樣,並且結構光光源在物體表面上造成的漫反射不一樣,當結構光編碼圖片不同時,即便是一樣經歷亮條紋照射,該位置的亮度(灰度值)也是不一樣的。總的來講,對於同一個位置,能夠近似認爲其被亮條紋照射到的亮度老是高於其被暗條紋照射到的亮度。那麼對於一個像素點在一張圖片中的二值化能夠用以下方法。
首先找到像素點在系列格雷碼圖片中最大的灰度值,記爲Imax,並找到該像素點在系列格雷碼圖片中最小的灰度值,記爲Imin。對於每張圖片,咱們能夠這樣計算,
In = (I-Imin)/(Imax-Imin)
其中I是該像素點在當前圖片下的亮度,In能夠看作是被歸一化(normalize)後的灰度值,顯然In的取值範圍是[0,1]的。由上述公式能夠看出,若是該像素點當前經歷的是暗條紋,其值會接近最小的灰度值,In接近0,反之,In會接近1, 因而咱們能夠設計一個閾值,好比0.5,即當In大於0.5時,咱們認爲其值是偏亮的,此時像素經歷的是亮條紋編碼,反之,若是In小於0.5時,該像素此時經歷的是暗條紋編碼。值得注意的是,這個方法對於編碼全爲0的點,或者編碼全爲1的點,會有影響,由於編碼全0的點和編碼全1的點不會同時經歷明暗變化。解決方法是避開這個編碼,或者額外投圖片讓全部編碼位置都能經歷全0或者全1的過程。
上述方法的前提是近似認爲被亮條紋照射到的亮度老是高於該位置被暗條紋照射到的亮度。實際上這個假設成立的前提是物體間沒有漫反射,以及投影投射的光之間不會互相干擾。在一些特殊的位置,是有可能物體在經歷亮條紋時其亮度值比其經歷暗條紋時要暗。由於每張格雷碼圖片整體的光分佈是不同的,如上圖的第一張和最後一張,第一張光主要分佈在右邊半邊,而最後一張條紋光很細,是明暗相間的。不同的格雷碼圖片的光強分佈,會形成物體間漫反射的光強不同,致使其經歷暗條紋時周圍物體間漫反射到的光遠大於結構光光源發出來的光。實際上這是有可能的,好比該像素點處於某個物體對的陰影部分,通常狀況下這樣的點是沒有光變化的,由於結構光自己沒法直射到該位置,可是由於其周邊物體漫反射的光有可能致使這個位置的光強發生劇烈變化。出現該位置經歷暗條紋時光強比經歷亮條紋時還要強。爲了解決這類特殊的點,論文[2] 給出其思路以下:
如圖所示,咱們能夠對每幅格雷碼編碼的條紋作一個逆向圖,把原來編碼條紋中的1的位置變爲0,0的位置成1。這樣咱們把每一幅編碼圖片變成了一對編碼圖. 咱們能夠經過比較一對編碼圖中每一個像素的灰度差值來判斷其值爲0仍是爲1。這個很容易理解,由於若是編碼是亮條紋,則其逆向編碼是暗條紋,則圖片上編碼是亮條紋的時候對應的點比編碼是暗條紋(逆向)的時候對應的像素點更亮,即灰度值更高。反之亦然, 這樣就能夠簡單地對相機圖片上的結構光條紋解碼了。
這個思路很簡單,對大部分相機圖片上的點,這樣的解碼效果就足夠好了。可是仍然不能解決上述提到的問題。對於部分點,其經歷暗條紋時仍舊可能比經歷亮條紋時灰度值要更高。因而論文【2】在上述思路上,再增長了一部分想法,若是咱們能求出當前灰度值中可能的來自結構光直接光源的成分的比例,就能夠幫助咱們辨別出該點是否經歷暗條紋或者亮條紋。具體計算規則以下:
其中p指像素座標,Lp+ 是像素在格雷碼系列圖中灰度最大值,Lp-是像素在格雷碼系列圖中灰度最小值。Ld能夠看做是該像素點來自直接光源的灰度值,Lg能夠看做來自其餘光源(物體間漫反射和環境光)等的光源的灰度值。對於大部分狀況,顯然來自投影光的光強較強,Ld>Lg。可是對於部分點Ld<Lg, 好比處於物體陰影處的點,又好比處於周圍反光物體較多點(來自周圍反光太強了)。這部分點就是咱們要解決的點,經過下面的規則,能夠很好的解決點的二值化問題:
對每一個像素點p和其灰度值I,有以下二值化規則 其中m是一個比較小的常數閾值,I_inv是條紋結構光的逆向圖。
  • I<m 該點的二值化認爲是不肯定點
  • Ld>Lg 且知足 I>I_inv 該點二值化爲1
  • Ld>Lg 且知足I <I_inv 該點二值化爲0
  • I<Ld 且知足I_inv>Lg 該點二值化爲0
  • I>Lg 且知足I_inv<Ld 該點二值化爲1
不符合以上全部條件的點爲不肯定點
有了以上的二值化方法,格雷碼的編碼和解碼都不是什麼太大的問題,解碼後能夠根據筆者以前文章提供的三維數據計算方法獲得較爲準確的物體三維信息。
在文章的最後,筆者想討論下爲何格雷碼編碼比通常的二進制編碼要好。咱們知道格雷碼最大的優勢是十進制相鄰數字編碼只相差一位。那爲何這樣就比普通二進制編碼好呢?咱們知道,解碼最容易出錯的點,每每是黑白相間的邊界點,相機拍攝到的黑白相間的邊界點每每是一個過渡灰度,很容易致使解碼錯誤,因此相鄰的數字間位數差異越多,其黑白相間的變化越多,天然出錯的機率也更大。對於這一點,其實有一個圖片很直觀感覺到,若是咱們對每一個像素進行格雷碼編碼,那麼不管多少位編碼,在其編碼的最後一張圖片上,條紋一般是很是細的,若是是普通二進制編碼,其最後一張細條紋圖片是每一個像素之間編碼都不同,對一幅圖片從左到右呈現010101…的變化,而若是用格雷碼編碼則會呈現0110011…的變化,明顯格雷碼編碼其投影條紋更粗,更不容易解碼出錯。
本文解碼方法參考論文:
[1] High-accuracy, high-speed 3D structured light imaging techniques and potential applications to intelligent robotics
[2] Robust Pixel Classification for 3D Modeling with Structured Light
相關文章
相關標籤/搜索