pyg-team / pytorch_geometric

Graph Neural Network Library for PyTorch
https://pyg.org
MIT License
21.18k stars 3.64k forks source link

open3d #2945

Open soccken opened 3 years ago

soccken commented 3 years ago

Importing PointConv, fps, radius, global_max_pool in torch_geometric.nn disables open3d's draw_geometries function What is the cause of this?

rusty1s commented 3 years ago

This shouldn't be the case. Can you give me a small example to reproduce?

soccken commented 3 years ago

Sorry for the late reply. I am improving the program of pointnet2_classification.py to analyze pointnet ++. The operating environment is jetsonnano (jetpack). I am downloading point cloud data using open3d, but when I import modules such as pointconv and global_max_pool, an error occurs in the draw_geometries function of open3d and I cannot visualize the point cloud data. Do you know anything about this cause? The content of the error is [open3d WARNING] GLFW Error: GLX: No GLXFBConfigs returned [open3d WARNING] GLFW Error: GLX: Failed to find a suitable GLXFBConfig [open3d WARNING] Failed to create window [open3d WARNING] [DrawGeometries] Failed creating OpenGL window

rusty1s commented 3 years ago

Does the same error happen when only importing torch?

soccken commented 3 years ago

No. Importing torch works fine with the draw_geometries function.

rusty1s commented 3 years ago

I sadly cannot reproduce this. Can you do some further inspection on which import is causing this in particular? Does it work when only importing torch_scatter or torch_sparse?

soccken commented 3 years ago

I'm using the code below. How do I investigate torch-scatter and torch-sparse? I don't seem to import them.

import numpy as np import torch import open3d as o3d import os import glob import pandas as pd from pathlib import Path import torch_geometric.transforms as T from torch_geometric.data import DataLoader, Data from torch_geometric.nn import PointConv, fps, radius, global_max_pool import torch.nn.functional as F from torch.nn import Sequential as Seq, Linear as Lin, ReLU, BatchNorm1d as BN import matplotlib.pyplot as plt

from deeplearning import creat_train_dataset, creat_test_dataset, load_train_dataset, load_test_dataset

data_train_list = [] data_test_list = []

class SAModule(torch.nn.Module): def init(self, ratio, r, nn): super(SAModule, self).init() self.ratio = ratio self.r = r self.conv = PointConv(nn, add_self_loops=False)

def forward(self, x, pos, batch):
    idx = fps(pos, batch, ratio=self.ratio)
    row, col = radius(pos.cpu(), pos[idx].cpu(), self.r, batch.cpu(), batch[idx].cpu(),
                      max_num_neighbors=32)
    row = row.to(device)
    col = col.to(device)
    edge_index = torch.stack([col, row], dim=0)
    x = self.conv(x, (pos, pos[idx]), edge_index)
    pos, batch = pos[idx], batch[idx]
    return x, pos, batch

class GlobalSAModule(torch.nn.Module): def init(self, nn): super(GlobalSAModule, self).init() self.nn = nn

def forward(self, x, pos, batch):
    x = self.nn(torch.cat([x, pos], dim=1))
    x = global_max_pool(x, batch)
    pos = pos.new_zeros((x.size(0), 3))
    batch = torch.arange(x.size(0), device=batch.device)
    return x, pos, batch

def MLP(channels, batch_norm=True): return Seq(*[ Seq(Lin(channels[i - 1], channels[i]), ReLU(), BN(channels[i])) for i in range(1, len(channels)) ])

class Net(torch.nn.Module): def init(self): super(Net, self).init()

    self.sa1_module = SAModule(0.5, 0.2, MLP([3, 64, 64, 128]))
    self.sa2_module = SAModule(0.25, 0.4, MLP([128 + 3, 128, 128, 256]))
    self.sa3_module = GlobalSAModule(MLP([256 + 3, 256, 512, 1024]))

    self.lin1 = Lin(1024, 512)
    self.lin2 = Lin(512, 256)
    self.lin3 = Lin(256, 10)

def forward(self, data):
    sa0_out = (data.x, data.pos, data.batch)
    sa1_out = self.sa1_module(*sa0_out)
    sa2_out = self.sa2_module(*sa1_out)
    sa3_out = self.sa3_module(*sa2_out)
    x, pos, batch = sa3_out

    x = F.relu(self.lin1(x))
    x = F.dropout(x, p=0.5, training=self.training)
    x = F.relu(self.lin2(x))
    x = F.dropout(x, p=0.5, training=self.training)
    x = self.lin3(x)
    return F.log_softmax(x, dim=-1)

def train(loader): model.train()

correct = 0

for data in loader:
    data = data.to(device)
    optimizer.zero_grad()

    pred = model(data).max(1)[1]
    #print(pred)
    correct += pred.eq(data.y).sum().item()
    loss = F.nll_loss(model(data), data.y)
    loss.backward()
    optimizer.step()
return correct / len(loader.dataset)

def test(loader): model.eval() a=1 correct = 0 for data in loader: data = data.to(device)

print(len(loader))

    print(a)
    with torch.no_grad():
        pred = model(data).max(1)[1]
        print(pred)
        print(data.y)
    correct += pred.eq(data.y).sum().item()
    #mistake = len(loader)-len1
    #mistake1 = correct - len1
    #loss = mistake1 / mistake
    #print(loss)
    print(correct)
    a = a+1
return correct / len(loader.dataset)

def creat_train_dataset(pcd, objtype):

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

class_num_dict={'stand':0, 'sleep':1, 'sit':2, 'others':3}
class_num=class_num_dict[objtype]

label=torch.tensor([class_num], dtype=torch.int64, device=device)

pcd_numpy = np.asarray(pcd.points).astype(np.float32)
pcd_tenser = torch.from_numpy(pcd_numpy)
pcd_tenser = pcd_tenser.to(device)

data=Data(pos=pcd_tenser, y=label)

#ns = T.NormalizeScale()
#data = ns(data)

data_train_list.append(data)

def creat_test_dataset(pcd, objtype):

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

class_num_dict={'stand':0, 'sleep':1, 'sit':2, 'others':3}
class_num=class_num_dict[objtype]

label=torch.tensor([class_num], dtype=torch.int64, device=device) 
pcd_numpy = np.asarray(pcd).astype(np.float32)
pcd_tenser = torch.from_numpy(pcd_numpy)
pcd_tenser = pcd_tenser.to(device)

data=Data(pos=pcd_tenser, y=label)

#ns = T.NormalizeScale()
#data = ns(data)

data_test_list.append(data)

def load_train_dataset(): files0=sorted(glob.glob("/home/keigo/デスクトップ/train/train_stand/.pcd")) files1=sorted(glob.glob("/home/keigo/デスクトップ/train/train_sleep/.pcd")) files2=sorted(glob.glob("/home/keigo/デスクトップ/train/train_sit/.pcd")) files3=sorted(glob.glob("/home/keigo/デスクトップ/train/others/.pcd")) for a in files0: pcd = o3d.io.read_point_cloud(a) creat_train_dataset(pcd=pcd, objtype='stand')

data_train_list.append(data)

for b in files1:
    pcd = o3d.io.read_point_cloud(b)
    creat_train_dataset(pcd=pcd, objtype='sleep')

for c in files2:
    pcd = o3d.io.read_point_cloud(c)
    creat_train_dataset(pcd=pcd, objtype='sit')

for d in files3:
    pcd = o3d.io.read_point_cloud(d)
    creat_train_dataset(pcd=pcd, objtype='others')

data_loader = DataLoader(data_train_list, batch_size=10, shuffle=True, num_workers=1)

##print(data_train_list[0])
#print(len(data_loader))
return data_loader

#print(data_loader)
#print(len(data_loader))
#print(len(data_train_list))

def load_test_dataset(): files6=sorted(glob.glob("/home/keigo/デスクトップ/test3/test_sit/*.pcd"))

for c in files6:
    pcd = o3d.io.read_point_cloud(c)
    for f in range(2):
        plane_model,inliers = pcd.segment_plane(distance_threshold=0.05,ransac_n=3,num_iterations=1000)
        [a,b,c,d]=plane_model
        #print(f"Plane equation: {a:.2f}x + {b:.2f}y + {c:.2f}z + {d:.2f} = 0")
        inlier_cloud=pcd.select_by_index(inliers)
        inlier_cloud.paint_uniform_color([1.0,0,0])
        outliers_cloud=pcd.select_by_index(inliers, invert=True)
        #print(inlier_cloud)
        #print(pcd)
        pcd=outliers_cloud

    with o3d.utility.VerbosityContextManager(
            o3d.utility.VerbosityLevel.Debug) as cm:
        labels = np.array(
            pcd.cluster_dbscan(eps=0.13, min_points=45, print_progress=True))

    max_label = labels.max()+1
    #print(f"point cloud has {max_label} clusters")
    colors = plt.get_cmap("tab20")(labels / (max_label if max_label > 0 else 1))
    colors[labels < 0] = 0
    pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])
    #o3d.visualization.draw_geometries([pcd])
    if max_label > 0:
        xyz = np.asarray(pcd.points)
        #print(xyz)
        for i in range(max_label):
            cluster_xyz = xyz[labels == i]
            #print(len(cluster_xyz))   
            point_cloud = o3d.geometry.PointCloud()
            point_cloud.points = o3d.utility.Vector3dVector(cluster_xyz)
            #print(cluster_xyz)
            #lists.append(point_cloud)
            #print(lists)
            if len(cluster_xyz) > 600:
                o3d.visualization.draw_geometries([point_cloud])
                creat_test_dataset(pcd=cluster_xyz, objtype='sit')

data_loader = DataLoader(data_test_list, batch_size=1, shuffle=False, num_workers=1)

#print(len(data_loader))

return data_loader

if name == 'main':

#test_loader = load_test_dataset()
#train_loader = load_train_dataset()
#print(len(test_loader))
#print(data_test_list)
#print(data_train_list[0].pos)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = Net().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)

model.load_state_dict(torch.load("/home/keigo/デスクトップ/train/model.pth"))
test_loader=load_test_dataset()
#print(test_loader)
test(test_loader)
#test_acc = test(test_loader)
#print('Test: {:.4f}'.format(test_acc))
#model_path = 'model.pth1'
#torch.save(model.state_dict(), model_path )
soccken commented 3 years ago

After investigating, when I imported torch-cluster, torch-scatter, torch-sparse, torch-sparse, torch-spline-conv, the draw_geometries function worked without any problem. The draw_geometries function stops working when importing modules such as PointConv and fps from torch_gemetric.nn.

rusty1s commented 3 years ago

That's super weird. I will try to look into it and reproduce the issue.