数论部分讲稿

数论 讲义v1.0

数论 课件 v1.0

 

 

原创文章地址:【数论部分讲稿】转载时请注明出处mhy12345.xyz

数学部分讲稿

数学 讲义 v1.1
数学 习题

 

 

 

原创文章地址:【数学部分讲稿】转载时请注明出处mhy12345.xyz

我是如何和搜索引擎斗智斗勇的.WordPress速度优化

网站访问速度是搜索引擎衡量一个网站的核心因素,因为这在另一方面意味着用户点选这个词条的用户体验。因此,我们十分有必要优化Wordpress的速度。这里,我使用了WP Super Cache和Jetpack插件,WP Super Cache可以缓存你的博客页面,特别是对于匿名用户,不论如何,网站对匿名用户返回的始终是同一个页面,因此将他们缓存下来可以达到很好的效果(从原来的2s变成了几乎看不到延迟)。同时Jetpack插件提供了免费的CDN服务。也可以优化图片以及视频的加载速度。

原创文章地址:【我是如何和搜索引擎斗智斗勇的.WordPress速度优化】转载时请注明出处mhy12345.xyz

我是如何和搜索引擎斗智斗勇的.要有一个固定的域名

要有一个固定的域名

之前曾经提到百度将我的博客列为“用户不友好网站”,追溯其原因。回想之前对网站做的危险操作,不外乎变更子域名了。最初我的博客使用的是blog.mhy12345.xyz,提交了百度收录之后,我又心血来潮将站点的域名改变成了mhy12345.xyz。当时的想仅仅是,也许我改变了域名,搜索引擎自己会直接迁移过去blablabla,但是可能并不是这样。

从搜索引擎视角来看,首先出现了一个blog.mhy12345.xyz网站,接着有出现了一个冒充blog.mhy12345.xyz网站的另一个网站,内容完全相似。直接判定为抄袭站点。接下来发生的事情就更好解释了,百度只收录blog.mhy12345.xyz,我一怒之下,删去了对于blog.mhy12345.xyz的解析,剩下了一个mhy12345.xyz,而这个网站已经被搜索引擎判定为了恶意站点。然后……就没有然后了……(等等,为啥google就没有判断出错呢? 唔,毕竟百度不是世界一流互联网公司吧)

原创文章地址:【我是如何和搜索引擎斗智斗勇的.要有一个固定的域名】转载时请注明出处mhy12345.xyz

我是如何和搜索引擎斗智斗勇的.现状

自己写博客,特别是技术类博客,当然希望能够有其他人能够看到。我的第一篇正式文章Ubuntu 16.04 & Docker 搭建 WordPress 写于2017年4月,而到现在已经一年多了。大大小小杂文有七十于篇(怎么会那么多!?)自己认为很有用的也有大约10篇了。

有了足够的干货,当然希望更多人能够看到,这就依赖于搜索引擎了。然而搜索引擎却貌似并不买我的账。怎么说呢,google是个好公司啊,因为至少在我一点一点写博客这个时间段,google索引量在逐渐增加的,google给我带来了95%的搜索引擎索引量。而百度,甚至将我的博客列为了“用户不友好网站”==。想一想其实不无道理,google面向国外,有非常多的优质个人站点,所以理所当然赋予了个人站点更高的权值,反观百度的用户主体,国内,随随便便点开一个小站,各种广告网站满天飞,是我也想一枪毙掉所有的个人网站了。

 

原创文章地址:【我是如何和搜索引擎斗智斗勇的.现状】转载时请注明出处mhy12345.xyz

真实感图像渲染系列:小结

这是真实感图像渲染系列的第十篇文章。

这里写一写个人在编写过程中发现的一些坑,分享出来以免之后再踩吧。

  • CMake好啊,比Makefile好,可以很容易整合第三方库,但是……编译超级慢,别人的工程3s编译完成我的需要半分钟……
  • eps设多少确实是个坑,我设的是1e-7,但是得保证牛顿迭代的精度严格高于eps,否则焦点可能存在大于eps的误差,eps的设置就没有意义了
  • MAC的错误报告挺有用的 == 比如下面这个直接秒调

原创文章地址:【真实感图像渲染系列:小结】转载时请注明出处mhy12345.xyz

真实感图像渲染系列:相机(Camera)与景深效果(Field of Depth)

这是真实感图像渲染系列的第九篇文章。

普通相机模型

不同的相机模型中,有一个人眼位置和一个屏幕,对于屏幕中每一个像素,连接人眼和该像素位置得到一条射出光线。其2D示意图如下:

首先,一直屏幕像素坐标,以及屏幕本身在场景中的位置,我们可以计算出该像素的位置,如图中红点所述。接着,连接人眼和像素的光线就可以用于计算该光线的颜色。这一部分挺容易理解的。

带景深的相机模型

在普通相机模型的屏幕和人眼位置之外,带景深的相机模型额外存在一个焦平面。如下图所示

通过普通的相机模型,我们可以求得普通相机的光线的方向。

普通相机的光线一定会和焦平面在某个位置碰撞,为了达到景深效果,一方面,我们需要保证同一个像素对应的光线一定会击打到焦平面上的同一个点,另一方面,在焦平面之外的其他位置,同一个像素对应的光线应该击打到不同的点。

解决方案如下:我们求得在普通相机模型中,光线和焦平面的焦点,将该焦点景深相机模型的焦点。接下来,我们对光线的起始位置做一个微小扰动,并且修改光线方向使得光线恒定过焦平面上的点。这样,无论初始光线如何扰动,焦平面上的点都可以最清晰的表现出来。而不在焦平面上的点,会产生随机的模糊效果。

 

 

原创文章地址:【真实感图像渲染系列:相机(Camera)与景深效果(Field of Depth)】转载时请注明出处mhy12345.xyz

真实感图像渲染系列:贝塞尔曲线旋转体与直线求交

这是真实感图像渲染系列的第八篇文章。

概述

贝塞尔曲线是一个由多个控制点组合而成的曲线。在本文探讨的贝塞尔曲线,是由多条简单的4阶贝塞尔曲线拼接而成。绕z轴旋转贝塞尔曲线,我们可以得到一个旋转体曲面,该曲面就是待渲染的参数曲面。本文将探讨如何使用牛顿迭代法与直线求交。求交过程中

  1. 关于迭代初值的求法
  2. 迭代中的一些优化技巧
  3. 关于浮点数精度误差eps的求法。

贝塞尔曲线的定义

贝塞尔曲线是一个由多个控制点组合而成的曲线,n阶贝塞尔曲线定义为

(1)   \begin{equation*}  P(u) = \left[ \begin{matrix}P^{(x)}(u) \\ P^{(y)}(u) \end{matrix} \right] = \left[ \begin{matrix} \sum _{i=0}^n P_i^{(x)} C(n,i) (1-u)^{n-i}u^i \\ \sum _{i=0}^n P_i^{(y)}C(n,i) (1-u)^{n-i}u^i \end{matrix} \right] \end{equation*}

式(1)定义了该曲线P(u)的关于参数u \in [0,1]的参数方程,其中P_i为n个曲线的控制点。当我看到这个公式的时候,整个人都已经懵掉了。实际上理解起来并不复杂。

函数P(u)由参数u定义了一个二维向量,其中P^{(x)}P^{(y)}相互独立。只需要理解其中一个的产生式即可。考虑函数 f_i(u) =C(n,i) u^i (1-u)^{n-i-1},发现这f_0(u),f_1(i),\cdots,f_{n-1}(u)实际上是一个和为1的数列,数列在杨辉三角形中定义。换句话来说,f_i(u)实际上可以得到一个权值的分配,使用f_i(u)对于所有的控制点P_i加权平均,就是贝塞尔曲线尝试完成的事情。当f_0(u) = C(n,0) u^0 (1-u)^{n-i} = 1权值全部分配给了P_0,因此贝塞尔曲线的起点(u=0)和P_0重合。

贝塞尔曲线旋转体

在三维空间中,我们通过旋转贝塞尔曲线得到一个曲面。曲面强制对z轴旋转对称。(注:在代码中是对x轴旋转对称,不过z轴对称相对好理解一些)。

(2)   \begin{equation*}  S(u,\theta) = \left[ \begin{matrix} Q_x + sin\theta P^{(x)}(u) \\ Q_y + cos\theta P^{(x)}(u) \\ Q_z + P^{(y)}(u) \end{matrix} \right] \end{equation*}

一个贝塞尔曲线旋转体要能够成功渲染,其核心就是需要支持与光线的求交。光线我们使用(rayO,rayD)表示,rayO表示光线起点,rayD表示光线方向,是一个单位向量。则光线上一点可表示为C(t),满足:

(3)   \begin{equation*}  C(t) = rayO + t \times rayD \end{equation*}

倘若直线C(t)S(u,\theta)相交,则有

(4)   \begin{equation*}  F(t,u,\theta) = C(t) - S(u,\theta) = 0 \end{equation*}

其中,F(t,u,\theta)t,u,\theta的函数,要求t>00\leq u \leq 1,原问题可转化为求函数零点问题。函数零点问题使用牛顿迭代解决。

(5)   \begin{equation*}  x_{i+1} = x_i - [F'(x_i)]^{-1} \cdot F(x_i) \end{equation*}

其中F'(x_i)为函数F(x_i)的Jacobian矩阵,定义为:

(6)   \begin{equation*}  \frac{\partial F}{\partial t} = \left[ \begin{matrix} \frac{\partial F_1}{\partial t} & \frac{\partial F_1}{\partial u} & \frac{\partial F_1}{\partial \theta} \\ \frac{\partial F_2}{\partial t} & \frac{\partial F_2}{\partial u} & \frac{\partial F_2}{\partial \theta} \\ \frac{\partial F_3}{\partial t} & \frac{\partial F_3}{\partial u} & \frac{\partial F_3}{\partial \theta} \\ \end{matrix} \right] \end{equation*}

要试图计算出式(\ref(eq:jacobian)),我们需要分别求出F(t,u,\theta)对于t,u,\theta偏导数的每一个分量的值(共九个)。结果为:

(7)   \begin{equation*}  \frac{\partial F}{\partial args} = \left[ \begin{matrix} rayD_x & -sin\theta \frac{dP_x}{du} & -cos\theta P_x(u)\\ rayD_y & -cos\theta \frac{dP_x}{du} & +sin\theta P_x(u)\\ rayD_z & -\frac{dP_y}{du} & 0\\ \end{matrix} \right] \end{equation*}

其中\frac{dP}{du}是对于式子(1)按照最原始的求导法则求导的结果。

贝塞尔曲面物体设计

如图

共6条4阶贝塞尔曲线,每一条由绿蓝红绿四个控制点定义。

注意事项

  1. 牛顿迭代需要保证答案中u \in [0,1],而牛顿迭代本身无法附加条件,因此需要在答案的邻域中查找合适的u,t,\theta,我用到的方法是,对于给定曲线,生成一个圆柱体包含框,随机该圆柱体里面高度h的一个圆形面片,将光线与该面片的交点的u,t,\theta作为迭代的初值。随机h约30次即可得解。
  2. 由于牛顿迭代不太精确,可能是的结果产生微小偏移,这种偏移会对判断点在平面哪一侧产生影响,我们可以通过调整eps的取值,不同部分赋予不同的eps,使得这些误差不至于相互影响。
  3. 贝塞尔曲线求交本身费时间,但是判断是否一定没有交点却相对简单。可以求出贝塞尔曲线旋转体的“圆柱体包围盒”,(更精确的话,可以是空心圆柱体包围盒)。然后判断直线是否与包围盒有交点。判断直线与圆柱交点P = rayO + k \times rayD的位置,可以先讲所有东西映射到z=0屏幕,这是变成2维直线和圆求交,算出k,回带到三维情况验证。
  4. 实际上,像本文采用的多条低阶贝塞尔曲线求交并不明智,倘若将本文那个碗的6条贝塞尔曲线改为1条简单一些的曲线,然后做一个玻璃杯什么的,渲染效率将提高6倍!

 

 

原创文章地址:【真实感图像渲染系列:贝塞尔曲线旋转体与直线求交】转载时请注明出处mhy12345.xyz

真实感图像渲染系列:使用OpenMP并行优化渲染

这是真实感图像渲染系列的第七篇文章。

如果将渲染修改为并行,那么渲染效率将提升约8倍(我的电脑是八核)。非常非常有诱惑力。而且基于OpenMP框架的并行化甚至还非常简单!

平台编译

使用OpenMP最麻烦的地方是框架安装问题,倘若本机的g++版本支持 -fopenmp ,那么恭喜你,你已经完成了90%的工作了。倘若本机g++不支持该编译选项,那么需要在网上搜索对应的安装方法。安装方法不同系统都有较大的差别,故不在这里细讲。

OpenMP程序并行化指令都是用 #pragma 实现的,也就是说倘若编译器不支持,也不会产生什么问题。

OpenMP简单使用

这是一个最简单的for语句,对应于PPM算法中的光子映射。

该for语句满足如下条件:

  • 循环起始位置和终结位置确定
  • 不同的循环没有依赖性,

满足这样条件的for语句,理论上,将循环不同的i并行处理是没有问题的。OpenMP使用了最简单的预编译指令帮助我们实现for语句的并行,修改为

OpenMP临界区设置

#pragma omp critical 编译器将自动将 #pragma 指令后面紧接着的语句块进行并行。

一般来说,并行语句块内使用的变量,都是读写局部变量以及读全局变量,这时,不会存在什么问题,但是总有特殊情况,我们多个并行的循环需要修改同一个全局变量。这是可能导致错误的。如PPM算法中,计算“视点”,需要将结果保存在全局数组 view_pts 里面。这时,多个线程并行修改会导致一些问题(诸如SegmentationFault)。这时,使用 #pragma omp critical 可以强制后面紧接着的那个语句块通过“加锁”保证同时只有一个线程在运行该代码块。

 

原创文章地址:【真实感图像渲染系列:使用OpenMP并行优化渲染】转载时请注明出处mhy12345.xyz

真实感图像渲染系列:渲染可视化

这是真实感图像渲染系列的第六篇文章。

动机

一幅图片渲染时间少则一分钟,多则半天,等到渲染完成再看效果未免也太佛系了。况且诸如PPM算法亮度调节什么的一般在前两轮的时候,就已经大概知道了,并不需要渲染完。因此我们希望写一个实时显示渲染效果的类。

实现

显示部分在技术上没有任何难度,就是OpenCV中的imshow而已,如果必要,每次imshow之前,使用imwrite备份图片到文件。

我们需要一边显示一遍渲染,这个就需要多线程了。由于opencv的限制,imshow和waitKey只能在主线程调用,因此我们把图像渲染放在子线程里面去。这里线程的创建我使用了pthreads库。

具体细节就看代码啦。init函数传入一个Color类数组的指针,而PaintBoard能够实时监测该指针指向内容的变化,并且显示出来。(需要用户在窗口按回车键刷新)

 

 

原创文章地址:【真实感图像渲染系列:渲染可视化】转载时请注明出处mhy12345.xyz