[TOC]
前置知识
在开始学习和应用以下内容之前,确保掌握相关的几何与代数基础、数值方法、微分方程求解、优化与拓扑以及相关工具的使用。
几何与代数
线性代数基础
推荐资源:
计算几何
计算几何涉及研究几何问题的计算方法和算法,包括点、线、面、多边形等对象的处理。
旋转变换
旋转变换主要研究物体在空间中的旋转操作,常用于计算机图形学和物理模拟中。
主成分分析与奇异值分解
主成分分析(PCA)和奇异值分解(SVD)是数据降维和特征提取的重要方法,在机器学习和数据分析中广泛应用。
数值方法
数值方法涉及求解数学问题的近似方法和算法,常用于科学计算和工程应用。
微分方程求解
微分方程求解包括常微分方程和偏微分方程的数值和解析求解方法,在物理、工程和经济学等领域应用广泛。
优化与拓扑
优化与拓扑研究最优解的寻找和几何结构的性质,常用于机器学习、网络分析和图像处理。
压缩感知(Compressed Sensing)
压缩感知(Compressed Sensing,CS)是一种信号处理技术,旨在以远低于奈奎斯特采样定理所需的采样率捕捉和重建信号。它利用信号的稀疏性和随机投影的理论,实现高效的数据采集和重建。压缩感知的核心思想是通过少量线性测量来获取信号,并利用优化算法从这些测量中重建原始信号。
基本原理
压缩感知基于以下三个主要原则:
稀疏性:信号在某个域(如时间域、频率域或小波域)中具有稀疏表示,即大部分系数为零或接近零。例如,自然图像在小波域中通常是稀疏的。
不相关性:测量矩阵与信号的稀疏基不相关。这意味着测量矩阵的行向量与信号的稀疏表示的列向量之间的内积接近于零。随机矩阵(如高斯矩阵或Bernoulli矩阵)通常满足这个条件。
非线性重建:通过求解一个优化问题,从少量的测量值中重建原始信号。通常采用凸优化方法,如(\ell_1)范数最小化来实现稀疏信号的重建。
数学描述
设信号$f(x) \in \mathbb{R}^N$在某个基${\Psi}$下具有稀疏表示,即${x} = \mathbf{\Psi} \mathbf{\theta}$,其中${\theta}$是稀疏系数向量。压缩感知通过线性测量获取信号:
$f{y} = \mathbf{\Phi} \mathbf{x} = \mathbf{\Phi} \mathbf{\Psi} \mathbf{\theta}$
其中,$y \in \mathbb{R}^M$是测量向量,${\Phi}$是测量矩阵,(M < N)。
重建信号可以通过求解以下优化问题来实现:
$
\min_{\mathbf{\theta}} |\mathbf{\theta}|_1 \quad \text{s.t.} \quad \mathbf{y} = \mathbf{\Phi} \mathbf{\Psi} \mathbf{\theta}
$
优势
- 高效数据采集:能够在低采样率下获取信号,从而减少数据传输和存储的负担。
- 鲁棒性:对噪声和丢失数据具有较强的鲁棒性。
- 广泛应用:在图像处理、医学成像(如MRI)、雷达系统、压缩传感网络等领域具有广泛应用。
实践应用
- 医学成像:在MRI中,通过减少采样点来加快成像速度,同时保持图像质量。
- 图像处理:在图像压缩和去噪中,通过稀疏表示实现高效处理。
- 无线传感器网络:在资源受限的无线传感器网络中,通过减少数据传输量延长电池寿命。
主要挑战
- 计算复杂度:重建算法通常需要求解复杂的优化问题,计算开销较大。
- 测量矩阵设计:选择合适的测量矩阵对重建性能影响较大。
相关工具使用
CMake——自动构建项目的工具
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| cmake_minimum_required(VERSION 3.10)
project(Rasterizer)
find_package(OpenCV REQUIRED)
set(CMAKE_CXX_STANDARD 17)
include_directories(/usr/local/include)
add_executable(Rasterizer main.cpp rasterizer.hpp rasterizer.cpp Triangle.hpp Triangle.cpp)
target_link_libraries(Rasterizer ${OpenCV_LIBRARIES})
|
配置CGAL库
一、安装 Boost
1. 下载 Boost
从 Boost C++ Libraries - SourceForge 下载合适版本。根据 Visual Studio 版本选择相应的 Boost 版本:
- VC2015 对应 14.0
- VC2017 对应 14.1
- VC2019 对应 14.2
例如,下载 boost_1_76_0-msvc-14.2-64.exe
。
2. 安装 Boost
运行下载的 boost_1_76_0-msvc-14.2-64.exe
文件,将 Boost 安装到指定目录,例如:D:\dev\boost_1_76_0
。
3. 配置环境变量
- 设置 Boost 的库目录和包含目录:
- 打开系统环境变量设置:
我的电脑
-> 属性
-> 高级系统设置
-> 环境变量
- 新建或编辑以下环境变量:
BOOST_LIBRARYDIR = D:\dev\boost_1_76_0\lib64-msvc-14.2
BOOST_INCLUDEDIR = D:\dev\boost_1_76_0
- 将 Boost 的库路径添加到系统环境变量
PATH
中:
- 在系统环境变量
PATH
中,添加 D:\dev\boost_1_76_0\lib64-msvc-14.2
二、下载并安装 CGAL
1. 下载 CGAL
从 CGAL GitHub Releases 页面下载 CGAL 安装程序,例如 CGAL-5.0.2-Setup.exe
。
2. 安装 CGAL
运行下载的 CGAL-5.0.2-Setup.exe
文件,按照安装向导完成安装。
3. 配置环境变量
安装完成后,将 CGAL 的 GMP 库路径添加到系统环境变量 PATH
中:
- 打开系统环境变量设置:
我的电脑
-> 属性
-> 高级系统设置
-> 环境变量
- 在系统环境变量
PATH
中,添加 D:\dev\CGAL-5.0.2\auxiliary\gmp\lib
三、配置VS2019属性页
1. 连接器 - 输入 - 附加依赖项
在 Visual Studio 中,配置项目属性页,添加以下附加依赖项:
1 2
| D:\dev\CGAL-5.0.2\auxiliary\gmp\lib\libmpfr-4.lib D:\dev\CGAL-5.0.2\auxiliary\gmp\lib\libgmp-10.lib
|
2. C/C++ - 常规 - 附加包含目录
在 Visual Studio 中,配置项目属性页,添加以下附加包含目录:
1 2 3
| D:\dev\CGAL-5.0.2\auxiliary\gmp\include D:\boost_1_76_0 D:\dev\CGAL-5.0.2\include
|
3. 测试代码
编写并运行以下测试代码,以确保配置正确并验证依赖项和包含目录的有效性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <iostream> #include <CGAL/Simple_cartesian.h> typedef CGAL::Simple_cartesian<double> Kernel; typedef Kernel::Point_2 Point_2; typedef Kernel::Segment_2 Segment_2; int main() { Point_2 p(1, 1), q(10, 10); std::cout << "p = " << p << std::endl; std::cout << "q = " << q.x() << " " << q.y() << std::endl; std::cout << "sqdist(p,q) = " << CGAL::squared_distance(p, q) << std::endl; Segment_2 s(p, q); Point_2 m(5, 9); std::cout << "m = " << m << std::endl; std::cout << "sqdist(Segment_2(p,q), m) = " << CGAL::squared_distance(s, m) << std::endl; std::cout << "p, q, and m "; switch (CGAL::orientation(p, q, m)) { case CGAL::COLLINEAR: std::cout << "are collinear\n"; break; case CGAL::LEFT_TURN: std::cout << "make a left turn\n"; break; case CGAL::RIGHT_TURN: std::cout << "make a right turn\n"; break; } std::cout << " midpoint(p,q) = " << CGAL::midpoint(p, q) << std::endl; return 0; }
|
配置PCL库
配置属性-调试-环境-添加:
1
| PATH=D:\PCL 1.11.1\\bin;D:\PCL 1.11.1\\3rdParty\FLANN\bin;D:\PCL 1.11.1\\3rdParty\VTK\bin;D:\PCL 1.11.1\\3rdParty\OpenNI2\Tools
|
C/C++-常规-SDL检查:否
C/C++-语言-符合模式:否
VC++目录一包含目录,添加7个include路径
1 2 3 4 5 6 7
| D:\PCL 1.11.1\include\pcl-1.11 D:\PCL 1.11.1\3rdParty\Boost\include\boost-1_74 D:\PCL 1.11.1\3rdParty\Eigen\eigen3 D:\PCL 1.11.1\3rdParty\FLANN\include D:\PCL 1.11.1\3rdParty\OpenNI2\Include D:\PCL 1.11.1\3rdParty\Qhull\include D:\PCL 1.11.1\3rdParty\VTK\include\vtk-8.2
|
VC++目录一库目录,添加6个ib路径
1 2 3 4 5 6
| D:\PCL 1.11.1\lib D:\PCL 1.11.1\3rdParty\Boost\lib D:\PCL 1.11.1\3rdParty\FLANN\lib D:\PCL 1.11.1\3rdParty\OpenNI2\Lib D:\PCL 1.11.1\3rdParty\Qhull\lib D:\PCL 1.11.1\3rdParty\VTK\lib
|
C/C++-预处理器-预处理器定义-添加:
1 2 3
| BOOST_USE_WINDOWS_H NOMINMAX _CRT_SECURE_NO_DEPRECATE
|
链接器一输入一附加依赖项—添加PCL和VTK的相关lib文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| pcl_commond.lib pcl_featuresd.lib pcl_filtersd.lib pcl_iod.lib pcl_io_plyd.lib pcl_kdtreed.lib pcl_keypointsd.lib pcl_mld.lib pcl_octreed.lib pcl_outofcored.lib pcl_peopled.lib pcl_recognitiond.lib pcl_registrationd.lib pcl_sample_consensusd.lib pcl_searchd.lib pcl_segmentationd.lib pcl_stereod.lib pcl_surfaced.lib pcl_trackingd.lib pcl_visualizationd.lib vtkChartsCore-8.2-gd.lib vtkCommonColor-8.2-gd.lib vtkCommonComputationalGeometry-8.2-gd.lib vtkCommonCore-8.2-gd.lib vtkCommonDataModel-8.2-gd.lib vtkCommonExecutionModel-8.2-gd.lib vtkCommonMath-8.2-gd.lib vtkCommonMisc-8.2-gd.lib vtkCommonSystem-8.2-gd.lib vtkCommonTransforms-8.2-gd.lib vtkDICOMParser-8.2-gd.lib vtkDomainsChemistry-8.2-gd.lib vtkDomainsChemistryOpenGL2-8.2-gd.lib vtkdoubleconversion-8.2-gd.lib vtkexodusII-8.2-gd.lib vtkexpat-8.2-gd.lib vtkFiltersAMR-8.2-gd.lib vtkFiltersCore-8.2-gd.lib vtkFiltersExtraction-8.2-gd.lib vtkFiltersFlowPaths-8.2-gd.lib vtkFiltersGeneral-8.2-gd.lib vtkFiltersGeneric-8.2-gd.lib vtkFiltersGeometry-8.2-gd.lib vtkFiltersHybrid-8.2-gd.lib vtkFiltersHyperTree-8.2-gd.lib vtkFiltersImaging-8.2-gd.lib vtkFiltersModeling-8.2-gd.lib vtkFiltersParallel-8.2-gd.lib vtkFiltersParallelImaging-8.2-gd.lib vtkFiltersPoints-8.2-gd.lib vtkFiltersProgrammable-8.2-gd.lib vtkFiltersSelection-8.2-gd.lib vtkFiltersSMP-8.2-gd.lib vtkFiltersSources-8.2-gd.lib vtkFiltersStatistics-8.2-gd.lib vtkFiltersTexture-8.2-gd.lib vtkFiltersTopology-8.2-gd.lib vtkFiltersVerdict-8.2-gd.lib vtkfreetype-8.2-gd.lib vtkGeovisCore-8.2-gd.lib vtkgl2ps-8.2-gd.lib vtkglew-8.2-gd.lib vtkGUISupportMFC-8.2-gd.lib vtkhdf5-8.2-gd.lib vtkhdf5_hl-8.2-gd.lib vtkImagingColor-8.2-gd.lib vtkImagingCore-8.2-gd.lib vtkImagingFourier-8.2-gd.lib vtkImagingGeneral-8.2-gd.lib vtkImagingHybrid-8.2-gd.lib vtkImagingMath-8.2-gd.lib vtkImagingMorphological-8.2-gd.lib vtkImagingSources-8.2-gd.lib vtkImagingStatistics-8.2-gd.lib vtkImagingStencil-8.2-gd.lib vtkInfovisCore-8.2-gd.lib vtkInfovisLayout-8.2-gd.lib vtkInteractionImage-8.2-gd.lib vtkInteractionStyle-8.2-gd.lib vtkInteractionWidgets-8.2-gd.lib vtkIOAMR-8.2-gd.lib vtkIOAsynchronous-8.2-gd.lib vtkIOCityGML-8.2-gd.lib vtkIOCore-8.2-gd.lib vtkIOEnSight-8.2-gd.lib vtkIOExodus-8.2-gd.lib vtkIOExport-8.2-gd.lib vtkIOExportOpenGL2-8.2-gd.lib vtkIOExportPDF-8.2-gd.lib vtkIOGeometry-8.2-gd.lib vtkIOImage-8.2-gd.lib vtkIOImport-8.2-gd.lib vtkIOInfovis-8.2-gd.lib vtkIOLegacy-8.2-gd.lib vtkIOLSDyna-8.2-gd.lib vtkIOMINC-8.2-gd.lib vtkIOMovie-8.2-gd.lib vtkIONetCDF-8.2-gd.lib vtkIOParallel-8.2-gd.lib vtkIOParallelXML-8.2-gd.lib vtkIOPLY-8.2-gd.lib vtkIOSegY-8.2-gd.lib vtkIOSQL-8.2-gd.lib vtkIOTecplotTable-8.2-gd.lib vtkIOVeraOut-8.2-gd.lib vtkIOVideo-8.2-gd.lib vtkIOXML-8.2-gd.lib vtkIOXMLParser-8.2-gd.lib vtkjpeg-8.2-gd.lib vtkjsoncpp-8.2-gd.lib vtklibharu-8.2-gd.lib vtklibxml2-8.2-gd.lib vtklz4-8.2-gd.lib vtklzma-8.2-gd.lib vtkmetaio-8.2-gd.lib vtkNetCDF-8.2-gd.lib vtkogg-8.2-gd.lib vtkParallelCore-8.2-gd.lib vtkpng-8.2-gd.lib vtkproj-8.2-gd.lib vtkpugixml-8.2-gd.lib vtkRenderingAnnotation-8.2-gd.lib vtkRenderingContext2D-8.2-gd.lib vtkRenderingContextOpenGL2-8.2-gd.lib vtkRenderingCore-8.2-gd.lib vtkRenderingExternal-8.2-gd.lib vtkRenderingFreeType-8.2-gd.lib vtkRenderingGL2PSOpenGL2-8.2-gd.lib vtkRenderingImage-8.2-gd.lib vtkRenderingLabel-8.2-gd.lib vtkRenderingLOD-8.2-gd.lib vtkRenderingOpenGL2-8.2-gd.lib vtkRenderingVolume-8.2-gd.lib vtkRenderingVolumeOpenGL2-8.2-gd.lib vtksqlite-8.2-gd.lib vtksys-8.2-gd.lib vtktheora-8.2-gd.lib vtktiff-8.2-gd.lib vtkverdict-8.2-gd.lib vtkViewsContext2D-8.2-gd.lib vtkViewsCore-8.2-gd.lib vtkViewsInfovis-8.2-gd.lib vtkzlib-8.2-gd.lib
|
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| #include <iostream> #include <vector> #include <ctime> #include <pcl/point_cloud.h> #include <pcl/octree/octree.h> #include <boost/thread/thread.hpp> #include <pcl/visualization/pcl_visualizer.h> using namespace std; int main(int argc, char** argv) { srand((unsigned int)time(NULL)); pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); cloud->width = 1000; cloud->height = 1; cloud->points.resize(cloud->width * cloud->height); for (size_t i = 0; i < cloud->points.size(); ++i) { cloud->points[i].x = 1024.0f * rand() / (RAND_MAX + 1.0f); cloud->points[i].y = 1024.0f * rand() / (RAND_MAX + 1.0f); cloud->points[i].z = 1024.0f * rand() / (RAND_MAX + 1.0f); }
pcl::octree::OctreePointCloudSearch<pcl::PointXYZ> octree(0.1); octree.setInputCloud(cloud); octree.addPointsFromInputCloud(); pcl::PointXYZ searchPoint; searchPoint.x = 1024.0f * rand() / (RAND_MAX + 1.0f); searchPoint.y = 1024.0f * rand() / (RAND_MAX + 1.0f); searchPoint.z = 1024.0f * rand() / (RAND_MAX + 1.0f);
vector<int>pointIdxRadiusSearch; vector<float>pointRadiusSquaredDistance; float radius = 256.0f * rand() / (RAND_MAX + 1.0f); cout << "Neighbors within radius search at (" << searchPoint.x << " " << searchPoint.y << " " << searchPoint.z << ") with radius=" << radius << endl; if (octree.radiusSearch(searchPoint, radius, pointIdxRadiusSearch, pointRadiusSquaredDistance) > 0) { for (size_t i = 0; i < pointIdxRadiusSearch.size(); ++i) cout << " " << cloud->points[pointIdxRadiusSearch[i]].x << " " << cloud->points[pointIdxRadiusSearch[i]].y << " " << cloud->points[pointIdxRadiusSearch[i]].z << " (squared distance: " << pointRadiusSquaredDistance[i] << ")" << endl; } boost::shared_ptr<pcl::visualization::PCLVisualizer>viewer(new pcl::visualization::PCLVisualizer("显示点云")); viewer->setBackgroundColor(0, 0, 0); pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ>target_color(cloud, 255, 0, 0); viewer->addPointCloud<pcl::PointXYZ>(cloud, target_color, "target cloud"); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "target cloud");
while (!viewer->wasStopped()) { viewer->spinOnce(100); boost::this_thread::sleep(boost::posix_time::microseconds(1000)); }
return (0); }
|
项目实践
一些常见问题
作为一名第一次接触计算图形学课程的学生,在学习GAMES102的过程中遇到了不少困难。由于已有一段时间没有使用过C++,编译和配置代码成了我最大的挑战之一。
下载链接失效导致的压缩包问题
在配置环境时,遇到的第一个问题是一个压缩包无法正确下载。由于原链接失效,导致花费了大量时间。在反复尝试并顺利编译生成后,代码却报了各种错误。经过仔细排查,终于发现问题出在这个压缩包上。
解决压缩包问题后的DLL缺失
压缩包问题解决后,运行程序时又提示缺少“luad.dll”。这种问题在网上很难找到明确的解决方法。尝试了各种途径,最终通过安装lua for Windows修复了这个问题。安装完成后,系统能够正确识别并加载“luad.dll”,程序也终于得以顺利运行。
相关资源
中国科学技术大学《计算机图形学》本科课程
GAMES: Graphics And Mixed Environment Symposium