深入理解计算机系统CMU-15213 CSAPP(二):DataLab
在国庆假期最后一天拾起一下一年前没做完的事情,尝试继续完成CSAPP的Lab,同时每个lab中都会结合原书补充一些细节知识。
实验目的
DataLab主要围绕数据表示设计,涉及到数据的按位运算和浮点数转化等知识,设计者希望我们修改bits.c文件中的函数,使得函数实现相应的目的。此外,每个函数会限制要用的运算符和数量,根据要求完成即可。当完成此节,你会对位运算刮目相看。尤其推荐通过其中的浮点数实验和本文描述了解浮点数存储细节,我相信这是没有之一的最详细和科学的描述。如有不当,欢迎指正。
具体实现
与和非实现异或
根据异或的卡诺图,可知:A^B = (A & ~B) | (~A & B)
而根据与或关系的转换:C | D = ~(~C & ~D)
所以有:A^B = ~(~(A & ~B) & \~(~A & B))
故有: 1234567891011//1/* * bitXor - x^y using only ~ and & * Example: bitXor(4, 5) = 1 * Legal op ...
OpenGL C++记录(二):基本渲染与着色器
根据LearnOpenGL记录了OpenGL的基本入门,初衷只是想接触一些计算机图形学内容,该系列估计最多只会到坐标变换一节,完整学习可移步原教程。
基本程序
OpenGL的入门打印不再是Hello
World了,其牵扯到比较多的概念,完整的一个基本程序如下,做了很多事情,但是效果上仅仅输出一个空白灰绿框以及打印了OpenGL版本信息。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374#include<glad/glad.h>#include<GLFW/glfw3.h> #include<iostream> // settingsconst unsigned int SCR_WIDTH = 800;const unsigned int SCR_HEIGHT = 600; const unsigned int VIEW ...
OpenGL C++记录(一):基于MinGw的环境搭建
OpenGL环境搭建
OpenGL(Open Graphics
Library)是一个2D、3D图形渲染库,它实际上并不是一种API,而是一种标准规范,规定了每个接口应该提供什么样的功能,也就是说它不关心内部实际实现,因为不同平台、不同设备上的接口实现总是不一样的,不同的系统、显卡、显卡驱动,都要求按照不同的系统API实现开发所需的对象创建和管理、音视频处理等,对编程者要求较高,因此OpenGL引入了各种库,例如GLUT,SDL,SFML和GLFW等,用于抽象和屏蔽底层的实现差异,实现使用统一的接口调用不同平台API的方法。
也由于OpenGL实现随平台变化的特点,显卡、驱动版本、系统版本都可能导致一些函数失效,或者通过宏支持新的函数功能,因此大多数函数的运行地址是运行期才真正确定,导致OpenGL的函数逻辑需要经过寻找函数指针-绑定对象-创建/操作对象的过程,例如在windows上,需要通过wglGetProcAddress获取函数指针再使用:
1234567// 定义函数原型typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);/ ...
设计模式(四):组合模式、责任链模式、策略模式
组合模式(Composite Pattern)
当集体对象和单一对象有功能上的相似时,使用组合模式可以为集体和单一对象提供统一的操作接口,例如文件系统,对文件夹和文件的操作,删除文件夹实际上是对文件夹中的文件进行删除;这种情况下使用组合模式有若干优点:
提供统一的操作,减少代码量;
树形的管理架构,除了文件系统,很多系统的组织与此类似,例如公司、军队等组织的管理系统;
易于扩展(开闭原则,对扩展开放,对修改封闭),一是能够容下多个层级关系,而无需每层独立一个类管理;二是添加层级和操作对象,都只要增加非叶子层级或者叶子、非叶子的操作接口即可。
组织模式将类结构组织成树形的架构,单一的对象称为叶子对象,由单一对象组成的集体对象称为组件或者容器,单一对象之下没有对象,组件对象之下可以是更细分的组件对象,也可以是某单一对象,其中抽象类定义了叶子对象和组件的类似特性,将组织架构中最大的组件定义为根,模拟一个组件模式的军队架构组织如下:
12345678910111213141516171819202122232425262728293031323334353637383940 ...
矩阵求导
函数与变元(自变量)
标量函数f
标量函数的自变量可以是标量、向量和矩阵。常见的函数形式以标量形式给出:
但仅使用标量方程不足以方便描述各种数学关系,所以拓展成向量和矩阵方程的形式:
向量形式:假设(列向量),由二次型分解知
矩阵形式:假设,有:
向量函数
向量函数的自变量同样可以分成标量、向量和矩阵。
标量作自变量:
向量作自变量:
矩阵作自变量:
矩阵函数F
矩阵函数的自变量同样可以分成标量、向量和矩阵。
标量自变量:
向量自变量:
矩阵自变量:
分子布局与分母布局
向量、矩阵这种多维变量互相求导,元素的个数实际上是确定的,关键是如何进行元素排列,主要是讨论分子布局和分母布局。
总结了几个结论:
分母和分子布局的本质就是由谁的维度来决定行数。分母布局下,假如分母是m维向量,那么结果就是m行,假如分母是m×n矩阵,那么结果就是mn行,分子布局同理;
标量函数求导,使用的是分母布局(分母可能是向量、矩阵,维度较高);
向量、矩阵函数对标量求导,使用的是分子布局(分子为向量、矩阵,维度较高);
向量对向量求导,没有断论 ...
不积代数,无以至千里:线性代数基础
在图像处理/数据优化/机器学习方法方面,看了一些需要代数背景的代码比较糊涂,决定以个人视角记录一些线性代数基础,也是想做很久的一件事。参考了多方资料,包括宋浩线性代数(理解细节参考)、张宇线性代数(排版、总结、详略、公式非常好)以及来自MIT的线性代数课程(思想、与工程结合性出众),可能比较综合(杂乱)。
逐渐更新。
矩阵基础
矩阵的定义不值一提,但从不同视角看待更容易理解矩阵的本质。
行图像(Row
Picture)与列图像(Column Picture)
平时习惯以行图像的时间看待矩阵,例如上述矩阵可以看成线性方程组的求解,对于二维矩阵求的是两直线的交点,三维则求三个面的交点:
解的存在性和个数取决于交点的存在性和分布规律。
列图像将矩阵看成是列向量的线性组合:
解的存在性和个数取决于两个向量的线性组合是否可达至目标向量。
如果目标向量B是任意的,从行向量看代表两条直线关系是随机的,如果是三维,则代表了空间中三个平面的关系是随机的;而从列图像理解更容易得多,因为其系数矩阵是不变的,无论是二维还是n维空间,关键在于系数向量的线性组合是否能够表示n维空间中任 ...
数值分析:多项式的最小二乘法拟合
多项式拟合-最小二乘法
代数角度
这个方法爱看不看,看了基本也没用。
最小二乘法使用多项式拟合样本数据,其基本代数原理以下。
假设使用的是m阶多项式拟合,那么在的估计值为:
其误差表示为:
那么对于n个样本点,使用平方和误差量化,该误差就是数据的优化目标,自变量为各阶的权值w,有:
求E(w)极小值,需对其求偏导,为:
有:
权重系数与i无关,可以写成:
同样的,此为一个约束条件,对于m阶的多项式,存在m+1项的偏导联合约束,所以有:
写成矩阵表达式:
C++实现
如下: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869#include <opencv2/opencv.hpp>#include <iostream>#include <math.h>using namespace std;using ...
OpenCV C++记录(十四):距离变换与基于标记的分水岭算法
距离变换算法
距离变换算法是基于二值化图像转换,得到与前景输入类似的灰度图,其基本原理是计算前景像素(255)到背景像素(0)的最小距离,背景像素值的距离仍然为0,距离变换算法能简单地在图像生成前景特征,在图像分割、特征提取中有重要作用,此处所说的距离是三种经典距离,在前面文章OpenCV
C++记录(八):Sobel、Scharr、Laplacian、Canny算子简单提过,其数学特征是:
欧氏距离(DIST_L2):
曼哈顿距离(城市距离,DIST_L1):
棋盘距离(切比雪夫距离,DIST_C)
三种距离定义
OpenCV实现
OpenCV提供了距离变换接口,可以计算二值图的前景和背景距离灰度分布情况:
123456void distanceTransform(cv::InputArray src, //输入二值化图 cv::OutputArray dst, //输出距离 int distanceType, //三种类型距离 int maskSize, //掩图大小,一般为3 int ds ...
OpenCV C++记录(十三):角点检测算法与亚像素优化
角点是图像的重要特征,往往比边缘和平坦区域具有更独一无二的特征,例如在拼图时,我们往往会先寻找物体对象的角点,最后再完善边缘和平坦区域,对于图像的特征检测亦是如此,角点检测是重要一环。
Harris角点检测
基本原理
1988年,Chris Harris和Mike
Stephens提出了角点检测的方法,称为Harris角点检测,其基本思想是考虑窗口到各个方向的灰度差异总和,表示为:
窗口权值函数灰度增量函数灰度函数
权值函数既可以是普通窗口,也可以是与中心距离相关的高斯窗口。
其中增量项可以根据二元一阶泰勒展开成偏导项Ix和Iy和二阶无穷小:
故原式等于:
此处令M = ,
可根据其特征值进一步判断某区域是平坦还是出现边缘还是角点,Harris检测响应公式:
此处的特征值可以理解成两个正交方向的变化率,结论如下:
当|R|很大,为角点,因为此时λ1和λ2均很大,说明两个正交方向都有大的变化率;
当|R|很小,为平坦区,此时λ1和λ2都很小,两个正交方向变化率军均很小;
当R<0,
为边缘,说明λ1和λ2其中一个很小,只有一个方向存在变化率 ...
OpenCV C++记录(十二):齐次坐标、相机成像模型与张正友标定
齐次坐标
在视觉处理的一些数学原理中,常常看见齐次坐标的身影。所谓齐次坐标,是在原来笛卡尔坐标的基础上增加一个维度,例如二维笛卡尔坐标(x,y)对应的齐次坐标为(x,y,1),以此类推,三维笛卡尔坐标(x,y,z)对应齐次坐标(x,y,z,1)。之所以使用齐次坐标,首先其能更方便地描述和求解几何关系,再者从2D到3D的变换,使用齐次坐标能表示一些二维空间难以表述的数学关系,例如无限远、两条平行线的交点(透视变换),其能够做到以下事情。
对点、线、平面关系的描述
点在线上、点在面上
一条二维直线的方程可以表示为: : 使用向量表示其系数,为:
所以对于任意点p(x,y),其对应齐次坐标为(x,y,1),p在直线上的充要条件是满足二者内积为0:
同理,对于三维情况,表示空间点p(x,y,z)在平面A上:
二维线交点与共线
齐次坐标还可以方便地表达两条二维直线的交点以及确定两点所在的直线方程,结论是:
1.
两条直线的系数向量叉乘等于其交点的齐次坐标
证明:假设直线、,易知两个系数向量的叉乘得到的向量同时垂直于和,故其内积为0,结合点在线上的充要条件:
...