1.图像旋转
image1=image1.rotate(angle)
或
np.rot90()
2.坐标旋转
一、首先来说一下关于像素旋转一定角度后的对应位置:
(1)旋转中心为左上角原点:
旋转有一个绕什么转的问题。我们先来看最简单的,绕第一个像素转,则旋转的情况会像这样:
令旋转前有
旋转a角度后有
以矩阵形式表示为
(2)旋转中心为图像中心:
当图片较大时,计算会很慢。主要是判断和计算太多了这里只讨论图像处理,程序的优化暂时放一边运行结果如下:
我们能看到,旋转后的图像有很多“蜂窝煤”。主要是点转换后要取整。导致原图中有些点映射到同一个点,而生成的图中有些点在原图中没有点映射到它。所以出现了很多“蜂窝煤”。果然理论还只是理论啊 下面我们来看看更通常一点的做法:以图像的中心为圆心进行旋转。这里涉及到一个坐标系的转换问题。看下图:
在矩阵中我们的坐标系通常是AB和AC方向的,而传统的笛卡尔直角坐标系是DE和DF方向的。令图像表示为M×N的矩阵,对于点A而言,两坐标系中的坐标分别是(0,0)和(-N/2,M/2)矩阵中点(x',y')转换为笛卡尔坐标系(x,y)的转换关系为:
逆变换为
于是我们得到图像以中心旋转的思路
于是得到最后结果
python中numpy有矩阵运算能力,但这里我们直接进行数值计算就可以了。用方程表示如下:
关键代码如下:
def rotatecordiate(angle,rect):
angle=angle*math.pi/180
n=1600
m=1200
def onepoint(x,y):
# X = x*math.cos(angle) - y*math.sin(angle)-0.5*n*math.cos(angle)+0.5*m*math.sin(angle)+0.5*n
# Y = y*math.cos(angle) + x*math.sin(angle)-0.5*n*math.sin(angle)-0.5*m*math.cos(angle)+0.5*m
X = x * math.cos(angle) - y * math.sin(angle) - 0.5 * n * math.cos(angle) + 0.5 * m * math.sin(angle) + 0.5 * n
Y = y * math.cos(angle) + x * math.sin(angle) - 0.5 * n * math.sin(angle) - 0.5 * m * math.cos(angle) + 0.5 * m
return [int(X),int(Y)]
newrect=[]
for i in range(4):
point=onepoint(rect[i*2],rect[i*2+1])
newrect.extend(point)
newrect.extend([1])
print(newrect)
return newrect
参考:https://www.cnblogs.com/zf-blog/p/8947800.html
(3)旋转中心为矩形框中心:
def rotatecordiate(angle,rect):
anglePi = -angle * math.pi / 180.0
cosA = math.cos(anglePi)
sinA = math.sin(anglePi)
x=rect[0]
y=rect[1]
width=rect[2]
height=rect[3]
x1 = x - 0.5 * width
y1 = y - 0.5 * height
x0 = x + 0.5 * width
y0 = y1
x2 = x1
y2 = y + 0.5 * height
x3 = x0
y3 = y2
x0n = (x0 - x) * cosA - (y0 - y) * sinA + x
y0n = (x0 - x) * sinA + (y0 - y) * cosA + y
x1n = (x1 - x) * cosA - (y1 - y) * sinA + x
y1n = (x1 - x) * sinA + (y1 - y) * cosA + y
x2n = (x2 - x) * cosA - (y2 - y) * sinA + x
y2n = (x2 - x) * sinA + (y2 - y) * cosA + y
x3n = (x3 - x) * cosA - (y3 - y) * sinA + x
y3n = (x3 - x) * sinA + (y3 - y) * cosA + y
return [(x0n,y0n),(x1n,y1n),(x2n,y2n),(x3n,y3n)]
绘制多边形:
plt.Polygon(rotatecordiate(angle,rect),color=color, fill=False, linewidth=2)