齐次坐标与仿射变换

http://www.cnblogs.com/csyisong/archive/2008/12/09/1351372.html 写的十分好


对于一个向量v以及基oabc可以找到一组坐标(v1,v2,v3),使得v = v1 a + v2 b + v3 c          1

 而对于一个p,则可以找到一组坐标(p1,p2,p3),使得 po = p1 a + p2 b + p3 c            2),

 

从上面对向量的表达,我们可以看出为了在坐标系中表示一个(如p),我们把点的位置看作是对这个基的原点o所进行的一个位移,即一个向量——p – o(有的书中把这样的向量叫做位置向量——起始于坐标原点的特殊向量),我们在表达这个向量的同时用等价的方式表达出了点p:p = o + p1 a + p2 b + p3 c (3)

 

(1)(3)是坐标系下表达一个向量的不同表达方式。这里可以看出,虽然都是用代数分量的形式表达向量和点,但表达一个点比一个向量需要额外的信息。如果我写出一个代数分量表达(1, 4, 7),谁知道它是个向量还是个点!

    我们现在把(1)(3)写成矩阵的形式:v = (v1 v2 v3 0) X (a b c o)

p = (p1 p2 p3 1) X (a b c o),这里(a,b,c,o)是坐标基矩阵,右边的列向量分别是向量v和点p在基下的坐标。这样,向量和点在同一个基下就有了不同的表达:3D向量的第4个代数分量是0,而3D的第4个代数分量是1。像这种这种用4个代数分量表示3D几何概念的方式是一种齐次坐标表示。

 

这样,上面的(1, 4, 7)如果写成(1,4,7,0),它就是个向量;如果是(1,4,7,1),它就是个点。下面是如何在普通坐标(Ordinary Coordinate)和齐次坐标(Homogeneous Coordinate)之间进行转换:

(1)从普通坐标转换成齐次坐标时

   如果(x,y,z)是个点,则变为(x,y,z,1);

   如果(x,y,z)是个向量,则变为(x,y,z,0)

(2)从齐次坐标转换成普通坐标时   

   如果是(x,y,z,1),则知道它是个点,变成(x,y,z);

   如果是(x,y,z,0),则知道它是个向量,仍然变成(x,y,z)

 

以上是通过齐次坐标来区分向量和点的方式。从中可以思考得知,对于平移T、旋转R、缩放S3个最常见的仿射变换,平移变换只对于点才有意义,因为普通向量没有位置概念,只有大小和方向.

 

而旋转和缩放对于向量和点都有意义,你可以用类似上面齐次表示来检测。从中可以看出,齐次坐标用于仿射变换非常方便。

 

此外,对于一个普通坐标的P=(Px, Py, Pz),有对应的一族齐次坐标(wPx, wPy, wPz, w),其中w不等于零。比如,P(1, 4, 7)的齐次坐标有(1, 4, 7, 1)、(2, 8, 14, 2)、(-0.1, -0.4, -0.7, -0.1)等等。因此,如果把一个点从普通坐标变成齐次坐标,给x,y,z乘上同一个非零数w,然后增加第4个分量w;如果把一个齐次坐标转换成普通坐标,把前三个坐标同时除以第4个坐标,然后去掉第4个分量。

 

由于齐次坐标使用了4个分量来表达3D概念,使得平移变换可以使用矩阵进行,从而如F.S. Hill, JR所说,仿射(线性)变换的进行更加方便。由于图形硬件已经普遍地支持齐次坐标与矩阵乘法,因此更加促进了齐次坐标使用,使得它似乎成为图形学中的一个标准。

 

   以上很好的阐释了齐次坐标的作用及运用齐次坐标的好处。其实在图形学的理论中,很多已经被封装的好的API也是很有研究的,要想成为一名专业的计算机图形学的学习者,除了知其然必须还得知其所以然。这样在遇到问题的时候才能迅速定位问题的根源,从而解决问题。



### Python 实现齐次坐标图像的仿射变换 齐次坐标是一种用于表示几何图形的方法,在计算机视觉和图像处理领域广泛应用。通过齐次坐标可以方便地描述平移、旋转、缩放等操作,并将其统一到矩阵形式下完成计算[^1]。 #### 齐次坐标的定义 齐次坐标通常用来扩展二维空间中的点 (x, y),使其变为三维向量 [x, y, 1]^T。这种扩展允许我们将各种线性变换(如平移、旋转、缩放)组合成单一的矩阵运算[^2]。 #### 使用 OpenCV 进行仿射变换 OpenCV 是一个强大的库,支持多种图像处理功能,其中包括基于齐次坐标仿射变换。以下是具体实现方法: ```python import cv2 import numpy as np # 原始图像加载 image = cv2.imread('example.jpg') # 定义三个对应点对来构建仿射变换矩阵 pts_src = np.float32([[50, 50], [200, 50], [50, 200]]) pts_dst = np.float32([[10, 100], [200, 50], [100, 250]]) # 计算仿射变换矩阵 M = cv2.getAffineTransform(pts_src, pts_dst) # 应用仿射变换 result = cv2.warpAffine(image, M, (image.shape[1], image.shape[0])) # 显示结果 cv2.imshow("Original", image) cv2.imshow("Transformed", result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 此代码片段展示了如何利用 `cv2.getAffineTransform` 函数创建仿射变换矩阵并应用它于输入图像上[^3]。 #### 自定义仿射变换矩阵 如果需要手动指定变换参数,则可以通过 NumPy 构建自定义矩阵来进行更灵活的操作: ```python import numpy as np import matplotlib.pyplot as plt def affine_transform(image, matrix): h, w = image.shape[:2] transformed_image = cv2.warpAffine(image, matrix, (w, h)) return transformed_image # 创建示例图像 img = np.zeros((200, 200), dtype=np.uint8) cv2.rectangle(img, (50, 50), (150, 150), 255, -1) # 手动设置仿射变换矩阵 A = np.array([ [1, 0.5, 30], [0, 1, 50]], dtype=np.float32) transformed_img = affine_transform(img, A) plt.figure(figsize=(10, 5)) plt.subplot(1, 2, 1) plt.title("Original Image") plt.imshow(img, cmap='gray') plt.subplot(1, 2, 2) plt.title("Transformed Image") plt.imshow(transformed_img, cmap='gray') plt.show() ``` 在此例子中,我们不仅实现了基本的矩形绘制还进行了斜切和平移效果展示[^4]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值