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

如何在skimage或OpenCV中绘制内外渐变的椭圆蒙版?

嘿,这个渐变椭圆蒙版的需求其实很好实现,我给你分享两种靠谱的方案——分别用scikit-image和OpenCV来搞定,代码都加了详细注释,你可以直接跑起来试试~

方法一:用scikit-image实现

核心思路是基于距离变换:先生成椭圆蒙版,计算椭圆内部每个点到边界的距离,再把距离值映射成颜色渐变,距离越远(越靠近中心)的点用你想要的“内部色”,距离越近(靠近边界)的点过渡到“外部色”。

import numpy as np
from skimage.draw import ellipse
from skimage.morphology import distance_transform_edt
from skimage import io, color

# 1. 创建空白画布,尺寸可以自己调整
height, width = 500, 500
# 先生成椭圆蒙版的基础图
mask_base = np.zeros((height, width), dtype=np.float32)

# 2. 绘制填充椭圆:参数分别是中心y坐标、中心x坐标、短半轴、长半轴
rr, cc = ellipse(height//2, width//2, 150, 200)
mask_base[rr, cc] = 1  # 椭圆区域标记为1,其余为0

# 3. 计算距离变换:得到椭圆内部每个点到边界的欧氏距离
dist_map = distance_transform_edt(mask_base)

# 4. 归一化距离值到0-1范围,方便映射颜色
dist_normalized = (dist_map - dist_map.min()) / (dist_map.max() - dist_map.min())

# 5. 生成自定义渐变效果:这里示例是中心深红色,边界过渡到浅粉色
# 分别给RGB通道赋值,用归一化后的距离值做权重
red_channel = dist_normalized * 255  # 中心红值最高,边界逐渐降低
green_channel = (1 - dist_normalized) * 100  # 中心绿值低,边界升高
blue_channel = (1 - dist_normalized) * 255  # 中心蓝值低,边界升高
# 合并成RGB图像
gradient_img = np.stack([red_channel, green_channel, blue_channel], axis=-1).astype(np.uint8)

# 显示或保存图像
io.imshow(gradient_img)
io.show()
# io.imsave('ellipse_gradient_skimage.png', gradient_img)

小技巧

  • 如果想要反向渐变(边界颜色深,中心浅),只需要把dist_normalized换成1 - dist_normalized即可。
  • 也可以用skimage的颜色映射函数,比如color.apply_colormap(dist_normalized, 'viridis'),快速得到现成的渐变效果。
方法二:用OpenCV实现

OpenCV的思路和skimage类似,只是API不同,它的distanceTransform和applyColorMap能快速帮你生成渐变效果,适合习惯OpenCV的开发者。

import cv2
import numpy as np

# 1. 创建空白蒙版画布
height, width = 500, 500
mask = np.zeros((height, width), dtype=np.uint8)

# 2. 绘制填充椭圆:参数依次是蒙版、中心坐标、轴长(长轴、短轴)、旋转角度、起始角度、结束角度、颜色、填充厚度
center = (width//2, height//2)
axes_length = (200, 150)
cv2.ellipse(mask, center, axes_length, 0, 0, 360, 255, -1)  # -1表示填充整个椭圆

# 3. 计算距离变换:DIST_L2是欧氏距离,5是距离变换的掩码大小
dist_map = cv2.distanceTransform(mask, cv2.DIST_L2, 5)

# 4. 归一化距离值到0-255的uint8范围,方便后续颜色映射
dist_normalized = cv2.normalize(dist_map, None, 0, 255, cv2.NORM_MINMAX, dtype=cv2.CV_8U)

# 5. 生成渐变效果:两种方式可选
# 方式1:用OpenCV自带的颜色映射(比如COLORMAP_JET,自带蓝到红的渐变)
jet_gradient = cv2.applyColorMap(dist_normalized, cv2.COLORMAP_JET)

# 方式2:自定义渐变,比如中心白色,边界黑色
custom_gradient = np.zeros((height, width, 3), dtype=np.uint8)
# 三个通道都用归一化后的距离值,中心值高(白色),边界值低(黑色)
custom_gradient[..., 0] = dist_normalized
custom_gradient[..., 1] = dist_normalized
custom_gradient[..., 2] = dist_normalized
# 反向渐变的话,改成custom_gradient = 255 - dist_normalized[:, :, None]

# 显示效果
cv2.imshow('Ellipse Gradient (OpenCV)', jet_gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
# cv2.imwrite('ellipse_gradient_opencv.png', jet_gradient)

额外扩展

如果需要渐变到透明的效果,可以给图像加一个alpha通道,把归一化后的距离值映射到alpha通道的透明度(比如中心不透明,边界逐渐透明):

# 以OpenCV为例,添加alpha通道
rgba_img = cv2.cvtColor(jet_gradient, cv2.COLOR_BGR2BGRA)
rgba_img[..., 3] = dist_normalized  # alpha通道用距离值,中心255(不透明),边界0(透明)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:47:09