Assignment 0: Iterated Function Systems
1.实验要求
本次任务要求实现一个简单的迭代函数系统IFS类,通过给定的随机变化矩阵数据利用点阵生成简单的分形自相似图片。
2.算法原理
IFS算法的主要思想是认为物体的全局和局部在仿射变换的意义下具有自相似结构,通过对原始图像(生成元)的收缩、旋转、平移等变换形成的极限图形产生自相似的分形结构。在实验实现上,即生成一定数量的二维点,对于每一个点,随机在预先给定的transform中选取一个对点进行收缩仿射变换(伸缩+平移变换结合)。将变换后的点写入图像,即可得到分形结果。
3.实验步骤
本次任务较为简单,只需要实现IFS类的定义,对于图像处理以及向量矩阵变换的库均已给出。
-
IFS类的定义
IFS类包含3个私有变量,分别是用来存储transformation数量的num,存储具体变换矩阵的vector:transformation与存储选择对应变换矩阵的概率大小p,这些数值都由输入得到。
class IFS { private: int num; vector<Matrix> transformations; vector<double> p; public: IFS(); IFS(char* file); ~IFS(); void ReadFile(char* file); int GetIndex(double probability); void Render(Image& img, int pointNum, int iterations); };
IFS的成员函数
-
IFS(char file)*
类的构造函数:读入文件名,调用
ReadFile()
IFS::IFS(char* file) { ReadFile(file); }
-
~IFS()
析构函数,释放变量内存
IFS::~IFS() { delete &transformations; delete &p; }
-
void ReadFile(char file)*
解析变换矩阵的文件数据,读入相应的变换矩阵数据并计算累计概率
void IFS::ReadFile(char* file) { transformations.clear(); p.clear(); double tmp_p=0; // open the file FILE* input = fopen(file, "r"); assert(input != NULL); // read the number of transforms int num_transforms; fscanf(input, "%d", &num_transforms); num = num_transforms; // < DO SOMETHING WITH num_transforms > // read in the transforms for (int i = 0; i < num_transforms; i++) { float probability; fscanf(input, "%f", &probability); Matrix m; m.Read3x3(input); // < DO SOMETHING WITH probability and m > tmp_p += probability;//计算累计概率 transformations.push_back(m); p.push_back(tmp_p); } p[num_transforms - 1] = 1.00001;//人为处理浮点数误差 // close the file fclose(input); }
-
void Render(Image& img, int pointNum, int iterations);
主要的绘制函数,随机生成一定数量点的坐标并依据累计概率选择随机变换矩阵对点进行变换写入结果图像
void IFS::Render(Image& img, int pointNum, int iterations) { double tmp_x, tmp_y; int index; Vec2f tmp_point; for (int i = 0; i < pointNum; i++) { tmp_x = (double)rand() / RAND_MAX; tmp_y = (double)rand() / RAND_MAX; tmp_point.Set(tmp_x, tmp_y); //pick a random transform for (int j = 0; j < iterations; j++) { double probability= (double)rand() / RAND_MAX; index = GetIndex(probability); Matrix m = transformations[index]; m.Transform(tmp_point); } tmp_x = tmp_point[0]; tmp_y = tmp_point[1]; int tx = min((int)(tmp_point[0] * img.Width()), img.Width() - 1); int ty = min((int)(tmp_point[1] * img.Height()), img.Height() - 1); tx = max(tx, 0); ty = max(ty, 0); img.SetPixel(tx, ty, Vec3f(0, 0, 0)); } }
-