Python 绘制和着色圆形截面
所以,我必须做一些图形/可视化工作,这是一场噩梦,因为我在这方面没有经验 简言之,我有一系列的同心圆(b,c,d),半径为1,2,3,以及穿过原点(-x-y=0和-x+y=0)的垂直线(e,f)。下面是GeoGebra可视化: 我还有一个12个灰度像素值的数组。该数组中的每个值对应于图像部分要着色的颜色(3个圆圈,每个圆圈有4个部分)。下面是一个示例图像,为了清晰起见,我在其中用粉色着色了一个区域 我已经能够创建可以着色的饼图切片,它适用于圆b中的部分,但不适用于其他两个部分Python 绘制和着色圆形截面,python,Python,所以,我必须做一些图形/可视化工作,这是一场噩梦,因为我在这方面没有经验 简言之,我有一系列的同心圆(b,c,d),半径为1,2,3,以及穿过原点(-x-y=0和-x+y=0)的垂直线(e,f)。下面是GeoGebra可视化: 我还有一个12个灰度像素值的数组。该数组中的每个值对应于图像部分要着色的颜色(3个圆圈,每个圆圈有4个部分)。下面是一个示例图像,为了清晰起见,我在其中用粉色着色了一个区域 我已经能够创建可以着色的饼图切片,它适用于圆b中的部分,但不适用于其他两个部分 from PI
from PIL import Image, ImageDraw
x_center = 400 // 2
y_center = 400 //2
img = Image.new('RGBA', (400, 400), 'white')
idraw = ImageDraw.Draw(img)
idraw.pieslice([x_center-100, x_center-100,
y_center + 106, y_center + 106], 225, 315, fill='blue')
和和弦很接近,但我需要一个弧形的底部,而不是一条直线
from PIL import Image, ImageDraw
x_center = 400 // 2
y_center = 400 //2
im = Image.new('RGBA', (400, 400), 'white')
draw = ImageDraw.Draw(im)
draw.chord([x_center-100, x_center-100,
y_center + 106, y_center + 106], 225, 315, fill='blue')
现在,最终目标是获取最终产品并将其保存为png或jpeg格式。这是因为每幅图像都反映了一个时间片,我想将它们全部涂抹到一个视频中。然而,我100%愿意使用任何最有效的工具,无论是PIL、matplotlib等(我对这类东西没有经验,所以我决定使用PIL/Pizz可能不是最明智的)
对这件事的任何见解都将不胜感激。好吧,在几乎两天没有睡觉之后,我为现在或将来碰巧也有这个问题的人找到了解决办法 简而言之,我找到了每个部分中的所有坐标,然后构建了一个位图图像。它不是特别快,但它可以工作
import numpy as np
from matplotlib import pyplot as plt
def inside_circle(radius, x_center, y_center):
"""
Determines all points that fall within a circle
Returns a set of tuples with each tuple being an x-y coordinate
inside the circle
"""
valid = set()
for x in xrange(0, 601):
for y in xrange(0, 601):
if ((x - x_center)*(x- x_center)) + \
((y - y_center)*(y - y_center)) <= radius*radius:
valid.add((x, y))
return valid
def above_line(all_points, p1, p2):
"""
Determines if each point is above the line defined by p1 and p2
Returns a set of tuples with each tuple being an x-y coordinate
above line
"""
valid = set()
for point in all_points:
p = np.array([point])
is_above = np.cross(p-p1, p2-p1) < 0
if is_above:
valid.add(tuple(point))
return valid
# Find all points in each circle
circle_1 = inside_circle(radius=100, x_center=300, y_center=300)
circle_2 = inside_circle(radius=200, x_center=300, y_center=300)
circle_3 = inside_circle(radius=300, x_center=300, y_center=300)
# Find all points above each line
above_positive = above_line(all_points=circle_3,
p1=np.array([100, 100]),
p2=np.array([300, 300])) # pos sloped line
above_negative = above_line(all_points=circle_3,
p1=np.array([100, 500]),
p2=np.array([300, 300])) # neg sloped line
# Find all points in each ring
ring_1 = circle_1
ring_2 = {i for i in circle_2 if i not in circle_1}
ring_3 = {i for i in circle_3 if i not in circle_2}
# Find all points in each wedge
wedge_0 = {i for i in circle_3 if (i in above_negative) and
(i in above_positive)}
wedge_1 = {i for i in circle_3 if (i in above_negative) and
(i not in above_positive)}
wedge_2 = {i for i in circle_3 if (i not in above_negative) and
(i not in above_positive)}
wedge_3 = {i for i in circle_3 if (i not in above_negative) and
(i in above_positive)}
# Take colours and convert each value to int (my data is floats, but
# I have used ints for this example)
image = [255, 255, 255, 255, 0, 255, 255, 255, 255, 255, 255, 255]
for index, value in enumerate(image):
image[index] = np.int64(round(abs(value)))
# Build a list where each index holds the coordinates for a particular
# section [{section 0 cords} ... {section 11 cords}]
wedges = [wedge_0, wedge_1, wedge_2, wedge_3]
rings = [ring_1, ring_2, ring_3]
cords_in_sections = []
section_number = 0
for ring in rings:
current_index = 0
while current_index < len(wedges):
points = {i for i in ring if i in wedges[current_index]}
cords_in_sections.append(points)
section_number += 1
current_index += 1
# Create an 600x600 matrix of white pixels, then change pixel values in
# each section
pixel_matrix = np.full((600, 600), 255)
# This is ugly, but seem to work better than a {cord: colour} dict
for row, y in enumerate(pixel_matrix):
for column, x in enumerate(y):
if (column, row) in cords_in_sections[0]:
pixel_matrix[row, column] = image[0]
elif (column, row) in cords_in_sections[1]:
pixel_matrix[row, column] = image[1]
elif (column, row) in cords_in_sections[2]:
pixel_matrix[row, column] = image[2]
elif (column, row) in cords_in_sections[3]:
pixel_matrix[row, column] = image[3]
elif (column, row) in cords_in_sections[4]:
pixel_matrix[row, column] = image[4]
elif (column, row) in cords_in_sections[5]:
pixel_matrix[row, column] = image[5]
elif (column, row) in cords_in_sections[6]:
pixel_matrix[row, column] = image[6]
elif (column, row) in cords_in_sections[7]:
pixel_matrix[row, column] = image[7]
elif (column, row) in cords_in_sections[8]:
pixel_matrix[row, column] = image[8]
elif (column, row) in cords_in_sections[9]:
pixel_matrix[row, column] = image[9]
elif (column, row) in cords_in_sections[10]:
pixel_matrix[row, column] = image[10]
elif (column, row) in cords_in_sections[11]:
pixel_matrix[row, column] = image[11]
plt.imshow(pixel_matrix, cmap='gray')
plt.axis('off')
plt.show()
将numpy导入为np
从matplotlib导入pyplot作为plt
def内圆(半径、x_中心、y_中心):
"""
确定落在圆内的所有点
返回一组元组,每个元组都是x-y坐标
圈内
"""
valid=set()
对于x范围内的x(0601):
对于X范围内的y(0601):
如果((x-x_中心)*(x-x_中心))+\
((y-y_中心)*(y-y_中心))从最大的第一个扇区到最小的扇区序列。连续较小的圆形扇区将绘制在前面的扇区之上,给出您要查找的区域形状。例如,使用您的代码调用idraw.pieslice
idraw.pieslice([x_center-100, x_center-100,
y_center+100, y_center+100], 225, 315, fill='blue')
idraw.pieslice([x_center-80, x_center-80,
y_center+80, y_center+80], 225, 315, fill='red')
假设您希望圆以您命名为x\u center
和y\u center
的坐标为中心,则需要为边界框添加和减去相同的值,而不是使用[x\u center-100,x\u center-100,y\u center+106,y\u center+106]
我刚刚开始写同样的东西。只要这些区域是不透明的,这就应该像一种魅力。干杯当然你可以画一些东西。。。这是一个比我想出的更好的解决办法。我必须画5000个这样的东西,所以这个解决方案将节省我很多时间。谢谢如果重复绘制相同的图案,则只生成一次图案并重复粘贴会更有意义。生成具有透明度的图案(RGBA)。在RGBA矩形中粘贴要比绘制两个圆楔快。