IFS是分形的重要分支。它是分形圖像處理中最富生命力而且最具有廣闊應用前景的領域之一。這一工作最早可以追溯到Hutchinson於1981年對自相似集的研究。美國科學家M.F.Barnsley於1985年發展了這一分形構型系統,並命名為迭代函數系統(Iterated Function System,IFS),后來又由Stephen Demko等人將其公式化,並引入到圖像合成領域中。IFS將待生成的圖像看做是由許多與整體相似的(自相似)或經過一定變換與整體相似的(自仿射)小塊拼貼而成。
算法:
1.設定一個起始點(x0,y0)及總的迭代步數。
2.以概率P選取仿射變換W,形式為
X1=a*x0 + b*y0 + e
Y1=c*x0 + d*y0 + f
或
X1=(a * x0*cosf(c/180)) - (b * y0*sinf(d/180)) + e
Y1=(a * x0*sinf(c/180)) + (b * y0*cosf(d/180)) + f
3.以W作用點(x0,y0),得到新坐標(x1,y1)。
4.令x0=x1,y0=y1。
5.在屏幕上打出(x0,y0)。
6.重返第2步,進行下一次迭代,直到迭代次數大於總步數為止。
(1)三角形
class IFSTriangle : public FractalEquation { public: IFSTriangle() { m_StartX = 0.0f; m_StartY = 0.0f; m_StartZ = 0.0f; m_ParamA = 0.0f; m_ParamB = 0.5f; //'IFS碼賦值
m[0][0] = 0.5f; m[0][1] = 0; m[0][2] = 0; m[0][3] = 0.5f; m[0][4] = 0; m[0][5] = 0; m[0][6] = 0.333f; m[1][0] = 0.5f; m[1][1] = 0; m[1][2] = 0; m[1][3] = 0.5f; m[1][4] = 0.5f; m[1][5] = 0; m[1][6] = 0.333f; m[2][0] = 0.5f; m[2][1] = 0; m[2][2] = 0; m[2][3] = 0.5f; m[2][4] = 0.25f; m[2][5] = 0.5f; m[2][6] = 0.334f; } void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const { float a, b, c, d, e, f; //'仿射變幻中的系數
float R = (float)rand()/RAND_MAX; if (R <= m[0][6]) { a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5]; } else if (R <= m[0][6] + m[1][6]) { a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5]; } else { a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5]; } outX = (a * x) + (b * y) + e*FRACTAL_RADIUS; outY = (c * x) + (d * y) + f*FRACTAL_RADIUS; outZ = z; } bool IsValidParamA() const {return true;} bool IsValidParamB() const {return true;} void SetParamA(float v) { m_ParamA = v; m[2][1] = v; } void SetParamB(float v) { m_ParamB = v; m[2][0] = v; m[0][3] = v; } private: float m[3][7]; // '存放IFS碼
};
這里生成的是謝爾賓斯基三角形,但可以通過參數設置對其變形
(2)皇冠
class IFSCrown : public FractalEquation { public: IFSCrown() { m_StartX = 0.0f; m_StartY = 0.0f; m_StartZ = 0.0f; m_ParamA = 2.0f; //'IFS碼賦值
m[0][0] = 0.5f; m[0][1] = 0.5f; m[0][2] = 0; m[0][3] = 0; m[0][4] = 0; m[0][5] = 0; m[0][6] = 0.2f; m[1][0] = 0.5f; m[1][1] = 0.5f; m[1][2] = 0; m[1][3] = 0; m[1][4] = 0.5f; m[1][5] = 0; m[1][6] = 0.2f; m[2][0] = 0.25f; m[2][1] = 0.25f; m[2][2] = 0; m[2][3] = 0; m[2][4] = 2.0f; m[2][5] = 2.0f;m[2][6] = 0.3f; m[3][0] = 0.25f; m[3][1] = 0.25f; m[3][2] = 0; m[3][3] = 0; m[3][4] = -1.0f;m[3][5] = 2.0f;m[3][6] = 0.3f; } void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const { float a, b, c, d, e, f; //'仿射變幻中的系數
float R = (float)rand()/RAND_MAX; if (R <= m[0][6]) { a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5]; } else if (R <= m[0][6] + m[1][6]) { a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5]; } else if (R <= m[0][6] + m[1][6] + m[2][6]) { a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5]; } else { a = m[3][0]; b = m[3][1]; c = m[3][2]; d = m[3][3]; e = m[3][4]; f = m[3][5]; } outX = (a * x*cosf(c/180)) - (b * y*sinf(d/180)) + e*FRACTAL_RADIUS; outY = (a * x*sinf(c/180)) + (b * y*cosf(d/180)) + f*FRACTAL_RADIUS; outZ = z; } bool IsValidParamA() const {return true;} void SetParamA(float v) { m_ParamA = v; m[2][4] = v; m[2][5] = v; m[3][4] = 1 - v; m[3][5] = v; } private: float m[4][7]; // '存放IFS碼
};
(3)蘆葦
// 蘆葦
class IFSBulrush : public FractalEquation { public: IFSBulrush() { m_StartX = 0.0f; m_StartY = 0.0f; m_StartZ = 0.0f; m_ParamA = 10.0f; float k = m_ParamA*100.0f; //'IFS碼賦值
m[0][0] = 0.5f; m[0][1] = 0.5f; m[0][2] = 0; m[0][3] = 0; m[0][4] = 0; m[0][5] = 0; m[0][6] = 0.3f; m[1][0] = 0.5f; m[1][1] = 0.5f; m[1][2] = k; m[1][3] = k; m[1][4] = 1; m[1][5] = k/1600; m[1][6] = 0.3f; m[2][0] = 0.5f; m[2][1] = 0.5f; m[2][2] = 0; m[2][3] = 0; m[2][4] = 0.5f; m[2][5] = 0; m[2][6] = 0.4f; } void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const { float a, b, c, d, e, f; //'仿射變幻中的系數
float R = (float)rand()/RAND_MAX; if (R <= m[0][6]) { a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5]; } else if (R <= m[0][6] + m[1][6]) { a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5]; } else { a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5]; } outX = (a * x*cosf(c/180)) - (b * y*sinf(d/180)) + e*FRACTAL_RADIUS; outY = (a * x*sinf(c/180)) + (b * y*cosf(d/180)) + f*FRACTAL_RADIUS; outZ = z; } bool IsValidParamA() const {return true;} void SetParamA(float v) { m_ParamA = v; float k = m_ParamA*100.0f; m[1][2] = k; m[1][3] = k; m[1][5] = k/1600; } private: float m[3][7]; // '存放IFS碼
};
(4)萬花筒
// 萬花筒
class IFSPhantoscope : public FractalEquation { public: IFSPhantoscope() { m_StartX = 0.0f; m_StartY = 0.0f; m_StartZ = 0.0f; m_ParamA = 2.0f; float k = m_ParamA*100.0f; //'IFS碼賦值
m[0][0] = 0.2f; m[0][1] = 0.2f; m[0][2] = 0; m[0][3] = 0; m[0][4] = 0.7f; m[0][5] = 0; m[0][6] = 0.2f; m[1][0] = 0.2f; m[1][1] = 0.2f; m[1][2] = 0; m[1][3] = 0; m[1][4] =-0.7f; m[1][5] = 0; m[1][6] = 0.2f; m[2][0] = 0.2f; m[2][1] = 0.2f; m[2][2] = 0; m[2][3] = 0; m[2][4] = 0; m[2][5] = 0.7f; m[2][6] = 0.2f; m[3][0] = 0.2f; m[3][1] = 0.2f; m[3][2] = 0; m[3][3] = 0; m[3][4] = 0; m[3][5] = -0.7f; m[3][6] = 0.2f; m[4][0] = 0.85f; m[4][1] = 0.85f; m[4][2] = k; m[4][3] = k; m[4][4] = 0; m[4][5] = 0; m[4][6] = 0.2f; } void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const { float a, b, c, d, e, f; //'仿射變幻中的系數
float R = (float)rand()/RAND_MAX; if (R <= m[0][6]) { a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5]; } else if (R <= m[0][6] + m[1][6]) { a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5]; } else if (R <= m[0][6] + m[1][6] + m[2][6]) { a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5]; } else if (R <= m[0][6] + m[1][6] + m[2][6] + m[3][6]) { a = m[3][0]; b = m[3][1]; c = m[3][2]; d = m[3][3]; e = m[3][4]; f = m[3][5]; } else { a = m[4][0]; b = m[4][1]; c = m[4][2]; d = m[4][3]; e = m[4][4]; f = m[4][5]; } outX = (a * x*cosf(c/180)) - (b * y*sinf(d/180)) + e*FRACTAL_RADIUS; outY = (a * x*sinf(c/180)) + (b * y*cosf(d/180)) + f*FRACTAL_RADIUS; outZ = z; } bool IsValidParamA() const {return true;} void SetParamA(float v) { m_ParamA = v; float k = m_ParamA*100.0f; m[4][2] = k; m[4][3] = k; } private: float m[5][7]; // '存放IFS碼
};
(5)Tree
class IFSTree : public FractalEquation { public: IFSTree() { m_StartX = 0.0f; m_StartY = 0.0f; m_StartZ = 0.0f; //'IFS碼賦值
m[0][0] = 0.195f; m[0][1] =-0.488f; m[0][2] = 0.344f; m[0][3] = 0.433f; m[0][4] = 0.4431f; m[0][5] = 0.2452f; m[0][6] = 0.25f; m[1][0] = 0.462f; m[1][1] = 0.414f; m[1][2] =-0.252f; m[1][3] = 0.361f; m[1][4] = 0.2511f; m[1][5] = 0.5692f; m[1][6] = 0.25f; m[2][0] =-0.058f; m[2][1] =-0.07f; m[2][2] = 0.453f; m[2][3] =-0.111f; m[2][4] = 0.5976f; m[2][5] = 0.0969f; m[2][6] = 0.25f; m[3][0] =-0.035f; m[3][1] = 0.07f; m[3][2] =-0.469f; m[3][3] =-0.022f; m[3][4] = 0.4884f; m[3][5] = 0.5069f; m[3][6] = 0.2f; m[4][0] =-0.637f; m[4][1] = 0.0f; m[4][2] = 0.0f; m[4][3] = 0.501f; m[4][4] = 0.8562f; m[4][5] = 0.2513f; m[4][6] = 0.05f; } void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const { float a, b, c, d, e, f; //'仿射變幻中的系數
float R = (float)rand()/RAND_MAX; if (R <= m[0][6]) { a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5]; } else if (R <= m[0][6] + m[1][6]) { a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5]; } else if (R <= m[0][6] + m[1][6] + m[2][6]) { a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5]; } else if (R <= m[0][6] + m[1][6] + m[2][6] + m[3][6]) { a = m[3][0]; b = m[3][1]; c = m[3][2]; d = m[3][3]; e = m[3][4]; f = m[3][5]; } else { a = m[4][0]; b = m[4][1]; c = m[4][2]; d = m[4][3]; e = m[4][4]; f = m[4][5]; } outX = a*x + b*y + e; outY = c*x + d*y + f; outZ = z; } private: float m[5][7]; // '存放IFS碼
};
這個圖形我很喜歡,所以還專門將其生成圖像:
(6)大腦
class IFSBrain : public FractalEquation { public: IFSBrain() { m_StartX = 0.0f; m_StartY = 0.0f; m_StartZ = 0.0f; //'IFS碼賦值 //0.03 0 0 0.45 0 0 0.05; //-0.03 0 0 -0.45 0 0.4 0.15; //0.56 -0.56 0.56 0.56 0 0.4 0.4; //0.56 0.56 -0.56 0.56 0 0.4 0.4;
m[0][0] = 0.03f; m[0][1] = 0.0f; m[0][2] = 0.0f; m[0][3] = 0.45f; m[0][4] = 0.0f; m[0][5] = 0.0f; m[0][6] = 0.05f; m[1][0] =-0.03f; m[1][1] = 0.0f; m[1][2] = 0.0f; m[1][3] =-0.45f; m[1][4] = 0.0f; m[1][5] = 0.4f; m[1][6] = 0.15f; m[2][0] = 0.56f; m[2][1] =-0.56f; m[2][2] = 0.56f; m[2][3] = 0.56f; m[2][4] = 0.0f; m[2][5] = 0.4f; m[2][6] = 0.4f; m[3][0] = 0.56f; m[3][1] = 0.56f; m[3][2] =-0.56f; m[3][3] = 0.56f; m[3][4] = 0.0f; m[3][5] = 0.4f; m[3][6] = 0.4f; } void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const { float a, b, c, d, e, f; //'仿射變幻中的系數
float R = (float)rand()/RAND_MAX; if (R <= m[0][6]) { a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5]; } else if (R <= m[0][6] + m[1][6]) { a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5]; } else if (R <= m[0][6] + m[1][6] + m[2][6]) { a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5]; } else { a = m[3][0]; b = m[3][1]; c = m[3][2]; d = m[3][3]; e = m[3][4]; f = m[3][5]; } outX = a*x + b*y + e; outY = c*x + d*y + f; outZ = z; } private: float m[4][7]; // '存放IFS碼
};
------------------------------------
關於基類FractalEquation的定義及相關軟件見:混沌與分形