
背景需求
前期在“留白边”过程中,发现AI的图片本身很大,顶格,无法实现很宽的描边和点状虚线、也无法让点状虚线与边线保持空隙(留白边),顶格的裁剪会沿线剪不能剪出完整一条(少点纸屑,便于整理)
【教学类-102-08】剪纸图案全套代码08——Python点状虚线优化版本02(有空隙)+制作1图2图6图24图-优快云博客文章浏览阅读746次,点赞15次,收藏6次。【教学类-102-08】剪纸图案全套代码08——Python点状虚线优化版本02(有空隙)+制作1图2图6图24图
https://blog.youkuaiyun.com/reasonsummer/article/details/147155698?spm=1011.2415.3001.5331
代码展示
'''
先把255白背景图片背景部分白色放大,然后(蝴蝶)做成透明图,及点状虚线,透明\切边\统一大小,保存1图2图4图24图,虚线与上下左右有空隙
deepseek,阿夏
20250412
'''
from PIL import Image, ImageDraw
import os
import math
print('------0、基本信息-----')
# 主路径b
path = r'C:\Users\jg2yXRZ\OneDrive\桌面\20250401边缘线剪纸'
a='11'
b='蝴蝶'
# 白边宽度(像素)
# white_border_width = 20
white_border_width = 40
# 黑点直径(像素)
# dot_size = 10
dot_size = 10
# 黑点间距(像素)
dot_spacing = dot_size * 2 # 增加间距确保均匀分布
# 白色背景放大
# bb=200
bb=3000
# 白边参数设置
transparent_edge = 50 # 裁剪时不保留额外透明边距(这个没有用)
# 图片大小
# target_width = 1400 # 统一宽度
# target_height = 1400 # 统一高度
target_width = 2000 # 统一宽度
target_height = 2000 # 统一高度
# 定义文件夹路径
in_folder = os.path.join(path,f'{a}_01{b}白背景') # 原始图片(白背景)
big_folder = os.path.join(path, f'{a}_02{b}放大背景') # 放大背景输出
transparent_folder = os.path.join(path, f'{a}_03{b}透明背景') # 透明背景输出
output_folder = os.path.join(path, f'{a}_04{b}虚线轮廓') # 最终输出
input_folder = output_folder # 原始图片文件夹
cropped_folder = os.path.join(path,f'{a}_05{b}虚线切边') # 裁剪后的透明图片
final=f'{a}_06{b}虚线切边统一图'# 1000*1000统一图
resized_folder = os.path.join(path,f'{final}')
# 创建输出文件夹
os.makedirs(output_folder,exist_ok=True)
os.makedirs(big_folder,exist_ok=True)
os.makedirs(cropped_folder, exist_ok=True)
os.makedirs(resized_folder, exist_ok=True)
os.makedirs(transparent_folder, exist_ok=True)
os.makedirs(output_folder, exist_ok=True)
print('------1、白色PNG背景放大一点-----')
# 遍历输入文件夹中的所有PNG文件
for filename in os.listdir(in_folder):
if filename.lower().endswith('.png'):
# 打开原始图片
input_path = os.path.join(in_folder, filename)
with Image.open(input_path) as img:
original_width, original_height = img.size
# 创建新画布(长宽各+200,白色背景)
new_width = original_width + bb
new_height = original_height + bb
new_image = Image.new('RGB', (new_width, new_height), (255, 255, 255))
# 计算粘贴位置(居中)
paste_x = (new_width - original_width) // 2
paste_y = (new_height - original_height) // 2
# 将原始图片粘贴到新画布上
new_image.paste(img, (paste_x, paste_y), img if img.mode == 'RGBA' else None)
# 保存结果
big_path = os.path.join(big_folder, filename)
new_image.save(big_path)
print('------2、白色PNG背景变成透明-----')
# 先把图片白色部分变成透明
def process_image_to_transparent(file_path):
img = Image.open(file_path)
img = img.convert("RGBA")
datas = img.getdata()
new_data = []
for item in datas:
if item[0] == 255 and item[1] == 255 and item[2] == 255:
# 设置为完全透明
new_data.append((255, 255, 255, 0))
else:
new_data.append(item)
img.putdata(new_data)
return img
# 第一步:将白背景转为透明背景
print("正在转换白背景为透明背景...")
for file_name in os.listdir(big_folder):
if file_name.lower().endswith((".png", ".jpg", ".jpeg")):
input_file_path = os.path.join(big_folder, file_name)
output_file_path = os.path.join(transparent_folder, file_name)
processed_image = process_image_to_transparent(input_file_path)
processed_image.save(output_file_path)
print(f"已处理: {file_name}")
print('------3、添加点状虚线轮廓-----')
def get_edge_pixels(image):
"""获取图像中不透明像素与透明像素交界的边缘像素坐标"""
edge_pixels = []
pixels = image.load()
width, height = image.size
for y in range(height):
for x in range(width):
if pixels[x, y][3] > 0: # 不透明像素
# 检查4邻域
for dx, dy in [(-1,0),(1,0),(0,-1),(0,1)]:
nx, ny = x+dx, y+dy
if 0 <= nx < width and 0 <= ny < height:
if pixels[nx, ny][3] == 0: # 邻域透明
edge_pixels.append((x, y))
break
return edge_pixels
def expand_edge_pixels(edge_pixels, distance, width, height):
"""扩展边缘像素坐标到指定距离"""
expanded_pixels = set()
for x, y in edge_pixels:
for dy in range(-distance, distance+1):
for dx in range(-distance, distance+1):
nx, ny = x+dx, y+dy
if 0 <= nx < width and 0 <= ny < height:
expanded_pixels.add((nx, ny))
return expanded_pixels
def get_contour_pixels(border_pixels, width, height):
"""获取白边区域的外轮廓像素(使用边缘追踪算法)"""
# 找到起始点(最左上角的边界像素)
start_point = None
for y in range(height):
for x in range(width):
if (x,y) in border_pixels:
start_point = (x,y)
break
if start_point:
break
if not start_point:
return []
# 使用Moore-Neighbor追踪算法获取轮廓
contour = []
current = start_point
previous = (current[0]-1, current[1]) # 假设从左侧开始
directions = [
(0, -1), (1, -1), (1, 0), (1, 1),
(0, 1), (-1, 1), (-1, 0), (-1, -1)
]
while True:
contour.append(current)
# 找到下一个边界点
found = False
start_dir = (directions.index((previous[0]-current[0], previous[1]-current[1])) + 1) % 8
for i in range(8):
dir_idx = (start_dir + i) % 8
dx, dy = directions[dir_idx]
neighbor = (current[0]+dx, current[1]+dy)
if 0 <= neighbor[0] < width and 0 <= neighbor[1] < height:
if neighbor in border_pixels:
previous = current
current = neighbor
found = True
break
if not found or current == start_point:
break
return contour
def draw_uniform_dots(image, contour, dot_size, dot_spacing):
"""在轮廓上均匀绘制黑点"""
dot_layer = Image.new('RGBA', image.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(dot_layer)
if not contour:
return dot_layer
# 计算轮廓总长度
total_length = 0
segments = []
for i in range(len(contour)):
p1 = contour[i]
p2 = contour[(i+1)%len(contour)]
dx = p2[0] - p1[0]
dy = p2[1] - p1[1]
length = math.sqrt(dx*dx + dy*dy)
segments.append((p1, p2, lengt