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

如何用Python实现书法字母的线条粗细自适应点填充效果

书法字母转动态点填充效果实现方案

核心思路

利用距离变换获取文字线条的粗细信息,以此控制点的大小,再通过网格采样绘制连贯的点集,替代原线条。


步骤1:图像预处理(提取文字+获取粗细信息)

先把图像转为灰度并二值化,再通过距离变换计算每个文字像素到边缘的距离(距离值直接对应线条粗细):

import cv2
import numpy as np

# 读取图像
img = cv2.imread("your_calligraphy_img.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二值化(反相,让文字区域为白色)
_, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# 距离变换:计算每个文字像素到最近边缘的距离,值越大线条越粗
distance_map = cv2.distanceTransform(binary, cv2.DIST_L2, 5)

步骤2:映射距离值为点半径

把距离值归一化到你需要的点大小范围,比如最小1像素,最大8像素:

min_radius = 1
max_radius = 8
# 归一化距离值到半径区间
radius_map = cv2.normalize(distance_map, None, min_radius, max_radius, cv2.NORM_MINMAX)

步骤3:采样并绘制点填充效果

用网格采样遍历文字区域,按对应半径绘制圆形,保证点的连贯性:

# 创建空白画布
result = np.zeros_like(img)
# 采样步长:控制点的密度,步长越小点越密
sample_step = 3

# 遍历采样点
for y in range(0, binary.shape[0], sample_step):
    for x in range(0, binary.shape[1], sample_step):
        # 只在文字区域绘制点
        if binary[y, x] == 255:
            radius = int(radius_map[y, x])
            cv2.circle(result, (x, y), radius, (255, 255, 255), -1)

# 保存或显示结果
cv2.imwrite("dot_fill_result.jpg", result)
cv2.imshow("Result", result)
cv2.waitKey(0)

优化技巧

  • 如果原图像有噪点,预处理时加高斯模糊:gray = cv2.GaussianBlur(gray, (3, 3), 0),避免噪点生成多余的点。
  • 调整sample_step控制点的密度:步长为2-4时,点的连贯性较好,同时不会过于密集。
  • 若想让点的颜色和原书法颜色一致,可把绘制颜色改为原图像对应位置的颜色:color = img[y, x]。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 10:27:20