Mandelbrot集渲染程序输出呈反转四分块问题求助
修复Mandelbrot集渲染的四分块翻转问题
问题根源分析
你的代码存在三个核心问题导致图像呈现四分块且方向错误:
- 像素坐标映射错误:直接将数学坐标
x、i作为图像像素坐标传入putpixel,但图像像素坐标范围是(0,0)到(999,499),而你使用的x(默认-550到450)、i(默认-250到250)包含负数,PIL会将负数坐标循环到图像另一侧,造成四分块错位。 - 坐标系方向不匹配:PIL图像的y轴向下递增,而数学坐标系的y轴向上递增,直接使用会导致图像上下翻转。
- 逃逸判断逻辑不严谨:通过字符串判断
zofn是否为nan的方式不可靠,Mandelbrot集的标准逃逸条件是当|z| > 2时,点会趋向无穷,属于逃逸点。
修复后的代码
from PIL import Image from PIL import ImageShow from PIL import ImageColor as ImageColour colours = ["navy","darkblue","blue","cornflowerblue","lightsteelblue","lightskyblue","turquoise","palegreen","lawngreen","greenyellow","yellowgreen","goldenrod","gold","yellow","darkorange","orange","brown","maroon","red","deeppink","darkmagenta","magenta","mediumorchid","darkviolet","slateblue"] def testpoint(c, max_iter): z = 0.0 count = 0 while abs(z) <= 2 and count < max_iter: z = z * z + c count += 1 # 达到最大迭代次数未逃逸则属于Mandelbrot集 return count if abs(z) > 2 else -1 def mainprogram(): # 处理输入默认值:用户直接回车时取默认值 zoom_input = input("Set Zoom Level. (Default: 10) ") zoom = int(zoom_input or 10) * 10 centre_x_input = input("Input centre x value. (Default: -50) ") centre_x = int(centre_x_input or -50) centre_y_input = input("Input centre y value. (Default: 0) ") centre_y = int(centre_y_input or 0) img_width = 1000 img_height = 500 max_iter = 5 * zoom for img_y in range(img_height): # 翻转y轴并映射到数学坐标系 math_y = (centre_y + 250 - img_y) / zoom for img_x in range(img_width): # 映射x坐标到数学坐标系 math_x = (centre_x - 500 + img_x) / zoom c = complex(math_x, math_y) value = testpoint(c, max_iter) colour = (0, 0, 0) if value == -1 else ImageColour.getrgb(colours[value % len(colours)]) result.putpixel((img_x, img_y), colour) print(f"line {img_y + 1} done") ImageShow.show(result) # 注释下方代码可避免无限递归请求输入 # mainprogram() # 初始化图像画布 result = Image.new("RGB", (1000, 500), "Black") mainprogram()
关键修复点说明
- 坐标映射修正:
- 图像x坐标
img_x从0到999,映射为数学x坐标:(centre_x - 500 + img_x) / zoom,确保对应设定的中心左右500单位范围。 - 图像y坐标
img_y从0到499,先翻转得到250 - img_y,再叠加中心y偏移后缩放:(centre_y + 250 - img_y) / zoom,解决上下翻转问题。
- 图像x坐标
- 逃逸判断优化:用
abs(z) <= 2替代字符串判断,逻辑准确且效率更高。 - 输入默认值修复:原代码中
input(...) or 10的写法存在逻辑漏洞,改为先接收输入再处理默认值。 - 避免无限递归:原代码末尾递归调用自身会导致程序无限循环请求输入,建议注释该调用。
内容的提问来源于stack exchange,提问作者Jessica
相关产品推荐
相关产品推荐

