作者:高煥堂
近幾年,隨著機器學習的流行,AI生成模型(如GAN)和大規模3D資料集(如ShapeNet等)的出現,讓人們可以藉助生成式AI,先從大數據中學到的事物形狀的先驗知識,然後進行生成形形色色的3D圖像。
簡介3D點雲 GAN模型
GAN(生成對抗網路)的潛力在於它可以類比資料樣本空間的機率分配(Distribution),成為AI機器學習快速發展的領域之一。例如,藉由 3D ShapeNet 資料集,可以訓練GAN模型來生成逼真的立體(3D)點雲圖像。
茲回顧ShapeNet數據集的源頭,它是由史丹佛大學、普林斯頓大學等研究機構所開發的大型 3D CAD模型資料庫。它含有數億個模型,分為數千個類別。

圖片來源:arXiv、stanford
通常是給定物件的深度圖,然後將其轉換為體積表示並識別觀察到的表面、自由空間和遮擋空間。3D ShapeNets 可以識別物體類別,完成完整的 3D 形狀,並在初始識別不確定的情況下預測下一個最佳視圖。
點雲(Point cloud)是 3D 幾何圖形表達的資料結構之一。它使用一群不規則點來描述一個物件的3D形狀表徵。於是,對事物形狀表(特)徵的學習成為點雲AI模型的主要任務。
隨著生活中越來越多東西連結到虛擬世界,點雲提供了快速的方式,精準產出實際物體的數位圖像。近年來,點雲在電力線巡檢、智慧城市、古蹟導覽服務、自動駕駛等領域得到廣泛應用。由於激光掃描技術和機器學習的發展,AI點雲模型越來越受到關注。
本文的目標是通過GAN來處理點雲資料。方法是,基於在大型數據集(如ShapeNet)上訓練GAN模型。
準備訓練數據:使用ShapeNet數據集
將ShapeNet數據集放置於您的工作區:
其中的每一個檔案都是一個3D圖像:
圖像的放大:

程式1:讀取點雲3D圖像
讀取/ShapeNet_data/chair/train/裡的第1張圖像,並且繪出來。
程式碼:
# paa_GAN_001.py
import numpy as np
import os
import scipy.ndimage as nd
import scipy.io as sio
import matplotlib.pyplot as plt
data_dir = 'c:/oopc/ShapeNet_data/chair/train/'
filenames = [os.path.join(data_dir, name)
for name in os.listdir(data_dir)
if name.endswith('.mat')]
print(len(filenames))
#-----------------------------------------------------
nchw = [1,32,32,32]
# 讀取一個3D的*.mat檔案
def getVoxelFromMat(file_path):
voxels = sio.loadmat(file_path)['instance']
voxels = np.pad(voxels, (1, 1), 'constant', constant_values=(0, 0))
if nchw[-1] != 32:
ratio = nchw[-1] / 32.
voxels = nd.zoom(voxels, (ratio, ratio, ratio),
mode='constant', order=0)
return voxels
#---------------------------------
file_path = filenames[0]
vx = getVoxelFromMat(file_path)
fig = plt.figure()
ax = plt.subplot(projection='3d')
ax.set_aspect('auto')
ax.voxels(vx, edgecolor='red')
plt.show()
#---------------------
#END
繪出圖像:
程式2:使用PaddlePaddle的Dataset
與上一個程式相同功能:讀取/ShapeNet_data/chair/train/裡的第1張圖像,並且繪出來。
使用飛槳(Paddle)的Dataset,程式碼如下:
# paa_GAN_002.py
import numpy as np
import os
import paddle
import paddle.nn as nn
from paddle.io import Dataset, DataLoader
import scipy.ndimage as nd
import scipy.io as sio
import matplotlib.pyplot as plt
data_dir = 'c:/oopc/ShapeNet_data/chair/train/'
file_list = [os.path.join(data_dir, name)
for name in os.listdir(data_dir)
if name.endswith('.mat')]
print(len(file_list))
#-----------------------------------------------------
nchw = [1,32,32,32]
# 讀取一個3D的*.mat檔案
def getVoxelFromMat(file_path):
voxels = sio.loadmat(file_path)['instance']
voxels = np.pad(voxels, (1, 1), 'constant', constant_values=(0, 0))
if nchw[-1] != 32:
ratio = nchw[-1] / 32.
voxels = nd.zoom(voxels, (ratio, ratio, ratio),
mode='constant', order=0)
return voxels
#---------------------------------
class ShapeNetDataset(Dataset):
def __init__(self):
self.filenames = file_list
def __getitem__(self, index):
fna = self.filenames[index]
volume = np.asarray(getVoxelFromMat(fna), dtype=np.float32)
return paddle.to_tensor(volume)
def __len__(self):
return len( self.filenames)
#---------------------------------------
dataset = ShapeNetDataset()
vx = dataset[8]
vx = vx.numpy()
fig = plt.figure()
ax = plt.subplot(projection='3d')
ax.set_aspect('auto')
ax.voxels(vx, edgecolor='red')
plt.show()
#---------------------
#END
讀取一張圖(第8張)圖像,並繪出來:
這是繪出於屏幕畫面上。
程式3:如何寫入點雲3D圖像
上一個程式是繪出於屏幕畫面上。現在就來看看,如何將所畫(生成)的圖像,儲存於檔案裡,程式碼如下:
# paa_GAN_003.py
import numpy as np
import os
import paddle
import paddle.nn as nn
from paddle.io import Dataset, DataLoader
import scipy.ndimage as nd
import scipy.io as sio
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
data_dir = 'c:/oopc/ShapeNet_data/chair/train/'
file_list = [os.path.join(data_dir, name)
for name in os.listdir(data_dir)
if name.endswith('.mat')]
print(len(file_list))
#-----------------------------------------------------
nchw = [1,32,32,32]
# 讀取一個3D的*.mat檔案
def getVoxelFromMat(file_path):
voxels = sio.loadmat(file_path)['instance']
voxels = np.pad(voxels, (1, 1), 'constant', constant_values=(0, 0))
if nchw[-1] != 32:
ratio = nchw[-1] / 32.
voxels = nd.zoom(voxels, (ratio, ratio, ratio),
mode='constant', order=0)
return voxels
def SavePloat_Voxels(voxels, path, iteration):
voxels = voxels.__ge__(0.5)
fig = plt.figure(figsize=(32, 16))
gs = gridspec.GridSpec(2, 4)
gs.update(wspace=0.05, hspace=0.05)
for i, sample in enumerate(voxels):
x, y, z = sample.nonzero()
ax = plt.subplot(gs[i], projection='3d')
ax.scatter(x, y, z, zdir='z', c='red')
ax.set_xticklabels([])
ax.set_yticklabels([])
plt.savefig(path + '/{}.png'.format(str(iteration).zfill(3)), bbox_inches='tight')
plt.close()
#---------------------------------
class ShapeNetDataset(Dataset):
def __init__(self):
self.filenames = file_list
def __getitem__(self, index):
fna = self.filenames[index]
volume = np.asarray(getVoxelFromMat(fna), dtype=np.float32)
return paddle.to_tensor(volume)
def __len__(self):
return len( self.filenames)
#---------------------------------------
dataset = ShapeNetDataset()
vx = dataset[0]
vx = vx.unsqueeze(0)
vx = vx.numpy()
print('images_saved...')
ep = 0
SavePloat_Voxels(vx, 'c:/oopc/ShapeNet_data/', ep)
#---------------------
#END
讀取一張圖(第0張)圖像,然後把該圖像,寫入(儲存)於檔案裡。例如,此程式將所讀取的(第0張)寫入檔案(儲存於/ShapeNet_data/)裡,如下:
放大圖像:
準備好訓練數據集之後,就可以展開訓練了,請見本文下集。
(責任編輯:謝涵如)
- LoRA微調三步驟:以大語言模型MT5為例 - 2024/05/02
- 為什麼Gemma採取Decoder-Only Transformer架構呢? - 2024/04/08
- 如何從0訓練企業自用Gemma模型 - 2024/04/03
訂閱MakerPRO知識充電報
與40000位開發者一同掌握科技創新的技術資訊!