[点云+深度学习]3DMatch论文解析

《3DMatch: Learning Local Geometric Descriptors from RGB-D Reconstructions》

运行代码

配置Marvin框架

  1. 安装Ubuntu 14.04
    U盘+软碟通
  2. 安装cuda 7.5
    (甚至不用关闭Ubuntu的图形界面)
    常用的方式安装不上(官网下载*.run),采用这样的方式。另一种没有尝试的方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    sudo add-apt-repository ppa:graphics-drivers/ppa
    sudo apt-get --purge remove "nvidia*"
    sudo apt-get --purge remove "cuda*"

    wget http://developer.download.nvidia.com/compute/cuda/7.5/Prod/local_installers/cuda-repo-ubuntu1404-7-5-local_7.5-18_amd64.deb
    sudo dpkg -i cuda-repo-ubuntu1404-7-5-local_7.5-18_amd64.deb
    sudo apt-get update
    sudo apt-get upgrade
    sudo apt-get install cuda

    配置cuda:
    sudo nano ~/.bashrc

    1
    2
    3
    export CUDA_HOME=/usr/local/cuda-7.5
    export PATH=/usr/local/cuda-7.5/bin${PATH:+:${PATH}}
    export LD_LIBRARY_PATH=/usr/local/cuda-7.5/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

    环境变量立刻生效:

    1
    source ~/.bashrc

    装完后,输入”nvidia-smi”验证

  3. 安装cudnn 5.1(参见中的”④cudnn 5.0安装”)
    配置cudnn,拷贝cudnn到cuda的安装目录下

    1
    2
    3
    sudo cp cuda/include/cudnn.h /usr/local/cuda/include # 复制到 include 中
    sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64 # 复制到 lib64 中
    sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn* # 将头文件复制进去

    此处我貌似做了多余的步骤(cudnn在三个地方有,并都设置了软链接,估计是3-起了作用。比较稳妥的方法是如下在三个地方都设置好软链接等)——事实证明,只要把上面的cuda/lib64下的4个cudnn的软链接按照下面的命令设置好即可,其余地方不重要
    1-/usr/local/cudnn/v5.1/lib64;/usr/local/cudnn/v5.1/include
    2-/usr/local/lib;/usr/local/include
    3-/usr/local/cuda-7.5/lib64;/usr/local/cuda-7.5/include

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    sudo tar xvf cudnn-7.5-linux-x64-v5.0-ga.tgz
    cd cuda/include
    sudo cp *.h /usr/local/include/
    ../lib64
    sudo cp lib* /usr/local/lib/
    cd /usr/local/cudnn/v5.1/lib64
    sudo chmod +r libcudnn.so.5.1.10
    sudo ln -sf libcudnn.so.5.1.10 libcudnn.so.5
    sudo ln -sf libcudnn.so.5 libcudnn.so
    sudo ldconfig

    装完后,输入”nvcc -V”验证
    查看cuda和cudnn的版本:

    1
    2
    3
    cat /usr/local/cuda/version.txt
    cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
    nvcc -V
  4. 安装Marvin
    参照Marvin官网,用源码编译(可能需要略微修改compile.sh)
    Marvin的所有代码只在两个文件里(marvin.hpp、marvin.cu)。

    1
    2
    3
    4
    curl -L https://github.com/PrincetonVision/marvin/tarball/master | tar zx
    mv PrincetonVision* marvin && cd marvin

    ./compile.sh
  5. 测试Marvin
    运行examples/mnist/demo.sh

安装Matlab R2017b


ubuntu16.04安装MATLAB R2017b步骤详解(附完整破解文件包)

matlab安装目录:/home/imv/MATLAB/R2017b

破解:

1
2
sudo cp /home/imv/Downloads/matlab/MATLABR2017b_Linux_Crack/license_standalone.lic /home/imv/MATLAB/R2017b/licenses/
sudo cp /home/imv/Downloads/matlab/MATLABR2017b_Linux_Crack/libmwservices.so /home/imv/MATLAB/R2017b/bin/glnxa64/

如不成功,

为了访问matlab时不用加路径,添加环境变量可在 /etc/profile中添加以下代码

1
export PATH=$PATH:/home/imv/MATLAB/R2017b/bin

环境变量立即生效

1
source /etc/profile

安装OpenCV

重要参考:
Ubuntu14.04 OpenCV编译安装 —— 配准环境变量
ubuntu 下编译安装cmake、OpenCV

下载OpenCV 2.4.11的源码

cmke-gui界面时改3个地方:把WITH-CUDA和BUILD_opencv_gpu选项去掉打钩,CMAKE_BUILD_TYPE 值输入RELEASE

多线程编译:

1
2
make -j4
sudo make install

再配置环境变量

QA:3DMatch代码运行失败

Q:运行”./demo ../data/sample/3dmatch-demo/single-depth-1.ply fragment-1”时报错:”./demo: error while loading shared libraries: libopencv_core.so.2.4: cannot open shared object file: No such file or directory”
A:运行sudo ldconfig -v

官方代码分析

例程 代码目录
Demo: Align Two Point Clouds with 3DMatch
使用预训练的3DMatch描述符配准两个点云
Converting 3D Data to TDF Voxel Grids
转换3D数据为TDF体素网格


Training 3DMatch from RGB-D Reconstructions
从RGBD三维重建数据集中训练3DMatch描述符
Multi-Frame Depth TSDF Fusion
将多个注册的深度图融合到TSDF体素体积中
Evaluation Code
评估代码



Demo: Align Two Point Clouds with 3DMatch

功能:使用预训练的3DMatch描述子标准的RANSAC将两组(从单视角深度图投影所得)点云配准

思路☆:

  1. 给定两组点云 —— 250000个点
  2. 计算随机表面关键点(random surface keypoints) —— 500个点
  3. 计算TDF体素网格体积(TDF voxel grid volumes
  4. 计算3DMatch描述子(3DMatch descriptors) —— 500个描述符,每个512维
  5. 在3DMatch描述符空间中查找相互最接近(欧氏距离)的关键点 —— 108个点
  6. 用RANSAC估计点云2到点云1的刚性变换
  7. 计算配准百分比(用于回环检测)
  8. 可视化配准结果

代码梳理:

变量名 说明 维度
fragment1PointCloud
fragment2PointCloud
第1/2组点云
fragment1Keypoints
fragment2Keypoints
第1/2组点云的关键点
fragment1Descriptors
fragment2Descriptors
第1/2组点云的关键点的3DMatch特征描述子
fragment1MatchKeypoints
fragment2MatchKeypoints
在3DMatch描述符空间中查找相互最接近的关键点
inlierIdx 108个关键点中,使用ransacfitRt()配准成功的关键点

ransacfitRt()的思路☆:

  1. 设定每次从所有的点(108个点)中随机取3个点(s=3)
  2. 用取出的3个点估计点云A到点云B的变换矩阵(3*4)
  3. 根据点云A到点云A’(转换关系*点云B)的欧式距离, 评估出内点(距离<0.05的对应点)
  4. 设定尝试抽样的上限(maxTrials=50000)
  5. 随着尝试, 内点数增加, 根据设定的log除法计算方式, N减小, 直到N小于尝试抽样的次数, 退出循环
  6. 返回最优的变换矩阵和内点
  7. 根据内点重新计算一次变换矩阵(因为之前的变换矩阵是通过抽样的3个点求得,此处内点可能是6个)

Matlab代码中的对象、函数:
KDTreeSearcher
knnsearch
find
ransac——代码中用的是作者自己写的
repmat
pointCloud

Matlab中的knnsearch(支持传入KDTreeSearcher、ExhaustiveSearcher)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
% knnsearch功能:在X(145个点)中寻找与Y(5个点)中距离最相近的点
% 返回的IdxKDT是Y在X中的索引
% 1.载入数据,执行近邻搜索
load fisheriris
rng(1); % For reproducibility
n = size(meas,1);
idx = randsample(n,5);
X = meas(~ismember(1:n,idx),:); % Training data [145,4]
Y = meas(idx,:); % Query data [5,4]
MdlKDT = KDTreeSearcher(X);
IdxKDT = knnsearch(MdlKDT,Y);
% 2.比较配准的结果
i = 1; % 2 3 4 5
Y(i,:)
X(IdxKDT(i),:)

关键代码理解☆:

1
2
3
4
5
6
7
8
fragment2MatchIdx = find((1:size(fragment2NNIdx,1))' == fragment1NNIdx(fragment2NNIdx));

% 理解
% fragment2NNIdx(6) % 距离 描述子2中的第6个点 最近的是 描述子1中的第366个点
% fragment1NNIdx(366) % 距离 描述子1中的第366个点 最近的是 描述子2中的第6个点
% => 描述子2中的第6个点 与 描述子1中的第366个点 互为距离最近,即匹配点
% 等价求的是:fragment1NNIdx(fragment2NNIdx(i)) == i
% 即在A看来距离B最近,在B看来也距离A最近

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
fragment2MatchIdx = find((1:size(fragment2NNIdx,1))' == fragment1NNIdx(fragment2NNIdx));
fragment2MatchKeypoints = fragment2Keypoints(fragment2MatchIdx,:);
fragment1MatchKeypoints = fragment1Keypoints(fragment2NNIdx(fragment2MatchIdx),:);

% 上述代码的等价写法:
% fragment1MatchIdx = find((1:size(fragment1NNIdx,1))' == fragment2NNIdx(fragment1NNIdx));
% fragment1MatchKeypoints_2 = fragment1Keypoints(fragment1MatchIdx,:);
% fragment2MatchKeypoints_2 = fragment2Keypoints(fragment1NNIdx(fragment1MatchIdx),:);

% 验证:排序后索引是相同的
% unique(fragment2MatchIdx) == unique(fragment1NNIdx(fragment1MatchIdx))
% unique(fragment1MatchIdx) == unique(fragment2NNIdx(fragment2MatchIdx))

% 验证:所有点中下面的点距离最近
% i = 1; % 2 3
% mean(abs(fragment2Descriptors(fragment1NNIdx(i), :) - fragment1Descriptors(i, :)))
% mean(abs(fragment1Descriptors(fragment2NNIdx(i), :) - fragment2Descriptors(i, :)))

Converting 3D Data to TDF Voxel Grids

功能:将各种形式的3D数据(点云、网格、深度图)转换成截断距离函数(TDF,Truncated Distance Function)值的体素网格(voxel grid)

pointCloud2TDF()的思路☆:

  1. 给定点云,计算其X、Y、Z的上下界 —— points.shape == (738, 3)
  2. 根据体素大小(voxelSize=0.005)生成网格点坐标矩阵 —— searchPC.shape == (358644, 3),根据体素大小(采样粒度)算得的x、y、z的长度分别为121、52、57
  3. 使用kd树搜索每个网格点到点云的最短距离 —— nnDist.shape == (358644,)
  4. 对距离进行运算得到TDF值 —— voxelGridTDF.shape == (121, 52, 57),与x、y、z的长度对应
    • voxelGridTDF = 1.0 - np.minimum(voxelGridTDF / (voxelSize*voxelMargin), 1.0)
    • a = voxelGridTDF / (voxelSize * voxelMargin) = voxelGridTDF / (0.005 * 5) = voxelGridTDF * 40 —— 把距离放大40倍
    • b = np.minimum(a, 1.0) —— 比1大的取1,比1小的不变。即把大于1的值截断,相当于归一化到[0,1](距离≥0)。此时1(远离表面)、0(表面上)
    • voxelGridTDF = 1.0 - b —— 翻转操作,仍是[0,1]。此时1(表面上)、0(远离表面)

注意:TDF(Truncated Distance Function)与TSDF(Truncated Signed Distance Function)的区别

  • TSDF
    • 接近0的值:表面(surface)
    • 接近1的值:自由空间(free space)
    • 接近-1的值:被遮挡的空间(occluded space)
  • TDF
    • 相比TSDF,删除符号,失去了自由空间和被遮挡空间之间的区别
    • 但在部分数据上获得了新属性(对描述子的鲁棒性至关重要):体素值之间的最大梯度集中在表面周围,而不是自由空间和遮挡空间之间的阴影边界
    • TDF表示减少了确定摄像机视图不可用的3D数据上的遮挡空间是什么的模糊性
    • 换句话说,每个体素的TDF值表示该体素的中心与最近的3D表面之间的距离。这些TDF值被截断、归一化、翻转到介于1(表面上)和0(远离表面)之间

注意:np.meshgrid()的使用(把两个数组的笛卡尔积内的元素的第一二个坐标分别放入两个矩阵中)
3分钟理解np.meshgrid()
numpy.meshgrid()理解

Training 3DMatch from RGB-D Reconstructions

功能:使用Marvin框架(孪生网络架构),从RGB-D三维重建数据集中随机采样特征对,训练3DMatch。

Multi-Frame Depth TSDF Fusion

功能:将多个注册的深度图融合到TSDF体素体积中,然后可用于创建表面网格和点云。

与作者的tsdf-fusion-python略有不同,运行同样的数据(3dmatch-toolbox-master\data\sample\depth-fusion-demo)
本代码:二进制格式,267793个点(vertex),只有x、y、z
py代码:Ascii格式,69922个点(vertex),有x、y、z、nx、ny、nz、red、green、blue,139048个面片(face)

Evaluation Code

功能:关键点匹配基准、几何注册基准的评估代码,以及论文中实验的参考实现。

Keypoint Matching Benchmark

功能:关键点匹配基准

代码 功能 说明
getError.m 计算验证集上的性能(false-positive rate (error) at 95% recall) 通过读取log文件实现
test3DMatch.m 在验证集上运行3DMatch,以生成log文件 注意需要先编译出get3DMatchDescriptors程序
makeCorresDataset.m 从RGB-D三维重建数据集中生成自己的点对(correspondence)数据集 运行很慢

Geometric Registration Benchmark

功能:几何配准基准

代码 功能 说明
getKeyptsAndDesc.m 生成场景片段的中间数据(TDF体素体积、关键点、3DMatch描述符)
runFragmentRegistration.m 读取中间数据,并为每对片段运行基于RANSAC的配准
writeLog.m 从每对片段中读取配准结果并创建log文件
evaluate.m 从验证的log文件中计算准确度(precision )和召回率(recall)

Model Fitting for 6D Object Pose Estimation in the Amazon Picking Challenge

功能:评估3DMatch在Shelf&Tote数据集上的6D姿态估计能力

数据相关文件夹:
$FromDir=../../data/apc/scenes/office/test/shelf/scene-0000$
$ToDir=../../data/apc/scenarios/000000$
$ObjDir=../../data/apc/objects$
$BenDir=../../data/benchmark/office/test/tote/scene-0000$
$BenRootDir=../../data/benchmark$

代码 功能
convertBenchmark2Scenarios.m 将$/apc/scenes$里的一些文件复制到$/apc/scenarios$
注意:$/apc/scenarios$里每个子文件夹里的3个文件名是相同的
convertScenarios2Benchmark.m 根据$/apc/scenarios$里的文件生成$/apc/scenes$里的一个文件
getModelTDF.m 物体模型生成体素网格体积的准确TDF值
步骤:读点云(195477×3)、降采样(9601×3)、去噪声(9138×3)、计算TDF(79×64×49)
getSegmentationTDF.m 分割点云生成体素网格体积的准确TDF值
getKeypoints.m 物体模型分割点云中随机采样表面关键点,并保存到二进制文件
getDescriptors.m 调用编译好的get3DMatchDescriptors,为物体模型分割点云生成3DMatch描述子
runModelFitting.m 循环遍历每个场景(预扫描对象模型与场景点云分割之间的模型匹配实例),并进行基于RANSAC的几何配准以预测对象姿态
调用自己写的clusterCallback()函数
getError.m 计算”Shelf&Tote”基准数据集的预测6D姿态和真实标签之间的误差
clusterCallback.m函数 通过在两组3D关键点及其描述子之间运行基于RANSAC的几何配准,来预测物体模型分割点云之间的物体姿态
pointCloud2TDF.m函数 从点云计算TDF值
很慢

convertBenchmark2Scenarios.m

①复制$FromDir/$creativity_chenille_stems.1.segm.ply为$ToDir/$segmentation.ply
②尝试复制$FromDir/$creativity_chenille_stems.1.segmentation.TDF.bin为$ToDir/$segmentation.TDF.bin
③生成$ToDir/$info.txt

convertScenarios2Benchmark.m

根据$ToDir/$info.txt决定路径和文件名、根据$ToDir/$ransac.3dmatch.model2segm.txt决定文件里的数据,生成$FromDir/$creativity_chenille_stems.1.ransac.3dmatch.model2segm.txt

getModelTDF.m

从点云数据$ObjDir/$barkely_hide_bones.ply计算出TDF数据$ObjDir/$barkely_hide_bones.TDF.bin

getSegmentationTDF.m

读取$BenDir/$cam.info.txt、$BenRootDir/$labels.mat并计算姿态,读取点云$FromDir/$creativity_chenille_stems.1.segm.ply,计算TDF的值$FromDir/$creativity_chenille_stems.1.segmentation.TDF.bin

getKeypoints.m

①读取信息$ToDir/$info.txt(没用到)、点云数据$ToDir/$segmentation.ply(没用到)、TDF值$ToDir/$segmentation.TDF.bin,从中随机抽取1000个关键点并保存$ToDir/$segmentation.keypoints.bin
②读取点云数据$ObjDir/$barkely_hide_bones.ply(没用到)、TDF值$ObjDir/$barkely_hide_bones.TDF.bin,从中随机抽取1000个关键点并保存$ObjDir/$barkely_hide_bones.keypoints.bin

getDescriptors.m

①读取点云数据$ToDir/$segmentation.ply(没用到)、TDF值数据$ToDir/$segmentation.TDF.bin、关键点数据$ToDir/$segmentation.keypoints.bin,将关键点数据写到data.bin(1000×30×30×30,临时数据)中,修改网络架构tmp.json,运行网络、载入data.bin、生成feat.bin(临时数据),将描述子保存为$ToDir/$segmentation.keypoints.3dmatch.descriptors.bin
②读取点云数据$ObjDir/$barkely_hide_bones.ply(没用到)、TDF值数据$ObjDir/$barkely_hide_bones.TDF.bin、关键点数据$ObjDir/$barkely_hide_bones.keypoints.bin,将关键点数据写到data.bin(1000×30×30×30,临时数据)中,修改网络架构tmp.json,运行网络、载入data.bin、生成feat.bin(临时数据),将描述子保存为$ObjDir/$barkely_hide_bones.keypoints.3dmatch.descriptors.bin

getError.m

①读取物体姿态的预测值(1063×1)、真实标签(1043×1)3dmatch-apc-predictions.mat、testing-split.mat,物体名(39×1)objectNames.mat,物体名及其属性(39×1)$BenRootDir/$objects.mat

②计算预测的6D物体姿态表现(旋转/平移准确率)subsetAcc、2D物体分割表现(准确率/召回率)subsetSegmPrecRec
分门别类统计:总体、各个场景、不同程度的场景混乱(cluttered)、不同程度的场景遮挡(occluded)、物体形变(deformable)、物体失去深度、物体微弱(thin)

③打印结果

偏差计算方法☆:
旋转欧拉角的偏差errorRot:两个旋转矩阵之间的变换关系=>转为欧拉角=>转为角度=>转为绝对值=>处理角度为90、180、360的特殊情况=>计算平均值
平移向量的偏差errorTrans:两平移向量之间的欧氏距离
errorRot<15为真
errorTrans<0.05为真

clusterCallback.m

①读取文件信息$ToDir/$info.txt
②读取分割点云数据(12896×3)及其TDF值数据(87×60×49)$ToDir/$segmentation.ply、$ToDir/$segmentation.TDF.bin
③读取物体模型数据(246909×3)及其TDF值数据(113×61×48)$ObjDir/$creativity_chenille_stems.ply、$ObjDir/$creativity_chenille_stems.TDF.bin
④读取分割点云关键点(1000×3)、物体模型关键点(1000×3)$ToDir/$segmentation.keypoints.bin、$ObjDir/$creativity_chenille_stems.keypoints.bin
⑤读取分割点云关键点描述子(1000×512)、物体模型关键点描述子(1000×512)$ToDir/$segmentation.keypoints.3dmatch.descriptors.bin、$ObjDir/$creativity_chenille_stems.keypoints.3dmatch.descriptors.bin
⑥寻找两者之间的匹配最近点(168×3)
⑦使用RANSAC估计从物体模型到分割点云的刚性变换,并保存姿态估计数据$ToDir/$ransac.3dmatch.model2segm.txt

Mesh Correspondence in Shape2Pose

核心思想

核心思想:提出一种叫做3DMatch的自监督特征学习方法,通过一个3D卷积神经网络对训练样本的学习,得到一种局部体积块描述子,该描述子在关键点匹配上达到很好的效果且在新场景下具有很好的鲁棒性。

局部几何特征学习

用自监督的方法从RGBD三维重建数据集中学习局部特征描述子

三维数据表示

训练数据集

细节

参考

官方

内容 描述
原始论文:3DMatch 《3DMatch: Learning Local Geometric Descriptors from RGB-D Reconstructions》
代码:3dmatch-toolbox 基于Marvin(CUDA7.5、cuDNN5.1)、Matlab 2016a、OpenCV2.4.11、Ubuntu14
主页 有数据集下载链接
CVPR2017口头报告视频
4分钟介绍视频
代码:tsdf-fusion-python 基于pycuda的tsdf实现

博客

内容 描述
Marvin官网 普林斯顿大学维护的深度学习框架。C++,仅依赖CUDA 7.5和cuDNN 5.1
论文《一种改进的点云局部几何特征匹配方法_史魁洋》
使用深度学习进行点云匹配(一) 第1个示例(Demo: Align Two Point Clouds with 3DMatch)
使用深度学习进行点云匹配(二) 第2个示例(Converting 3D Data to TDF Voxel Grids)
使用深度学习进行点云匹配(三) 第3个示例(Training 3DMatch from RGB-D Reconstructions)
使用深度学习进行点云匹配(四) 更换数据跑第1个示例(Demo: Align Two Point Clouds with 3DMatch)
使用深度学习进行点云匹配(五) TDF的具体含义、如何训练3DMatch描述子
利用深度学习进行点云匹配(六) 孪生网络,第3个示例(Training 3DMatch from RGB-D Reconstructions)
KNN算法与Kd树
刚体变换
RANSAC算法详解
回环检测
三维重建中的表面模型构建—TSDF算法
下面是其他的链接
机器人视觉 移动机器人 VS-SLAM ORB-SLAM2 深度学习目标检测 yolov3 行为检测 opencv PCL 机器学习 无人驾驶
一文教你读懂3D目标检测
open3d文档 包含点云处理、KD树

从CUDA 7.5版开始,完全支持gcc 4.8,在Ubuntu 14.04和Fedora 21上支持4.9。
(实际装的Ubuntu14.04.5的gcc版本是4.8.4)
cuda和gcc版本不兼容

ubuntu14.04降级gcc/g++至4.9版本

gcc、g++降级的命令:

1
2
3
4
5
6
7
8
sudo apt-get install -y gcc-4.8
sudo apt-get install -y g++-4.8

cd /usr/bin
sudo rm gcc
sudo ln -s gcc-4.8 gcc
sudo rm g++
sudo ln -s g++-4.8 g++

compile.sh的作用:
把”demo.cu”编译成”demo”

自己跑数据
拷贝数据 3DAlignLego1_1.ply、3DAlignLego1_2.ply 到 /home/imv/Downloads/3dmatch-toolbox-master/data/mytest 下

命令:
cd /home/imv/Downloads/3dmatch-toolbox-master/core

生成关键点和描述子

./demo ../data/mytest/3DAlignLego1_1.ply 3DAlignLego1_1
./demo ../data/mytest/3DAlignLego1_2.ply 3DAlignLego1_2

./demo ../data/mytest/3DAlignLego1_1_ZoomUp_100_bin.ply 3DAlignLego1_1
./demo ../data/mytest/3DAlignLego1_2_ZoomUp_100_bin.ply 3DAlignLego1_2

运行”./demo ../data/sample/3dmatch-demo/single-depth-1.ply fragment-1”报错:

Loaded point cloud with 252179 points!
Size of TDF voxel grid: 370 x 253 x 324
Computing TDF voxel grid…
modprobe: ERROR: ../libkmod/libkmod.c:556 kmod_search_moddep() could not open moddep file ‘/lib/modules/4.4.0-146-generic/modules.dep.bin’
modprobe: ERROR: ../libkmod/libkmod.c:556 kmod_search_moddep() could not open moddep file ‘/lib/modules/4.4.0-146-generic/modules.dep.bin’
modprobe: ERROR: ../libkmod/libkmod-module.c:809 kmod_module_insert_module() could not find module by name=’nvidia_384_uvm’
modprobe: ERROR: could not insert ‘nvidia_384_uvm’: Function not implemented
CUDA failure at LINE 146: cudaError code 30: This indicates that an unknown internal error has occurred.
FatalError. Program Terminated.

原因貌似是内核版本不对,”/lib/modules”下只有”4.2.0-27-generic”,而非”4.4.0-146-generic”

查看系统版本
sudo lsb_release -a

查看linux内核版本
cat /proc/version

sudo apt-get install linux-image-4.4.0-146-generic

win10下编译: