深度圖轉(zhuǎn)點(diǎn)云(2)—再略微優(yōu)化了下
最近回過頭優(yōu)化以前寫的代碼,還是不少地方能好好捯飭捯飭加快點(diǎn)速度
這段之前寫成博客的深度圖轉(zhuǎn)點(diǎn)云的代碼就是其中一個(gè)

由于B站文章投稿只能修改三次,而之前那篇已經(jīng)因?yàn)楦腻e(cuò)字用光了次數(shù)?
所以新開一篇寫寫
新代碼:
修改的是初始化的時(shí)候會(huì)用到的get_depth_vector()這個(gè)函數(shù)

用jyupyter notebook來測(cè)試的話,之前的函數(shù)用時(shí)將近7秒 而新函數(shù)用時(shí)0.5秒
校驗(yàn)兩個(gè)函數(shù)的得到的數(shù)據(jù)是否一致


舊算法
整體的流程并沒有改變,這里只重新簡(jiǎn)單地說一下
已知一個(gè)像素點(diǎn)(u,v)的深度值depth的情況下
點(diǎn)從畫面坐標(biāo)系到相機(jī)坐標(biāo)系可以用[u,v,depth]乘以相機(jī)內(nèi)參矩陣的逆矩陣

然后為了更快連續(xù)地計(jì)算多張深度圖,我們假設(shè)有一張深度圖,所有像素的深度值都為1
用循環(huán)計(jì)算其中所有像素的結(jié)果, 也就是遍歷圖片的像素坐標(biāo)(u,v),反復(fù)用[u,v,1]乘以相機(jī)的逆矩陣 保存得到的三維坐標(biāo)[x,y,1]
這時(shí)得到的[x,y,1]可以看成是一個(gè)方向向量
因?yàn)閮牲c(diǎn)確定一條直線?
光心以及像素點(diǎn)兩點(diǎn)確定了一個(gè)方向,所以無論depth值為多少,點(diǎn)都應(yīng)該在這個(gè)方向上
有了所有像素點(diǎn)的方向向量數(shù)組以后,只需要將新來的深度圖的depth乘以數(shù)組,便可以得到點(diǎn)云數(shù)組
而舊的get_depth_vector()函數(shù)就遍歷所有像素點(diǎn)的方式在計(jì)算方向向量

新算法
代碼中為了計(jì)算方便和速度,一直用了矩陣來計(jì)算變換
而畫面坐標(biāo)到相機(jī)坐標(biāo)系的變換也可以寫成以下形式,其中cx cy為光心坐標(biāo),fx fy為焦距,這些都包含在相機(jī)內(nèi)參矩陣中
z = depth
x = (u - cx) * z / fx
y = (v - cy) * z / fy
以x為例,在計(jì)算圖像中所有像素點(diǎn)的時(shí)候 式子右邊cx fx是固定值 u和z是變量
但由于我們計(jì)算假設(shè)所有像素點(diǎn)的深度值都為1,所以這時(shí)變量只剩下了 u
u圖像分辨率的寬,以代碼中的分辨率(960,720)的情況
那么?變量u 就是 0-959 的960個(gè)整數(shù)
那么可知 相應(yīng)的結(jié)果 x 也應(yīng)該只有 960種 ,對(duì)應(yīng)著960個(gè)u
同理 y應(yīng)該只有720種 結(jié)果 對(duì)應(yīng)著 720個(gè)v的量
所以我們并不需要遍歷一張圖像上的所有像素坐標(biāo),只需要計(jì)算出0~959 的u以及0~719的v的結(jié)果 然后將他們按照順序組合起來,便可以得到同之前一樣的結(jié)果
當(dāng)然,具體的實(shí)現(xiàn)為了計(jì)算速度 還是采用了矩陣計(jì)算的形式
首先根據(jù)圖像的分辨率我們構(gòu)建代表長(zhǎng)寬的豎數(shù)組和橫橫數(shù)組
為了保存結(jié)果[x,y,1]?,第三個(gè)維度為3
注意這里兩個(gè)數(shù)組的長(zhǎng)度都暫時(shí)為 u,因?yàn)閡>v 為了下一步計(jì)算的方便暫且都設(shè)置成大的這個(gè)數(shù)
接著遍歷0~959 ,通過[u,v,1]乘以相機(jī)逆矩陣得到對(duì)應(yīng)的 x 和y? ,存入剛才的兩個(gè)數(shù)組的對(duì)應(yīng)位置中
為了計(jì)算方便我們一并計(jì)算了960個(gè)y值,但是實(shí)際上只有720個(gè) 所以隊(duì)v_vector進(jìn)行切片取前720
接著對(duì)豎數(shù)組,此時(shí)為 720*1*3的v_vector,豎著復(fù)制960列
對(duì)橫數(shù)組,1*960*3的u_vector, 橫著復(fù)制720行
?復(fù)制之后兩者的shape都為 720*960*3
接著只要直接將兩組數(shù)據(jù)相乘,便可得到和舊函數(shù)一樣的結(jié)果
此時(shí) 對(duì)應(yīng)每個(gè)像素點(diǎn)上都會(huì) [x,1,1] * [1,y,1] = [x,y,1]
????????
如此一來 ,從之前遍歷所有點(diǎn) (720*960個(gè)點(diǎn)) 進(jìn)行[u,v,1]乘以相機(jī)矩陣逆計(jì)算的步驟
變成了現(xiàn)在只計(jì)算960次再通過numpy的復(fù)制 ,乘法融合 得到相同的結(jié)果