图像几何变换之图像旋转
原理
旋转变化——极坐标表示
设点P0(x0,y0)旋转θ角后对应点为P(x,y)。
对于两点坐标可以这样表示:
x0=R*cosα
y0=R*sinα
x=R*cos(α-θ)= x0 *cosθ + y0 *sinθ
y=R*sin(α-θ)= -x0 *sinθ+ y0 *cosθ
1.png
以矩阵形式表示为:
下面我们来看看更通常一点的做法:以图像的中心为圆心进行旋转。
这里涉及到一个坐标系的转换问题。如图:
2.png
在矩阵中我们的坐标系通常是AD和AB方向的,而传统的笛卡尔直角坐标系是以矩阵中心建立坐标系的。
令图像表示为M×N的矩阵,对于点A而言,两坐标系中的坐标分别是(0,0)和(-N/2,M/2)
矩阵中点(x',y')转换为笛卡尔坐标系(x,y)的转换关系为: 3.png逆变换:
4.png于是得到图像中心旋转的步骤:
5.png
- 转换为笛卡尔坐标系
- 将图像上的点旋转α°
- 将旋转后的点再转换为矩阵坐标
6.png
代码
#encoding:UTF-8
from PIL import Image
import math
import matplotlib.pyplot as plt
def rotate(image,degree,crop=False):
im = Image.open(image)
radius = math.pi * degree / 180
width, height = im.size
if not crop:
X1 = math.ceil(abs(0.5 * height * math.cos(radius) + 0.5 * width * math.sin(radius)))
X2 = math.ceil(abs(0.5 * height * math.cos(radius) - 0.5 * width * math.sin(radius)))
Y1 = math.ceil(abs(-0.5 * height * math.sin(radius) + 0.5 * width * math.cos(radius)))
Y2 = math.ceil(abs(-0.5 * height * math.sin(radius) - 0.5 * width * math.cos(radius)))
H = int(2 * max(Y1, Y2))
W = int(2 * max(X1, X2))
dstwidth = W + 1
dstheight = H + 1
if crop:
dstheight = height
dstwidth = width
im_new = Image.new('RGB', (dstwidth, dstheight), (255, 255, 255))
for i in range(dstwidth):
for j in range(dstheight):
new_i = int(
(i - 0.5 * dstwidth) * math.cos(radius) - (j - 0.5 * dstheight) * math.sin(radius) + 0.5 * width)
new_j = int(
(i - 0.5 * dstwidth) * math.sin(radius) + (j - 0.5 * dstheight) * math.cos(radius) + 0.5 * height)
if new_i >= 0 and new_i < width and new_j >= 0 and new_j < height:
im_new.putpixel((i, j), im.getpixel((new_i, new_j)))
# im_new.show()
sub = plt.subplot(1, 2, 1)
sub.set_title("Src Img")
plt.imshow(im)
sub = plt.subplot(1, 2, 2)
sub.set_title("Dst->Src & Nearest")
plt.imshow(im_new)
plt.show()
结果图像
Figure_1.pngFigure_2.png
网友评论