利用Python多處理庫(kù)處理3D數(shù)據(jù)詳解
今天我們將介紹處理大量數(shù)據(jù)時(shí)非常方便的工具。我不會(huì)只告訴您可能在手冊(cè)中找到的一般信息,而是分享一些我發(fā)現(xiàn)的小技巧,例如tqdm與 multiprocessing?imap??一起使用、并行處理檔案、繪制和處理 3D 數(shù)據(jù)以及如何搜索如果您有點(diǎn)云,則用于對(duì)象網(wǎng)格中的類(lèi)似對(duì)象。?
那么我們?yōu)槭裁匆笾诓⑿杏?jì)算呢?如今,如果您處理任何類(lèi)型的數(shù)據(jù),您可能會(huì)面臨與“大數(shù)據(jù)”相關(guān)的問(wèn)題。每次我們有不適合 RAM 的數(shù)據(jù)時(shí),我們都需要一塊一塊地處理它。幸運(yùn)的是,現(xiàn)代編程語(yǔ)言允許我們生成在多核處理器上完美運(yùn)行的多個(gè)進(jìn)程(甚至線程)。(注意:這并不意味著單核處理器不能處理多處理。? 這是關(guān)于該主題的堆棧溢出線程。)
今天,我們將嘗試處理經(jīng)常發(fā)生的計(jì)算網(wǎng)格和點(diǎn)云之間距離的 3D 計(jì)算機(jī)視覺(jué)任務(wù)。例如,當(dāng)您需要在所有可用網(wǎng)格中找到定義與給定點(diǎn)云相同的 3D 對(duì)象的網(wǎng)格時(shí),您可能會(huì)遇到此問(wèn)題。
我們的數(shù)據(jù)由??.obj???存儲(chǔ)在??.7z??存檔中的文件組成,這在存儲(chǔ)效率方面非常出色。但是當(dāng)我們需要訪問(wèn)它的確切部分時(shí),我們應(yīng)該努力。在這里,我定義了包裝 7-zip 存檔并提供底層數(shù)據(jù)接口的類(lèi)。
類(lèi) Archive7z(基礎(chǔ)):
def __init__ ( self , file , password = None ):
# ...
自我。文件={}
# ...
對(duì)于信息的文件。文件:
#創(chuàng)建一個(gè)知道磁盤(pán)位置的ArchiveFile實(shí)例
file = ArchiveFile ( info , pos , src_pos , folder , self , maxsize = maxsize )
# ...
自我。文件。追加(文件)
# ...
自我。文件映射。更新([(X。文件名,X)為X的自我。文件])
#從files_map字典返回ArchiveFile的方法
def getmember ( self , name ):
if isinstance ( name , ( int , long )):
嘗試:
回歸自我。文件[名稱(chēng)]
除 了 IndexError:
返回?zé)o
回歸自我。文件映射。獲取(名稱(chēng),無(wú))
類(lèi) Archive7(基礎(chǔ)):
定義讀取(自我):
# ...
對(duì)于水平,編碼器在枚舉(自我。_folder。編碼器):
# ...
#獲取解碼器并解碼底層數(shù)據(jù)
data = getattr ( self , decoder ) ( coder , data , level , num_coders )
返回?cái)?shù)據(jù)
這個(gè)類(lèi)幾乎不依賴(lài)??py7zlib???包,它允許我們?cè)诿看握{(diào)用get方法時(shí)解壓縮數(shù)據(jù)并為我們提供存檔中的文件數(shù)。我們還定義了??__iter__??這將幫助我們map像在可迭代對(duì)象上一樣在該對(duì)象上啟動(dòng)多處理。
您可能知道,可以創(chuàng)建一個(gè) Python 類(lèi),從中可以實(shí)例化可迭代對(duì)象。該類(lèi)應(yīng)滿足以下條件:覆蓋??__getitem__???返回??self???和??__next__???返回后續(xù)元素。我們絕對(duì)遵守這條規(guī)則。
上面的定義為我們提供了遍歷存檔的可能性,但 它是否允許我們 并行隨機(jī)訪問(wèn)內(nèi)容,這是一個(gè)有趣的問(wèn)題,我在網(wǎng)上沒(méi)有找到答案,但我們可以研究源代碼??py7zlib??并嘗試自己回答。
在這里,我提供了來(lái)自pylzma的代碼片段:
類(lèi) Archive7z(基礎(chǔ)):
def __init__ ( self , file , password = None ):
# ...
自我。文件={}
# ...
對(duì)于信息的文件。文件:
#創(chuàng)建一個(gè)知道磁盤(pán)位置的ArchiveFile實(shí)例
file = ArchiveFile ( info , pos , src_pos , folder , self , maxsize = maxsize )
# ...
自我。文件。追加(文件)
# ...
自我。文件映射。更新([(X。文件名,X)為X的自我。文件])
#從files_map字典返回ArchiveFile的方法
def getmember ( self , name ):
if isinstance ( name , ( int , long )):
嘗試:
回歸自我。文件[名稱(chēng)]
除 了 IndexError:
返回?zé)o
回歸自我。文件映射。獲取(名稱(chēng),無(wú))
類(lèi) Archive7z(基礎(chǔ)):
定義讀取(自我):
# ...
對(duì)于水平,編碼器在枚舉(自我。_folder。編碼器):
# ...
#獲取解碼器并解碼底層數(shù)據(jù)
data = getattr ( self , decoder ) ( coder , data , level , num_coders )
返回?cái)?shù)據(jù)
在代碼中,您可以看到在從存檔中讀取下一個(gè)對(duì)象期間調(diào)用的方法。我相信從上面可以清楚地看出,只要同時(shí)多次讀取存檔,就沒(méi)有理由阻止存檔。
接下來(lái),我們快速介紹一下什么是網(wǎng)格和點(diǎn)云。
首先,網(wǎng)格是頂點(diǎn)、邊和面的集合。頂點(diǎn)由空間中的(x,y,z) 坐標(biāo)定義并分配有唯一編號(hào)。邊和面是相應(yīng)的點(diǎn)對(duì)和三元組的組,并用提到的唯一點(diǎn) id 定義。通常,當(dāng)我們談?wù)摗熬W(wǎng)格”時(shí),我們指的是“三角形網(wǎng)格”,即由三角形組成的表面。使用??trimesh??庫(kù)在 Python 中使用網(wǎng)格要容易得多。例如,它提供了一個(gè)接口來(lái)加載??.obj??內(nèi)存中的文件。要在??jupyter notebook??一個(gè)3D 對(duì)象中顯示和交互,可以使用??k3d??庫(kù)。
所以,用下面的代碼片段我回答這個(gè)問(wèn)題:“你怎么繪制??trimesh???的對(duì)象??jupyter???有??k3d???”
進(jìn)口飾面 導(dǎo)入k3d 使用 open ( w. /data/meshes/stanford-bunny, obj")作為 f : bunny_mesh =網(wǎng)眼。力口載(f , 'obj') 情節(jié)=k3d。情節(jié)() 網(wǎng)格= k3d。網(wǎng)格 (bunny_mesh . vertices> bunny_mesh . faces) 繪圖上網(wǎng)格 情節(jié)。顯示。

其次,點(diǎn)云是表示空間中對(duì)象的 3D 點(diǎn)數(shù)組。許多 3D 掃描儀生成點(diǎn)云作為掃描對(duì)象的表示。出于演示目的,我們可以讀取相同的網(wǎng)格并將其頂點(diǎn)顯示為點(diǎn)云。
?進(jìn)口飾面 導(dǎo)入k3d 使用 open ( w. /data/meshes/stanford-bunny, obj")作為 f : bunny_mesh =網(wǎng)眼。力口載(f , 'obj') 情節(jié)=k3d。情節(jié)() 云=k3d。點(diǎn)(bunny_mesh . vertices , point_size = 0. 0001 , shader = "flat") 情節(jié)+=云 情節(jié)。顯示。 ?
?
k3d繪制的點(diǎn)云
如上所述,3D 掃描儀為我們提供了一個(gè)點(diǎn)云。假設(shè)我們有一個(gè)網(wǎng)格數(shù)據(jù)庫(kù),我們想在我們的數(shù)據(jù)庫(kù)中找到一個(gè)與掃描對(duì)象對(duì)齊的網(wǎng)格,也就是點(diǎn)云。為了解決這個(gè)問(wèn)題,我們可以提出一種簡(jiǎn)單的方法。我們將從我們的檔案中搜索給定點(diǎn)云的點(diǎn)與每個(gè)網(wǎng)格之間的最大距離。如果??1e-4??某些網(wǎng)格的距離更小,我們將認(rèn)為該網(wǎng)格與點(diǎn)云對(duì)齊。
?最后,我們來(lái)到了多處理部分。請(qǐng)記住,我們的存檔中有大量文件可能無(wú)法放在一起放在內(nèi)存中,因?yàn)槲覀兏矚g并行處理它們。為了實(shí)現(xiàn)這一點(diǎn),我們將使用 ??multiprocessing Pool???,它使用??map???或??imap/imap_unordered???方法處理用戶定義函數(shù)的多次調(diào)用。??map???和??imap???影響我們的區(qū)別在于,??map???在將其發(fā)送到工作進(jìn)程之前將可迭代對(duì)象轉(zhuǎn)換為列表。如果存檔太大而無(wú)法寫(xiě)入 ??RAM???,則不應(yīng)將其解壓縮到 ??Python ??列表中。換句話說(shuō),兩者的執(zhí)行速度是相似的。
[加載網(wǎng)格:pool.map w/o manager] 4 個(gè)進(jìn)程的池經(jīng)過(guò)時(shí)間:37.213207403818764 秒 [加載網(wǎng)格:pool.imap_unordered w/o manager] 4 個(gè)進(jìn)程的池經(jīng)過(guò)時(shí)間:37.219303369522095 秒
上面您可以看到從適合內(nèi)存的網(wǎng)格檔案中簡(jiǎn)單讀取的結(jié)果。
更進(jìn)一步??imap???:讓我們討論如何實(shí)現(xiàn)我們的目標(biāo),即找到靠近點(diǎn)云的網(wǎng)格。這是數(shù)據(jù)。我們有 5 種來(lái)自斯坦福模型的不同網(wǎng)格。我們將通過(guò)向斯坦福兔子網(wǎng)格的頂點(diǎn)添加噪聲來(lái)模擬 3D 掃描。
將numpy導(dǎo)入為np
A numpy。隨機(jī) 導(dǎo)入 defaulting
def normalize_pc (點(diǎn)):
點(diǎn)額=點(diǎn)額-點(diǎn)額。平均值(軸=0)[無(wú),:]
分布=np。linalg<>范數(shù)(點(diǎn),軸=1) scaled_points =點(diǎn) / dists中。最大值。 返回 scaled_points
def load_bunny_pc ( bunny_path ):
標(biāo)準(zhǔn)差=l?-3
使用 open ( bunny_path )作為 f : bunny_mesh = load_mesh ( f )
#標(biāo)準(zhǔn)化后云
scaled_bunny = normalize_pc ( bunny_mesh . vertices )
#向點(diǎn)云添加一些噪聲 rng = defaulting ()
噪音=rng。正常(0. 0 , STD , scaled_bunny . shape ) 畸變兔子=縮放兔子+噪聲
返回 di st ort ed_bunny
當(dāng)然,我們之前在下面將點(diǎn)云和網(wǎng)格頂點(diǎn)歸一化,以在 3D 立方體中縮放它們。
要計(jì)算點(diǎn)云和網(wǎng)格之間的距離,我們將使用??igl??。為了完成,我們需要編寫(xiě)一個(gè)函數(shù)來(lái)調(diào)用每個(gè)進(jìn)程及其依賴(lài)項(xiàng)。讓我們用下面的代碼片段來(lái)總結(jié)一下。
導(dǎo)入迭代工具
導(dǎo)入時(shí)間
將 numpy 導(dǎo)入為 np
nwnpyo 隨機(jī)導(dǎo)入 default rng
面以1 口口如 進(jìn)進(jìn)從
A多處理導(dǎo)入池
de£ load_mesh ( obj_file ):
目二 trimesh。力口載(obj_file , ' obj')
返回網(wǎng)格
def get_max__dist ( basjmesh , point_cloud ):
distance_sq , mesh_face__indexes , _ = igl。point_mesh_squared_distance (
點(diǎn)云,
basjmesho 頂點(diǎn),
basjmesho 面孔
)
返回distancjsq。最大值0
def 1 oad_mesh__get_di stance ( args ):
obj_file , point__cloud = args [ 0 ]/ args [ 1 ]
網(wǎng)格二 load_mesh ( obj_file )
網(wǎng)。頂點(diǎn)=RormaliNe_pc (網(wǎng)格。頂點(diǎn))
max_dist = get_max_dist (網(wǎng)格,點(diǎn)云)
返回 max__dist
de£ read_meshes__get__di stances_pool__imap ( archive_path , point_cloud , nwn_proc , nwn_i terations ):
#在疝中進(jìn)行向格“理
elapsed__time =[]
為一在 范圍(nujn-i terati ons ):
歸檔二 MeshesArchive (ARCHIVE-PATH)
池二池(nwn_proc )
開(kāi)始=時(shí)間。時(shí)間0
導(dǎo)致=名單(tqdm(池。IMAP (
1 o ad_m e sh__ge t_di s t anc e ,
zip (存檔,itertoolso 重復(fù)(point_cloud)),
),總計(jì)=len辱檔)))
池。關(guān)閉0
池。加入o
結(jié)束=時(shí)間。時(shí)間0
elapsed time o追加(結(jié)束一開(kāi)始)
print ( F [Process meshes: pool, imap] {num_proc}個(gè)進(jìn)程的池經(jīng)過(guò)的時(shí)間:{np. array (elapsed_time). mean()} sec )
對(duì)于 name , di st in zip ( archive . namesjist , result ): 打印(r{name} {dist}")
返回結(jié)果
如果 _name_ ==
bunny_path = /data/meshes/stanford-bunny, obj"
archive_path = /data/meshes. 7zff
nwn_proc = 4
num_iterations = 3
point__cloud - load__bunny_pc ( bunny_path )
read_meshes__get__di stances_pool_no_manager__imap ( archive_path ,point_cloud , nwn_proc , num.
iterations )
這??read_meshes_get_distances_pool_imap是一個(gè)中心函數(shù),其中完成以下操作:??
- MeshesArchive??并??multiprocessing.Pool??初始化
- ??tqdm?? 用于觀察池進(jìn)度,并手動(dòng)完成整個(gè)池的分析
- 執(zhí)行結(jié)果的輸出
請(qǐng)注意我們?nèi)绾蝹鬟f參數(shù)以??imap???從??archive???和??point_cloud???使用??zip(archive, itertools.repeat(point_cloud))???. 這允許我們將點(diǎn)云數(shù)組粘貼到存檔的每個(gè)條目上,避免轉(zhuǎn)換??archive??為列表。
執(zhí)行結(jié)果如下:
100%|########################################### #####################| 5/5 [00:00<00:00, 5.14it/s]
100%|########################################### #####################| 5/5 [00:00<00:00, 5.08it/s]
100%|########################################### #####################| 5/5 [00:00<00:00, 5.18it/s]
[進(jìn)程網(wǎng)格:pool.imap w/o manager] 4 個(gè)進(jìn)程的池經(jīng)過(guò)時(shí)間:1.0080536206563313 秒
犰狳.obj 0.16176825266293382
野獸.obj 0.28608649819198073
牛.obj 0.41653845909820164
現(xiàn)貨.obj 0.22739556571296735
stanford-bunny.obj 2.3699851136074263e-05
我們可以注意到斯坦福兔子是最接近給定點(diǎn)云的網(wǎng)格。還可以看出,我們沒(méi)有使用大量數(shù)據(jù),但我們已經(jīng)證明,即使我們?cè)诖鏅n中有大量網(wǎng)格,該解決方案也能奏效。
多處理使數(shù)據(jù)科學(xué)家不僅在 3D 計(jì)算機(jī)視覺(jué)中而且在機(jī)器學(xué)習(xí)的其他領(lǐng)域中都取得了出色的表現(xiàn)。理解并行執(zhí)行比在循環(huán)內(nèi)執(zhí)行快得多是非常重要的。差異變得顯著,尤其是在正確編寫(xiě)算法時(shí)。大量數(shù)據(jù)揭示了如果沒(méi)有關(guān)于如何使用有限資源的創(chuàng)造性方法就無(wú)法解決的問(wèn)題。幸運(yùn)的是,Python 語(yǔ)言及其廣泛的庫(kù)集幫助我們數(shù)據(jù)科學(xué)家解決了這些問(wèn)題。
到此這篇關(guān)于利用Python多處理庫(kù)處理3D數(shù)據(jù)詳解的文章就介紹到這了,更多相關(guān)Python處理3D數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python基于動(dòng)態(tài)規(guī)劃算法計(jì)算單詞距離
這篇文章主要介紹了Python基于動(dòng)態(tài)規(guī)劃算法計(jì)算單詞距離的方法,實(shí)例分析了Python動(dòng)態(tài)規(guī)劃算法的實(shí)現(xiàn)與使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
一文帶你掌握Python內(nèi)置reversed函數(shù)的使用
Python作為一門(mén)強(qiáng)大的編程語(yǔ)言,提供了許多內(nèi)置函數(shù)來(lái)處理各種數(shù)據(jù)結(jié)構(gòu)和對(duì)象,本文將詳細(xì)探討reversed函數(shù)的用法、示例代碼以及實(shí)際應(yīng)用場(chǎng)景,需要的可以參考下2024-01-01
python 自動(dòng)刷新網(wǎng)頁(yè)的兩種方法
這篇文章主要介紹了python 自動(dòng)刷新網(wǎng)頁(yè)的兩種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
python3調(diào)用百度翻譯API實(shí)現(xiàn)實(shí)時(shí)翻譯
這篇文章主要為大家詳細(xì)介紹了python3調(diào)用百度翻譯API,實(shí)現(xiàn)實(shí)時(shí)翻譯,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08
python中windows鏈接linux執(zhí)行命令并獲取執(zhí)行狀態(tài)的問(wèn)題小結(jié)
這篇文章主要介紹了python中windows鏈接linux執(zhí)行命令并獲取執(zhí)行狀態(tài),由于工具是pyqt寫(xiě)的所以牽扯到用python鏈接linux的問(wèn)題,這里記錄一下一些碰到的問(wèn)題,需要的朋友可以參考下2022-11-11

