使用静态点的贝塞尔曲线

3

我在网上找到了这段代码,它可以生成随机的Bezier曲线并使用随机点。我想把它变成非随机的,让它使用静态点。我成功地让它只使用了4个点,这很容易。我以前从未在Python中使用过PIL,事实上我正在慢慢学习Python。而且我只做过前端工作(HTML、JavaScript、CSS等),我想知道是否有人能帮助我。以下是我在网上找到的代码:

# Random Bezier Curve using De Casteljau's algorithm
# http://en.wikipedia.org/wiki/Bezier_curve
# http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm
# FB - 201111244
import random
from PIL import Image, ImageDraw
imgx = 500
imgy = 500
image = Image.new("RGB", (imgx, imgy))
draw = ImageDraw.Draw(image)

def B(coorArr, i, j, t):
    if j == 0:
        return coorArr[i]
    return B(coorArr, i, j - 1, t) * (1 - t) + B(coorArr, i + 1, j - 1, t) * t

n = 4 # number of control points
coorArrX = []
coorArrY = []
for k in range(n):
    x = (0, imgx - 1)
    y = (0, imgy - 1)
    coorArrX.append(x)
    coorArrY.append(y)

# plot the curve
numSteps = 10000    
for k in range(numSteps):
    t = float(k) / (numSteps - 1)
    x = int(B(coorArrX, 0, n - 1, t))
    y = int(B(coorArrY, 0, n - 1, t))
    try:
        image.putpixel((x, y), (0, 255, 0))
    except:
        pass

# plot the control points
cr = 3 # circle radius
for k in range(n):
    x = coorArrX[k]
    y = coorArrY[k]
    try:
        draw.ellipse((x - cr, y - cr, x + cr, y + cr), (255, 0, 0))
    except:
        pass

# image.save("BezierCurve.png", "PNG")
image.show() I add this so I can see it right away

任何形式的帮助都是非常好的。

代码对我不起作用,无法使用任何地方都用到的“random”... - heltonbiker
我不确定你的疑问是什么,而且在你修改代码之前我已经看过原始代码了。所以,你定义了 n = 4。现在你想要手动指定4个点,而不是使用 random 函数来获取它们?你只需要为 coorArrX 给出四个 x 坐标,为 coorArrY 给出四个 y 坐标,并删除当前代码中填充这些列表的虚假循环。例如,定义 coorArrX = [25, 220, 430, 430]coorArrY = [250, 10, 450, 40],并删除 for k in range(n): ... 循环。这解决了你的问题吗? - mmgp
2个回答

1

好的,下面是开始这一切的冗长详细内容。结果答案在这里。

您的静态点是x、y坐标,x值和y值分别放置在不同的数组中(coorArrx和coorArrY)。请确保永远不要使用值=imgx或imy。

# Random Bezier Curve using De Casteljau's algorithm
# http://en.wikipedia.org/wiki/Bezier_curve
# http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm
# FB - 201111244
import random
from PIL import Image, ImageDraw
imgx = 500
imgy = 500
image = Image.new("RGB", (imgx, imgy))
draw = ImageDraw.Draw(image)

def B(coorArr, i, j, t):
    if j == 0:
        return coorArr[i]
    return B(coorArr, i, j - 1, t) * (1 - t) + B(coorArr, i + 1, j - 1, t) * t

# n = random.randint(3, 6) # number of control points
n=4
#coorArrX = []
#coorArrY = []
#for k in range(n):
#    x = random.randint(0, imgx - 1)
#    y = random.randint(0, imgy - 1)
#    coorArrX.append(x)
#    coorArrY.append(y)
coorArrX=[3,129,12,77]
coorArrY=[128,52,12,491]

# plot the curve
numSteps = 10000
for k in range(numSteps):
    t = float(k) / (numSteps - 1)
    x = int(B(coorArrX, 0, n - 1, t))
    y = int(B(coorArrY, 0, n - 1, t))
    try:
        image.putpixel((x, y), (0, 255, 0))
    except:
        pass

# plot the control points
cr = 3 # circle radius
for k in range(n):
    x = coorArrX[k]
    y = coorArrY[k]
    try:
        draw.ellipse((x - cr, y - cr, x + cr, y + cr), (255, 0, 0))
    except:
        pass
image.show()

=.........................................................................................= 我也是一个对这一切比较新的人,而且我拒绝像你一样去查找资料...因为我认为这是一个学习的过程。

但是当我看着这段代码时,我发现了一些奇怪的东西。

for k in range(n):
    x = (0, imgx - 1)
    y = (0, imgy - 1)
    coorArrX.append(x)
    coorArrY.append(y)

你确定这部分是正确的吗?在其他地方,imgx被定义为500,而n是4。因此,这可能会被解读为


for k in range(4):
    x = (0, 500 - 1)
    y = (0, 500 - 1)

这意味着(由于这些值在此代码中从不改变),:

x = (0, 499)
y = (0, 499)

在每次通过时。 因此,每次他们到达:

coorArrX.append(x)
coorArrY.append(y)

他们只是不断地向数组添加相同数据的新副本,因此当完成时,数组看起来像这样(内部)

[(0, 499), (0, 499), (0, 499), (0,499)]

更加令人困惑的是,coorArrX和coorArrY A)相同,B)在它们的基本部分(即每个元素都相同)也相同。因此,当您到达代码的这一部分时:
# plot the control points
cr = 3 # circle radius
for k in range(n):
    x = coorArrX[k]
    y = coorArrY[k]
    try:
        draw.ellipse((x - cr, y - cr, x + cr, y + cr), (255, 0, 0))
    except:
        pass

当您在数组中替换值时,您会得到:

# plot the control points
cr = 3 # circle radius
for k in range(n):
    x = coorArrX[k]
    y = coorArrY[k]
    try:
        draw.ellipse(((0, 499) - 3, (0, 499) - 3, (0, 499) + 3, (0, 499) + 3), (255, 0, 0))
    except:
        pass

现在这部分控制绘制曲线段的情节,但我不明白如何在那些不可能的坐标集上居中一个椭圆可以画出任何东西?!

我崩溃了并进行了复制粘贴测试运行。这段代码纯属虚假,要么是为了欺骗人们浪费时间而放置的,要么是为了同样的原因而放置在OP找到它的地方。

但尝试还是很有趣的!!


这是之前的代码: x = random.randint(0, 499) y = random.randint(0, 499) 它会生成一个介于0到499之间的随机数。 - Jamal Martin
哦,这些代码行在哪里呢?能提供原始页面链接吗? - Jase
这是链接:http://code.activestate.com/recipes/577961-bezier-curve-using-de-casteljau-algorithm/?c=14802 - Jamal Martin
好的,现在我全都懂了,但我不理解维基百科上原始的公式,所以尽管我理解了这里使用的代码,但我不确定你请求中“静态”点部分的含义。我认为它们的x和y值只需要写入coorArrx和coorArrY(比如说你的点是3,2,将3附加到x数组,2附加到y数组),让我进行一些实验,然后再回复你。 - Jase
所以這就是我做的,只是為了測試一些點。n = 4 #控制點數量coorArrX = []coorArrY = []for k in range(n):x = 100 y = 100 coorArrX.append(x) coorArrY.append(y) if (x!= 0)並且(y!= 0): x = 150 y = 50 coorArrX.append(x) coorArrY.append(y) if (x!= 0)並且(y!= 0): x = 200 y = 50 coorArrX.append(x) coorArrY.append(y) if (x != 10)並且(y != 10): x = 280 y = 100 coorArrX.append(x) coorArrY.append(y) - Jamal Martin
谢谢,这比我的解决方案好多了,现在我只需要考虑如何输入。 - Jamal Martin

0
根据您的描述,唯一的问题似乎只涉及Python基础知识。我已重新排列代码如下,现在只需要触及底部的事情即可。现在,如果您希望手动指定4个控制点,请继续(在以下代码中,我已经指定了其中4个作为示例)。您需要明白,在原始代码中,coorArrXcoorArrY仅是列表,每个列表将包含4个点(分别是x和y坐标)。如果您正在手动指定它们,则没有必要使用循环来编写它们。我希望这段代码足够清晰:

# Random Bezier Curve using De Casteljau's algorithm
# http://en.wikipedia.org/wiki/Bezier_curve
# http://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm
# FB - 201111244
from PIL import Image, ImageDraw

def plot_curve(image, px, py, steps=1000, color=(0, 255, 0)):
    def B(coord, i, j, t):
        if j == 0:
            return coord[i]
        return (B(coord, i, j - 1, t) * (1 - t) +
                B(coord, i + 1, j - 1, t) * t)

    img = image.load()
    for k in range(steps):
        t = float(k) / (steps - 1)
        x = int(B(px, 0, n - 1, t))
        y = int(B(py, 0, n - 1, t))
        try:
            img[x, y] = color
        except IndexError:
            pass

def plot_control_points(image, px, py, radi=3, color=(255, 0, 0)):
    draw = ImageDraw.Draw(image)
    for x, y in zip(px, py):
        draw.ellipse((x - radi, y - radi, x + radi, y + radi), color)


# Your fixed, manually specified, points.
n = 4
coord_x = [25, 220, 430, 410]
coord_y = [250, 10, 450, 40]

image = Image.new("RGB", (500, 500))

plot_curve(image, coord_x, coord_y)
plot_control_points(image, coord_x, coord_y)

image.save("BezierCurve.png")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接