You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成网格渐变?求多色二维颜色插值的伪代码/Python实现

多色二维网格渐变实现方案

要实现类似的随机点多色网格渐变,常用两种主流方法:逆距离加权(IDW)插值和Delaunay三角剖分+重心插值,以下是具体实现:


方法一:逆距离加权(IDW)插值

该方法通过目标点与所有控制点的距离反比权重,加权求和得到目标颜色,距离越近的控制点对颜色影响越大。

伪代码

// 定义控制点集合,每个元素包含坐标与RGB颜色
控制点列表 = [ (x1,y1,r1,g1,b1), (x2,y2,r2,g2,b2), ..., (xn,yn,rn,gn,bn) ]

// 计算目标点颜色
函数 计算目标颜色(x_target, y_target):
    总权重 = 0
    累计r = 0, 累计g = 0, 累计b = 0
    极小值 = 1e-6  // 避免除以0
    
    遍历每个控制点 in 控制点列表:
        dx = x_target - 控制点.x
        dy = y_target - 控制点.y
        距离 = sqrt(dx*dx + dy*dy)
        
        如果 距离 < 极小值:
            返回 (控制点.r, 控制点.g, 控制点.b)
        
        权重 = 1 / (距离^p)  // p为幂次,通常取2,可调整
        累计r += 控制点.r * 权重
        累计g += 控制点.g * 权重
        累计b += 控制点.b * 权重
        总权重 += 权重
    
    // 归一化得到最终颜色
    最终r = 累计r / 总权重
    最终g = 累计g / 总权重
    最终b = 累计b / 总权重
    
    返回 (最终r, 最终g, 最终b)

Python实现

import numpy as np
from PIL import Image

def idw_color_interpolation(target_x, target_y, control_points, p=2):
    total_weight = 0.0
    r_sum, g_sum, b_sum = 0.0, 0.0, 0.0
    eps = 1e-6
    
    for (x, y, r, g, b) in control_points:
        dx = target_x - x
        dy = target_y - y
        dist = np.sqrt(dx**2 + dy**2)
        if dist < eps:
            return (r, g, b)
        weight = 1.0 / (dist ** p)
        r_sum += r * weight
        g_sum += g * weight
        b_sum += b * weight
        total_weight += weight
    
    r = int(round(r_sum / total_weight))
    g = int(round(g_sum / total_weight))
    b = int(round(b_sum / total_weight))
    
    # 确保颜色值在0-255范围内
    r = max(0, min(255, r))
    g = max(0, min(255, g))
    b = max(0, min(255, b))
    return (r, g, b)

if __name__ == "__main__":
    # 生成随机控制点,可替换为自定义点
    np.random.seed(42)
    width, height = 500, 500
    num_points = 10
    control_points = []
    for _ in range(num_points):
        x = np.random.randint(0, width)
        y = np.random.randint(0, height)
        r = np.random.randint(0, 256)
        g = np.random.randint(0, 256)
        b = np.random.randint(0, 256)
        control_points.append((x, y, r, g, b))
    
    # 生成图像
    img_array = np.zeros((height, width, 3), dtype=np.uint8)
    for y in range(height):
        for x in range(width):
            img_array[y, x] = idw_color_interpolation(x, y, control_points)
    
    img = Image.fromarray(img_array)
    img.save("idw_color_gradient.png")
    img.show()

方法二:Delaunay三角剖分 + 重心插值

该方法先将控制点剖分为三角网格,再在每个三角形内部通过重心坐标做线性插值,渐变过渡更平滑,效果更接近目标网站的网格风格。

伪代码

// 步骤1:执行Delaunay三角剖分
三角剖分结果 = 生成Delaunay三角网格(控制点的(x,y)坐标集合)
// 每个三角形由三个控制点的索引组成

// 步骤2:找到目标点所属的三角形
函数 找到所属三角形(x_target, y_target, 三角剖分结果, 控制点列表):
    遍历每个三角形 in 三角剖分结果:
        p1 = 控制点列表[三角形索引0]
        p2 = 控制点列表[三角形索引1]
        p3 = 控制点列表[三角形索引2]
        如果 点(x_target,y_target) 在三角形p1-p2-p3内部:
            返回 (p1, p2, p3)
    // 边界外的点返回最近的控制点
    返回 距离最近的控制点

// 步骤3:重心坐标插值计算颜色
函数 重心插值颜色(x_target, y_target, p1, p2, p3):
    x1, y1, r1, g1, b1 = p1
    x2, y2, r2, g2, b2 = p2
    x3, y3, r3, g3, b3 = p3
    
    // 计算重心坐标(u, v, w),满足u + v + w = 1
    分母 = (y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3)
    u = ((y2 - y3)*(x_target - x3) + (x3 - x2)*(y_target - y3)) / 分母
    v = ((y3 - y1)*(x_target - x3) + (x1 - x3)*(y_target - y3)) / 分母
    w = 1 - u - v
    
    // 加权计算颜色
    r = u*r1 + v*r2 + w*r3
    g = u*g1 + v*g2 + w*g3
    b = u*b1 + v*b2 + w*b3
    
    返回 (r, g, b)

// 主函数
函数 计算目标颜色(x_target, y_target):
    三角形顶点 = 找到所属三角形(x_target, y_target, 三角剖分结果, 控制点列表)
    如果 三角形顶点是单个控制点:
        返回 该控制点颜色
    否则:
        返回 重心插值颜色(x_target, y_target, 三角形顶点[0], 三角形顶点[1], 三角形顶点[2])

Python实现

import numpy as np
from PIL import Image
from scipy.spatial import Delaunay

def barycentric_interpolation(target_x, target_y, p1, p2, p3):
    x1, y1, r1, g1, b1 = p1
    x2, y2, r2, g2, b2 = p2
    x3, y3, r3, g3, b3 = p3
    
    denom = (y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3)
    u = ((y2 - y3)*(target_x - x3) + (x3 - x2)*(target_y - y3)) / denom
    v = ((y3 - y1)*(target_x - x3) + (x1 - x3)*(target_y - y3)) / denom
    w = 1.0 - u - v
    
    r = u*r1 + v*r2 + w*r3
    g = u*g1 + v*g2 + w*g3
    b = u*b1 + v*b2 + w*b3
    
    r = int(round(max(0, min(255, r))))
    g = int(round(max(0, min(255, g))))
    b = int(round(max(0, min(255, b))))
    return (r, g, b)

def get_nearest_control_point(target_x, target_y, control_points):
    min_dist = float('inf')
    nearest_point = None
    for pt in control_points:
        dx = target_x - pt[0]
        dy = target_y - pt[1]
        dist = np.sqrt(dx**2 + dy**2)
        if dist < min_dist:
            min_dist = dist
            nearest_point = pt
    return nearest_point

if __name__ == "__main__":
    np.random.seed(42)
    width, height = 500, 500
    num_points = 10
    
    # 生成随机控制点
    control_points = []
    coords = []
    for _ in range(num_points):
        x = np.random.randint(0, width)
        y = np.random.randint(0, height)
        r = np.random.randint(0, 256)
        g = np.random.randint(0, 256)
        b = np.random.randint(0, 256)
        control_points.append((x, y, r, g, b))
        coords.append([x, y])
    coords = np.array(coords)
    
    # 执行Delaunay三角剖分
    tri = Delaunay(coords)
    
    # 生成图像
    img_array = np.zeros((height, width, 3), dtype=np.uint8)
    for y in range(height):
        for x in range(width):
            simplex_idx = tri.find_simplex([x, y])
            if simplex_idx == -1:
                # 边界外点用最近控制点颜色
                nearest_pt = get_nearest_control_point(x, y, control_points)
                img_array[y, x] = (nearest_pt[2], nearest_pt[3], nearest_pt[4])
            else:
                idx1, idx2, idx3 = tri.simplices[simplex_idx]
                p1 = control_points[idx1]
                p2 = control_points[idx2]
                p3 = control_points[idx3]
                img_array[y, x] = barycentric_interpolation(x, y, p1, p2, p3)
    
    img = Image.fromarray(img_array)
    img.save("delaunay_color_gradient.png")
    img.show()

内容的提问来源于stack exchange,提问作者Jacob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 11:45:30