您的位置:首頁(yè) > 軟件教程 > 教程 > Spherical Voxelization

Spherical Voxelization

來(lái)源:好特整理 | 時(shí)間:2024-08-24 09:54:19 | 閱讀:75 |  標(biāo)簽: a T v VoxEL El Ri S C   | 分享到:

介紹了球面體素化的過(guò)程,包括重要的類(lèi)和方法,如ConvertToSphericalVoxel和spherical_voxel_optimized,詳細(xì)解釋了參數(shù)及其作用。球面體素化通過(guò)將點(diǎn)云轉(zhuǎn)換為球面坐標(biāo)系,利用自適應(yīng)采樣權(quán)重來(lái)平衡不同緯度區(qū)域的點(diǎn)密度,從而有效捕捉幾何特征。文中還提到C++綁定的s

Spherical Voxelization

  • 標(biāo)簽: voxelization
  • AI 摘要: 文檔介紹了球面體素化的過(guò)程,包括重要的類(lèi)和方法,如ConvertToSphericalVoxel和spherical_voxel_optimized,詳細(xì)解釋了參數(shù)及其作用。球面體素化通過(guò)將點(diǎn)云轉(zhuǎn)換為球面坐標(biāo)系,利用自適應(yīng)采樣權(quán)重來(lái)平衡不同緯度區(qū)域的點(diǎn)密度,從而有效捕捉幾何特征。文中還提到C++綁定的sv.compute函數(shù),負(fù)責(zé)體素特征的計(jì)算與填充,確保在特征計(jì)算中考慮鄰近體素的信息。
  • 最相關(guān)鏈接: https://github.com/CVLAB-Unibo/compass

Spherical Voxelization

參考鏈接:

  • CVLAB-Unibo/compass: Repository containing the code of "Learning to Orient Surfaces by Self-supervised Spherical CNNs". (github.com)
  • jonkhler/s2cnn: Spherical CNNs (github.com)
  • qq456cvb/PRIN: Pointwise Rotation-Invariant Network (AAAI 2020) (github.com)

代碼組成:

ConvertToSphericalVoxel類(lèi):最高接口,實(shí)例化一個(gè)converter類(lèi),調(diào)用convert轉(zhuǎn)換局部點(diǎn)云
↓
spherical_voxel_optimized方法:在convert中調(diào)用,實(shí)現(xiàn)轉(zhuǎn)換,先轉(zhuǎn)換到球面坐標(biāo)系,然后進(jìn)行體素化
↓
spherical_voxel.compute方法:最終實(shí)現(xiàn)體素化,用pybind綁定C++代碼最終實(shí)現(xiàn)

ConvertToSphericalVoxel

from utils import geometry as ug

class ConvertToSphericalVoxel():

    """
    Convert point cloud to spherical voxel [beta = 2 * bandwidth,  alfa = 2 * bandwidth, num_radial_division].
    Alfa in [0, 2pi], Beta in [0, pi]
    """

    def __init__(self, bandwidth, radius_support, num_radial_division, num_points, random_sampling):

        self.bandwidth = bandwidth
        self.radius_support = radius_support
        self.num_radial_division = num_radial_division
        self.num_points = num_points
        self.random_sampling = random_sampling

    def __call__(self, point_cloud):

        features, pts_normed = ug.spherical_voxel_optimized(points=point_cloud,
                                                size_bandwidth=self.bandwidth,
                                                size_radial_divisions=self.num_radial_division,
                                                radius_support=self.radius_support,
                                                do_random_sampling=self.random_sampling,
                                                num_random_points=self.num_points)

        return features, pts_normed
……

參數(shù)解釋?zhuān)?

  • bandwidth: 球面體素化的帶寬,通常用于定義球面信號(hào)的分辨率。它決定了角度方向上的采樣密度(球面坐標(biāo)系的 \(\beta\) , \(\alpha\) ),影響了球面信號(hào)的分辨率,PRIN, LMVD, Compess等設(shè)置為24。
  • radius_support: 支持半徑,定義了local patch的支持半徑,也就是說(shuō)它確定了從關(guān)鍵點(diǎn)向外延伸的范圍內(nèi)哪些點(diǎn)將被納入local patch。
  • num_radial_division: 表示徑向(從關(guān)鍵點(diǎn)向外輻射的方向)上的分割數(shù)目。它影響了在徑向方向上球面信號(hào)的分辨率。
  • num_points: 采樣點(diǎn)的數(shù)量,這個(gè)值與local patch的固定點(diǎn)數(shù)一致(即1024點(diǎn)),確保輸入到轉(zhuǎn)換過(guò)程中的點(diǎn)數(shù)是一致的,這對(duì)于后續(xù)處理和模型輸入非常重要。
  • random_sampling: 控制是否在從點(diǎn)云中選擇點(diǎn)時(shí)進(jìn)行隨機(jī)采樣,設(shè)置為 True 使得在局部區(qū)域內(nèi)的點(diǎn)采樣更加多樣化,避免由于局部密度過(guò)高或過(guò)低而導(dǎo)致的信息丟失。隨機(jī)采樣可以讓網(wǎng)絡(luò)更具魯棒性,適應(yīng)不同點(diǎn)云的分布。

spherical_voxel_optimized

def spherical_voxel_optimized(points: np.ndarray, size_bandwidth: int, size_radial_divisions: int,
                              radius_support: float, do_random_sampling: bool, num_random_points: int) \
        -> Tuple[np.ndarray, np.ndarray]:
    """Compute spherical voxel using the C++ code.

    Compute Spherical Voxel signal as defined in:
    Pointwise Rotation-Invariant Network withAdaptive Sampling and 3D Spherical Voxel Convolution.
    Yang You, Yujing Lou, Qi Liu, Yu-Wing Tai, Weiming Wang, Lizhuang Ma and Cewu Lu.
    AAAI 2020.

    :param points: the points to convert.
    :param size_bandwidth: alpha and beta bandwidth.
    :param size_radial_divisions: the number of bins along radial dimension.
    :param radius_support: the radius used to compute the points in the support.
    :param do_random_sampling: if true a subset of random points will be used to compute the spherical voxel.
    :param num_random_points: the number of points to keep if do_random_sampling is true.

    :return: A tuple containing:
        The spherical voxel, shape(size_radial_divisions, 2 * size_bandwidth, 2 * size_bandwidth).
        The points used to compute the signal normalized according the the farthest point.
    """
    if do_random_sampling:
        min_limit = 1 if points.shape[0] > 1 else 0
        indices_random = np.random.randint(min_limit, points.shape[0], num_random_points)
        points = points[indices_random]

    pts_norm = np.linalg.norm(points, axis=1)
    # Scale points to fit unit sphere
    pts_normed = points / pts_norm[:, None]
    pts_normed = np.clip(pts_normed, -1, 1)

    pts_s2_coord = S2.change_coordinates(pts_normed, p_from='C', p_to='S')
    # Convert to spherical voxel indices
    pts_s2_coord[:, 0] *= 2 * size_bandwidth / np.pi  # [0, pi]
    pts_s2_coord[:, 1] *= size_bandwidth / np.pi # raw 2*size_bandwidth/2*np.pi
    pts_s2_coord[:, 1][pts_s2_coord[:, 1] < 0] += 2 * size_bandwidth

    # Adaptive sampling factor sin{pi*[(1/2,..., 2*size_bandwidth+1/2)/(2*size_bandwidth)]}
    # 能更好的聚合點(diǎn)云信息,但是也會(huì)導(dǎo)致更多的形變,有得必有失
    daas_weights = np.sin(np.pi * (2 * np.arange(2 * size_bandwidth) + 1) / 4 / size_bandwidth).astype(np.float32)
    voxel = np.asarray(sv.compute(pts_on_s2=pts_s2_coord,
                                  pts_norm=pts_norm,
                                  size_bandwidth=size_bandwidth,
                                  size_radial_divisions=size_radial_divisions,
                                  radius_support=radius_support,
                                  daas_weights=daas_weights))
    pts_normed = points / np.max(pts_norm)
    return voxel.astype(np.float32), pts_normed.astype(np.float32)
  • pts_norm 是local patch的點(diǎn)云徑向距離,所以 local patch輸入的時(shí)候最好經(jīng)過(guò)對(duì)于關(guān)鍵點(diǎn)的中心化操作 ,不然徑向距離會(huì)是關(guān)于坐標(biāo)系原點(diǎn)的。
  • S2.change_coordinates 用于將點(diǎn)云從笛卡爾坐標(biāo)系轉(zhuǎn)換成球面坐標(biāo)系,球面坐標(biāo)系解釋見(jiàn)WIKI,簡(jiǎn)單來(lái)說(shuō)就是兩個(gè)坐標(biāo),維度角度坐標(biāo)\beta,和經(jīng)度角度坐標(biāo)\alpha
  • daas_weights是自適應(yīng)權(quán)重:
    • 采樣密度平衡 :在球面坐標(biāo)系中,由于緯度(通常用 β 表示)不同區(qū)域的面積差異,不同區(qū)域的點(diǎn)密度會(huì)有所不同。例如,在球面的極地區(qū)域(緯度接近 0 π 的區(qū)域),同樣的角度變化可能覆蓋的球面面積較小,而在赤道區(qū)域,面積較大。為了避免在這些區(qū)域中出現(xiàn)過(guò)度或不足的采樣,自適應(yīng)采樣權(quán)重用于平衡不同緯度區(qū)域的影響。
    • 信息保持 :通過(guò)在不同的緯度上使用不同的采樣權(quán)重,可以更精確地保留球面上重要的幾何特征,特別是在特定的關(guān)鍵區(qū)域。這樣可以確保球面信號(hào)在高緯度和低緯度區(qū)域都能有效地捕捉到有意義的幾何信息。
  • sv.compute 用于體素轉(zhuǎn)換。

sv.compute

該函數(shù)是用pybind綁定的C++方法,文件為 spherical_voxel.cc ,代碼解釋如下:

初始化

    const float interval = radius_support / (size_radial_divisions);
    std::vector > > > > grids;
    std::vector > > features;
   
    grids.resize(size_radial_divisions);
    features.resize(size_radial_divisions);
  
    for (auto &beta: grids) {
	      beta.resize(2 * size_bandwidth);
	      for (auto &alpha: beta) {
	          alpha.resize(2 * size_bandwidth);
	      }
    }

    for (auto &beta: features) {
        beta.resize(2 * size_bandwidth);
        for (auto &alpha: beta) {
            alpha.resize(2 * size_bandwidth, 0);
        }
    }
  • interval表示徑向分割下每個(gè)體素的徑向長(zhǎng)度
  • grids用來(lái)存儲(chǔ)每個(gè)體素覆蓋的所有點(diǎn),可以通過(guò)下面的初始化看到,會(huì)初始化徑向,維度,經(jīng)度,每個(gè)體素是一種voxel
  • feature用來(lái)存儲(chǔ)最終每個(gè)體素的特征(特征是密度特征)

grids填充

    // mapping the points to the voxel grid
    for (size_t i = 0; i < pts_on_s2.size(); i++) {
        int r_idx = int(pts_norm[i] / interval);
        // except for the points radius larger than radius_support
        if (r_idx > size_radial_divisions - 1) r_idx = size_radial_divisions - 1; 

        int beta_idx = int(pts_on_s2[i][0] + 0.5f);
        if (beta_idx > 2 * size_bandwidth - 1) beta_idx = 2 * size_bandwidth - 1;

        int alpha_idx = int(pts_on_s2[i][1] + 0.5f);
        if (alpha_idx > 2 * size_bandwidth - 1) alpha_idx = 2 * size_bandwidth - 1;

        grids[r_idx][beta_idx][alpha_idx].emplace_back(std::vector{pts_norm[i], pts_on_s2[i][0], pts_on_s2[i][1]});
    }

這里會(huì)遍歷每個(gè)點(diǎn),計(jì)算每個(gè)點(diǎn)的徑向體素所用 r_idx ,緯度體素索引 beta_idx ,經(jīng)度體素索引 alpha_idx ,然后push到對(duì)應(yīng)的體素里面。

feature計(jì)算

首先計(jì)算每個(gè)體素的經(jīng)度左右特征計(jì)算邊界 left 、 right (也就是說(shuō)每個(gè)體素的特征計(jì)算并不僅僅只考慮本體素內(nèi)部,還有一些可能出現(xiàn)的相鄰體素),這里計(jì)算左右邊界就用到自適應(yīng)權(quán)重,維度高的,左右邊界會(huì)寬一些。

之后根據(jù)左右邊界訪(fǎng)問(wèn)對(duì)應(yīng)體素,并取出體素中所有點(diǎn),基于徑向距離確定點(diǎn)是否靠近本體素中心,越靠近該點(diǎn)的特征權(quán)重越大([0, 1])。

然后考慮徑向相鄰體素內(nèi)部的點(diǎn),用于本體素的特征計(jì)算,因?yàn)閺膹较蚩紤],點(diǎn)分布相對(duì)連續(xù),需要補(bǔ)充這樣的信息。

最后計(jì)算本體素的特征(密度特征(加過(guò)權(quán)的點(diǎn)個(gè)數(shù)))

    // compute the feature of each voxel
    for (size_t i = 0; i < size_radial_divisions; i++) {
        for (size_t j = 0; j < 2 * size_bandwidth; j++) {
            for (size_t k = 0; k < 2 * size_bandwidth; k++) {
                const float left = std::max(0.f, k - 0.5f / daas_weights[j]);
                const float right = std::min(2.f * size_bandwidth, k + 0.5f / daas_weights[j]);
                float sum = 0.f;
                int cnt = 0;

                for (int m = int(left + 0.5f); m < int(right + 0.5f); m++) {
                    for (int n = 0; n < grids[i][j][m].size(); n++) {
                        if (grids[i][j][m][n][2] > left && grids[i][j][m][n][2] < right) {
                            sum += 1.f - std::abs(grids[i][j][m][n][0] / interval - (i + 1)); // radial feature weight
                            cnt++;
                        }
                    }
                    
                    // 在實(shí)際情況中,點(diǎn)云數(shù)據(jù)可能分布在兩個(gè)相鄰的徑向分割之間,
                    // 尤其是當(dāng)點(diǎn)的徑向距離位于兩個(gè)徑向分割的邊界附近時(shí)。
                    // 為了防止因單純考慮當(dāng)前徑向分割而導(dǎo)致信息的丟失,
                    // 代碼會(huì)查找相鄰徑向分割中滿(mǎn)足條件的點(diǎn),并將它們的貢獻(xiàn)也加到當(dāng)前體素單元的特征值中。
                    if (i < size_radial_divisions - 1) {
                        for (int n = 0; n < grids[i + 1][j][m].size(); n++) {
                            if (grids[i + 1][j][m][n][2] > left && grids[i + 1][j][m][n][2] < right) {
                                sum += 1.f - std::abs(grids[i + 1][j][m][n][0] / interval - (i + 1));
                                cnt++;
                            }
                        }
                    }
                }

                // 與徑向分割不同,緯度分割(即 beta 方向)代表的是球面坐標(biāo)中的角度,
                // 分割的區(qū)域代表不同的“環(huán)”或“帶”。
                // 在這種情況下,每個(gè)緯度分割對(duì)應(yīng)的球面區(qū)域是明確的,
                // 且這些分割區(qū)域之間沒(méi)有交叉,因此點(diǎn)不會(huì)“跨越”到另一個(gè)緯度分割。

                if (cnt > 0) {
                    features[i][j][k] = sum / cnt;
                }
            }
        }
    }
小編推薦閱讀

好特網(wǎng)發(fā)布此文僅為傳遞信息,不代表好特網(wǎng)認(rèn)同期限觀點(diǎn)或證實(shí)其描述。

a 1.0
a 1.0
類(lèi)型:休閑益智  運(yùn)營(yíng)狀態(tài):正式運(yùn)營(yíng)  語(yǔ)言:中文   

游戲攻略

游戲禮包

游戲視頻

游戲下載

游戲活動(dòng)

《alittletotheleft》官網(wǎng)正版是一款備受歡迎的休閑益智整理游戲。玩家的任務(wù)是對(duì)日常生活中的各種雜亂物
VoxEL
VoxEL
類(lèi)型:動(dòng)作冒險(xiǎn)  運(yùn)營(yíng)狀態(tài):未知  語(yǔ)言: 日文  

游戲攻略

游戲禮包

游戲視頻

游戲下載

游戲活動(dòng)

《VoxEL》是游戲商DeNA最新推出的二次元VR冒險(xiǎn)游戲。游戲中,玩家能跟隨銀發(fā)小姐姐一起展開(kāi)刺激的冒險(xiǎn),

相關(guān)視頻攻略

更多

掃二維碼進(jìn)入好特網(wǎng)手機(jī)版本!

掃二維碼進(jìn)入好特網(wǎng)微信公眾號(hào)!

本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請(qǐng)發(fā)郵件[email protected]

湘ICP備2022002427號(hào)-10 湘公網(wǎng)安備:43070202000427號(hào)© 2013~2025 haote.com 好特網(wǎng)