分形/计算机图形技术/2D/变换
外观
< 分形 | 计算机图形技术/2D
平面变换
2D 光栅图形中的映射是一个复杂的函数 ,它将复平面映射到复平面。
它被实现为点变换。
它通常表示为
其中
- 是复平面的一个点(输入)
- 是图像复平面的一个点(输出 = 结果)
例如,墨卡托:[3]
function Spherical_mercator(x, y) {
return [x, Math.log(Math.tan(Math.PI / 4 + y / 2))];
}
function transverseMercatorRaw(lambda, phi) {
return [log(tan((halfPi + phi) / 2)), -lambda];
}
transverseMercatorRaw.invert = function(x, y) {
return [-y, 2 * atan(exp(x)) - halfPi];
};
如果有人使用离散几何(多边形和折线),那么投影就很难实现。必须在精度和性能之间取得平衡。 [4]
// https://github.com/adammaj1/Mandelbrot-Sets-Alternate-Parameter-Planes/blob/main/src/lcm/d.c
// projection from p to c
complex double map_parameter(const ParameterTypeT ParameterType, const complex double parameter){
complex double p;
// plane transformation
switch(ParameterType){
case c_identity :{p = parameter; break;}
case c_inverted :{p = 1.0/parameter; break;}
case c_parabola :{p = 0.25+ 1.0/parameter; break;}
case c_Myrberg_type :{p = cf - 1.0/parameter; break;}
case c_inverted_2_type :{p = -2.0 + 1.0/parameter; break;}
case c_exp :{p = cf + cexp(parameter) ; break;} // here one can change cf to get different image
case lambda_identity :{ p = parameter; break;}
case lambda_inverted_type :{p = 1.0/parameter; break;}
case lambda_inverted_1_type :{p =1.0+ 1.0/parameter; break;}
default: {p = parameter;}
}
映射分类
- 基于对象的映射(图像对象是具有相同整数值的连接像素集)
- 基于像素的映射
2D 图形中的变换(映射)
- 基本类型
- 复合变换[5]
矩阵的使用
- 不使用矩阵(使用函数)
- 使用矩阵
坐标
- 使用笛卡尔坐标
- 使用齐次坐标
- "矩阵乘法不满足交换律。变换的顺序至关重要——旋转后平移与平移后旋转截然不同" [6]
实现
-
行
-
列
为了用矩阵表示仿射变换,我们可以使用齐次坐标。这意味着将 2 向量 (x, y) 表示为 3 向量 (x, y, 1),更高维度也是如此。
变换名称 | 仿射矩阵 | 示例 |
---|---|---|
恒等(变换到原始图像) | ||
平移 | ||
反射 | ||
缩放 | ||
旋转 | 其中 θ = π6 =30° | |
剪切 |
仿射变换适用于将两幅或多幅图像对齐(配准)的配准过程。一个图像配准的例子是全景图像的生成,全景图像是多幅拼接在一起的图像的产物。
关于原点按比例因子缩放物体
变为
缩放
- 均匀(在缩放时保持物体的比例):sx = sy
- 非均匀:sx != sy
在保持固定中心点的情况下调整物体大小 = 关于其自身中心缩放物体
- 宽度' = 宽度 * sx
- 高度' = 高度 * sy
- 计算中心点的角坐标
复数平移是一个映射[7]
其中
使用这种系统,平移可以用矩阵乘法表示。 函数形式
变为
旋转
[edit | edit source]绕原点以角度 θ 逆时针(正方向)旋转的函数形式为
.
写成矩阵形式,就变成了:[8]
类似地,绕原点顺时针(负方向)旋转的函数形式为
矩阵形式为
这些公式假设x轴指向右侧,y轴指向上方。
归一化坐标下的逆时针旋转矩阵
没有矩阵的 C 代码
/*
C program to rotate an object by a given angle about a given point
gcc r.c -Wall -Wextra -lm
./a.out
*/
#include <stdio.h>
#include <math.h>
#include <complex.h> // complex numbers : https://stackoverflow.com/questions/6418807/how-to-work-with-complex-numbers-in-c
//The sin() function returns the value in the range of [-1, 1]
/*
https://stackoverflow.com/questions/2259476/rotating-a-point-about-another-point-2d
First subtract the pivot point (cx,cy), then rotate it (counter clock-wise), then add the point again.
*/
complex double rotate_point(const complex double center, const double angle_in_radians, const complex double point )
{
// translate point to center
complex double translated_point = creal(point) - creal(center) + (cimag(point) - cimag(center))*I;
// rotate point counter clock-wise by a given angle about a given pivot point ( center)
double s = sin(angle_in_radians);
double c = cos(angle_in_radians);
complex double new_point = creal(translated_point) * c - cimag(translated_point) * s + (creal(translated_point) * s + cimag(translated_point) * c)*I;
// translate point back
new_point = creal(new_point) + creal(center) +(cimag(new_point) + cimag(center))*I;
return new_point;
}
#define kMax 6
// center, angle_rad, point
double examples[kMax][5] = {
{50,-50, -0.7853982, 100,100 },
{50,-50, -0.7853982, 100,200 },
{50,-50, -0.7853982, 200,200 },
{0,0, 1.570796, 100,100},
{0,0, 1.570796, 150,200},
{0,0, 1.570796, 200,200}
};
int main(void){
int k;
complex double center ;
double angle_r ;
complex double point ;
complex double rotated_point;
for (k=0; k<kMax; ++k){
center = examples[k][0] + examples[k][1] * I ;
angle_r = examples[k][2];
point = examples[k][3] + examples[k][4] * I ;
rotated_point = rotate_point(center, angle_r, point );
fprintf(stdout, "point %f%+f*I rotated about %f%+f*I by %f radians is %f%+f*I \n", creal(point), cimag(point), creal(center), cimag(center), angle_r, creal(rotated_point), cimag(rotated_point));
}
return 0;
}
输出
point 100.000000+100.000000*I rotated about 50.000000-50.000000*I by -0.785398 radians is 191.421359+20.710673*I point 100.000000+200.000000*I rotated about 50.000000-50.000000*I by -0.785398 radians is 262.132040+91.421348*I point 200.000000+200.000000*I rotated about 50.000000-50.000000*I by -0.785398 radians is 332.842715+20.710668*I point 100.000000+100.000000*I rotated about 0.000000+0.000000*I by 1.570796 radians is -99.999967+100.000033*I point 150.000000+200.000000*I rotated about 0.000000+0.000000*I by 1.570796 radians is -199.999951+150.000065*I point 200.000000+200.000000*I rotated about 0.000000+0.000000*I by 1.570796 radians is -199.999935+200.000065*I
其他有趣的映射
[edit | edit source]-
带有 python 代码
- Jason Davies:地图
- 桶形失真
- 螺旋形[11]
- 对数极坐标图 [12]
- 抛物柱面坐标 [13]
- 抛物线坐标[14]
- 共形映射的数值近似 [15]
- 描述[16][17]
- 拐点 [18]
- Altmetric:25次引用:1更多详细信息文章 | 开放量子物理中的指数敏感性及其成本,作者:András Gilyén、Tamás Kiss 和 Igor Jex
- 布拉施克乘积 [19]
- 化圆为方[20]
- 椭圆,作者:Claude Heiland-Allen
- 作者:Paul Bourke
- 制图投影是二维中的非线性变换
- 地图投影和坐标变换
- 到球体[21]
- 曼德尔布罗特集合投影到收缩的黎曼球体上,作者:Arneauxtje
- 曼德尔布罗特象谷(短版本)蒂莫西·蔡斯
- 曼德尔布罗特芽和分支蒂莫西·蔡斯蒂莫西·蔡斯
- craftvid 制作的曼德尔布罗特集合球体缩放视频 : "这是曼德尔布罗特集合的 300 万亿倍缩放。 图像设置在球形“莫比乌斯”投影上,旨在包裹到球形表面上。 图像在球体的正面中心放大,同时在球体的背面逐渐消失。"
- 猫眼 : 反转的曼德尔布罗特集合,作者:denis archambaud
- 反转和幂曼德尔布罗特集合,作者:Jens-Peter Christensen
- Z² + Sin(Cˉᵐ+phase),作者:Jens-Peter Christensen
- snibgo 的 ImageMagick 页面:桶形和针垫形
- snibgo 的 ImageMagick 页面:3D 缩放、旋转和平移 请参阅立方体地球
共形映射
[edit | edit source]- "共形映射保持角度,并将无穷小圆映射到无穷小圆。 非共形映射将无穷小圆映射到无穷小椭圆(或更糟)。" Claude Heiland-Allen
- "复函数 在无穷远处是共形的,如果函数 在 0 处是共形的。 这等同于通常的关于共形的定义,即在大小和方向(顺时针/逆时针)方面保持角度不变,如果你将 视为在黎曼球体的“北极”处保持角度不变。"[22]
共形映射
- henry seg:python 中的球形图像编辑
- newconformist:将双曲平面共形映射到任意形状,作者:Zeno Rogue
- 应用于图片的共形映射示例
- 梅比乌斯变换
- 共形几何处理概述(2017 年),作者:Keenan Crane
- 离散共形变形:算法与实验,作者:Jian Sun、Tianqi Wu、Xianfeng Gu 和 Feng Luo
- 共形映射
- 庞加莱双曲圆盘共形映射食谱,作者:bugman123
- 用 Python 可视化共形映射,作者:MJ Gruber
- 共形动画,作者:denis archambaud
- ConformalMaps 是一个 Julia 包,用于将来自简单连通平面域到圆盘的黎曼映射进行近似。 它使用拉链算法,如 Don Marshall 和 Steffen Rohde 的论文《共形映射拉链算法的收敛性》中所述。
- sswatson:ConformalMaps
共形映射词典,作者:John H. Mathews 和 Russell W. Howell(2008 年)
制图地图投影
[edit | edit source]圆柱投影
[edit | edit source]圆柱投影(或圆柱 p.)将球体(无极点)映射到圆柱上[23][24]
茹科夫斯基变换(映射)
[edit | edit source]描述
- John D Cook[25]
复杂函数的可视化
- 可视化复杂函数的 5 种方法
- commons : Category:Complex_functions
- Rand Asswad 的复杂映射
- Paul Nylander 的庞加莱双曲圆盘共形映射配方
- david lowry-duda : phase_mag_plot/
- Christopher J. Bishop 的黎曼映射定理
- ©2015 LYM Canada 的针对反傻瓜的黎曼映射
- 映射组件到单位圆盘 (黎曼映射)
- 乘子映射 和内部射线
- 在参数平面上
- 在动力平面上
- Boettcher 映射、复势和外部射线
- 乘子映射 和内部射线
- ↑ 维基百科中的地图投影
- ↑ observable: plot-projections
- ↑ 维基百科中的横轴墨卡托投影
- ↑ : JavaScript 中的地理投影、球形形状和球面三角学
- ↑ geeksforgeeks : 2D 图形中的复合变换
- ↑ Nicolas Holzschuch 博士的 2D 变换和齐次坐标 开普敦大学
- ↑ Terr, David. "复杂平移." 来自 MathWorld--Wolfram Web 资源,由 Eric W. Weisstein 创建。
- ↑ http://ocw.mit.edu/courses/aeronautics-and-astronautics/16-07-dynamics-fall-2009/lecture-notes/MIT16_07F09_Lec03.pdf Template:Bare URL PDF
- ↑ opentextbc.ca: 地理信息本质
- ↑ wolfram : ComplexFunctionsAppliedToASquare
- ↑ scikit-image.org 文档: swirl
- ↑ Alexandre Bernardino 的对数极坐标映射
- ↑ Weisstein, Eric W. "抛物柱面坐标." 来自 MathWorld--Wolfram Web 资源
- ↑ Weisstein, Eric W. "抛物线坐标." 来自 MathWorld--Wolfram Web 资源。
- ↑ Bjørnar Steinnes Luteberget 的共形映射数值逼近
- ↑ processing : transform2d
- ↑ 看起来圆形的正方形: Saul Schleimer 和 Henry Segerman 的球面图像变换
- ↑ fractalforums inflection-mappings
- ↑ theinnerframe : playing-with-circular-images
- ↑ theinnerframe: squaring-the-circle
- ↑ fractalforums: fractal-on-sphere
- ↑ math.stackexchange 问题: conformal-mappings-of-riemann-sphere
- ↑ Paul Bourke 编写的球面投影(立体投影和圆柱投影)
- ↑ Weisstein, Eric W. "圆柱投影." 来自 MathWorld--Wolfram Web 资源。
- ↑ johndcook : joukowsky-transformation