在 PIL 中旋转一个正方形
Rotating a square in PIL
使用 PIL,我想通过指定正方形的边长和旋转角度在图像上绘制一个旋转的正方形。正方形应该是白色的,背景是灰色的。例如下图旋转了45度:
我知道如何在 PIL 中进行旋转的唯一方法是旋转整个图像。但是如果我从下图开始:
然后旋转45度,我明白了:
该方法只是引入黑色部分来填充图像的 "undefined" 区域。
如何只旋转正方形?
生成我原来的正方形(第二个图)的代码如下:
from PIL import Image
image = Image.new('L', (100, 100), 127)
pixels = image.load()
for i in range(30, image.size[0] - 30):
for j in range(30, image.size[1] - 30):
pixels[i, j] = 255
rotated_image = image.rotate(45)
rotated_image.save("rotated_image.bmp")
如果你只想画一个任意角度的纯色正方形,你可以用三角学计算旋转正方形的顶点,然后用polygon
画出来。
import math
from PIL import Image, ImageDraw
#finds the straight-line distance between two points
def distance(ax, ay, bx, by):
return math.sqrt((by - ay)**2 + (bx - ax)**2)
#rotates point `A` about point `B` by `angle` radians clockwise.
def rotated_about(ax, ay, bx, by, angle):
radius = distance(ax,ay,bx,by)
angle += math.atan2(ay-by, ax-bx)
return (
round(bx + radius * math.cos(angle)),
round(by + radius * math.sin(angle))
)
image = Image.new('L', (100, 100), 127)
draw = ImageDraw.Draw(image)
square_center = (50,50)
square_length = 40
square_vertices = (
(square_center[0] + square_length / 2, square_center[1] + square_length / 2),
(square_center[0] + square_length / 2, square_center[1] - square_length / 2),
(square_center[0] - square_length / 2, square_center[1] - square_length / 2),
(square_center[0] - square_length / 2, square_center[1] + square_length / 2)
)
square_vertices = [rotated_about(x,y, square_center[0], square_center[1], math.radians(45)) for x,y in square_vertices]
draw.polygon(square_vertices, fill=255)
image.save("output.png")
结果:
让我们概括为一个矩形:
- 长度 l 在 x 和宽度 w 在 y.
- 使用 "rotation matrix".
旋转代码:
import math
def makeRectangle(l, w, theta, offset=(0,0)):
c, s = math.cos(theta), math.sin(theta)
rectCoords = [(l/2.0, w/2.0), (l/2.0, -w/2.0), (-l/2.0, -w/2.0), (-l/2.0, w/2.0)]
return [(c*x-s*y+offset[0], s*x+c*y+offset[1]) for (x,y) in rectCoords]
绘图代码:
from PIL import Image
from PIL import ImageDraw
import math
L=512; W=512
image = Image.new("1", (L, W))
draw = ImageDraw.Draw(image)
vertices = makeRectangle(100, 200, 45*math.pi/180, offset=(L/2, W/2))
draw.polygon(vertices, fill=1)
image.save("test.png")
使用 PIL,我想通过指定正方形的边长和旋转角度在图像上绘制一个旋转的正方形。正方形应该是白色的,背景是灰色的。例如下图旋转了45度:
我知道如何在 PIL 中进行旋转的唯一方法是旋转整个图像。但是如果我从下图开始:
然后旋转45度,我明白了:
该方法只是引入黑色部分来填充图像的 "undefined" 区域。
如何只旋转正方形?
生成我原来的正方形(第二个图)的代码如下:
from PIL import Image
image = Image.new('L', (100, 100), 127)
pixels = image.load()
for i in range(30, image.size[0] - 30):
for j in range(30, image.size[1] - 30):
pixels[i, j] = 255
rotated_image = image.rotate(45)
rotated_image.save("rotated_image.bmp")
如果你只想画一个任意角度的纯色正方形,你可以用三角学计算旋转正方形的顶点,然后用polygon
画出来。
import math
from PIL import Image, ImageDraw
#finds the straight-line distance between two points
def distance(ax, ay, bx, by):
return math.sqrt((by - ay)**2 + (bx - ax)**2)
#rotates point `A` about point `B` by `angle` radians clockwise.
def rotated_about(ax, ay, bx, by, angle):
radius = distance(ax,ay,bx,by)
angle += math.atan2(ay-by, ax-bx)
return (
round(bx + radius * math.cos(angle)),
round(by + radius * math.sin(angle))
)
image = Image.new('L', (100, 100), 127)
draw = ImageDraw.Draw(image)
square_center = (50,50)
square_length = 40
square_vertices = (
(square_center[0] + square_length / 2, square_center[1] + square_length / 2),
(square_center[0] + square_length / 2, square_center[1] - square_length / 2),
(square_center[0] - square_length / 2, square_center[1] - square_length / 2),
(square_center[0] - square_length / 2, square_center[1] + square_length / 2)
)
square_vertices = [rotated_about(x,y, square_center[0], square_center[1], math.radians(45)) for x,y in square_vertices]
draw.polygon(square_vertices, fill=255)
image.save("output.png")
结果:
让我们概括为一个矩形:
- 长度 l 在 x 和宽度 w 在 y.
- 使用 "rotation matrix".
旋转代码:
import math
def makeRectangle(l, w, theta, offset=(0,0)):
c, s = math.cos(theta), math.sin(theta)
rectCoords = [(l/2.0, w/2.0), (l/2.0, -w/2.0), (-l/2.0, -w/2.0), (-l/2.0, w/2.0)]
return [(c*x-s*y+offset[0], s*x+c*y+offset[1]) for (x,y) in rectCoords]
绘图代码:
from PIL import Image
from PIL import ImageDraw
import math
L=512; W=512
image = Image.new("1", (L, W))
draw = ImageDraw.Draw(image)
vertices = makeRectangle(100, 200, 45*math.pi/180, offset=(L/2, W/2))
draw.polygon(vertices, fill=1)
image.save("test.png")