【教学类-102-01】自制剪纸图案(留白边、沿线剪)01
背景需求:
班级里个别化美工区买了一套剪纸
这批中班孩子的80、90后父母很重视孩子的手脑协调性,在家经常剪纸。所以孩子们延边剪的水平都不错。而且很有兴趣挑选图案
‘
’
不到一周,一百张彩色图纸就全部剪完了(有车类、用品、交通工具、字母等图形)
图案造型是点状虚线、留0.5CM白边
思考:
用的太快了,彩色图案比较贵。所以我想自制一些黑白线条图纸,留白边,让幼儿先涂色、再沿线剪。
(AI也可以生成彩色图片,但是学校里用彩色打印不值得。所以只考虑黑白线条图案)
思路:
1、根据之前制作青蛙立体书的经验,要想实现边框线描,必须将背景变成透明色、与非透明的青蛙主体进行区分
【教学类-83-02】20241214立体书三角嘴2.0——青蛙(扁菱形嘴)-CSDN博客文章浏览阅读1.1k次,点赞49次,收藏16次。【教学类-83-02】20241214立体书三角嘴2.0——青蛙(长扁菱形)https://blog.csdn.net/reasonsummer/article/details/144510078?spm=1011.2415.3001.5331
所以我选了已经用PS修图的青蛙图片作为实验品
2、关键词思路:找到透明与非透明的交界线,向外(在透明部分)画5磅白色边框。然后再次对新的白色边框外延与非透明部分进行检测,画一根1磅黑线。
3、问题:测试过程中,发现画的线条都是在交界线上的,5磅就是对外2.5磅,对内2.5磅,会遮住一部分图案。
多次修改后都无法改变,最后将原图覆盖在新图最上方,解决了这个难题
代码展示
'''
剪纸练习:将透明背景的png图片的边缘留空白,然后再边缘的边缘画黑色线(留边剪)
星火讯飞 阿夏
20250401
'''
from PIL import Image, ImageDraw # 导入Pillow库中的Image和ImageDraw模块
import os # 导入os模块用于文件和目录操作
# 距离图片边缘的距离(留多少白边)
bianju = 10
# 留白线的粗细(剪切边的粗细)
bianju2 = 2
def detect_edges(image):
"""
检测图像的边缘。如果像素透明,则标记为边缘。
:param image: 输入的图像
:return: 包含边缘信息的图像
"""
# 如果图像不是RGBA模式,将其转换为RGBA模式
if image.mode != 'RGBA':
image = image.convert('RGBA')
width, height = image.size # 获取图像的宽度和高度
edges = Image.new('L', (width, height), 0) # 创建一个新的灰度图像来存储边缘信息,初始值为0(黑色)
draw = ImageDraw.Draw(edges) # 创建一个ImageDraw对象用于绘制
pixels = image.load() # 加载图像的像素数据
for y in range(1, height - 1): # 遍历图像的每一行,除了第一行和最后一行
for x in range(1, width - 1): # 遍历图像的每一列,除了第一列和最后一列
r, g, b, a = pixels[x, y] # 获取当前像素的RGBA值
if a == 0: # 如果当前像素是透明的
continue # 跳过该像素
# 检查相邻的像素
neighbors = [
pixels[x-1, y], pixels[x+1, y],
pixels[x, y-1], pixels[x, y+1]
]
for nr, ng, nb, na in neighbors: # 遍历相邻的像素
if na == 0: # 如果相邻像素是透明的
draw.point((x, y), fill=255) # 将当前像素标记为边缘(白色)
break # 跳出循环
return edges # 返回包含边缘信息的图像
def expand_edges(edges, distance):
"""
扩展图像的边缘。根据给定的距离,将边缘像素扩展到指定范围。
:param edges: 包含边缘信息的图像
:param distance: 扩展的距离
:return: 扩展后的边缘图像
"""
expanded_edges = Image.new('L', edges.size, 0) # 创建一个新的灰度图像来存储扩展后的边缘信息,初始值为0(黑色)
draw = ImageDraw.Draw(expanded_edges) # 创建一个ImageDraw对象用于绘制
pixels = edges.load() # 加载图像的像素数据
for y in range(edges.height): # 遍历图像的每一行
for x in range(edges.width): # 遍历图像的每一列
if pixels[x, y] > 0: # 如果当前像素是边缘像素
for dy in range(-distance, distance + 1): # 根据给定的距离扩展边缘像素
for dx in range(-distance, distance + 1):
nx, ny = x + dx, y + dy # 计算新的像素位置
if 0 <= nx < edges.width and 0 <= ny < edges.height: # 确保新的位置在图像范围内
draw.point((nx, ny), fill=255) # 将新位置的像素标记为边缘(白色)
return expanded_edges # 返回扩展后的边缘图像
def process_images(input_folder, output_folder):
"""
处理输入文件夹中的所有PNG图像,并将结果保存到输出文件夹中。
:param input_folder: 输入文件夹路径
:param output_folder: 输出文件夹路径
"""
if not os.path.exists(output_folder):
os.makedirs(output_folder) # 如果输出文件夹不存在,则创建它
for filename in os.listdir(input_folder): # 遍历输入文件夹中的所有文件
if filename.endswith(".png"): # 只处理PNG文件
image_path = os.path.join(input_folder, filename) # 获取图像的完整路径
image = Image.open(image_path).convert('RGBA') # 打开图像并转换为RGBA模式
# 检测图像的边缘
edges = detect_edges(image)
# 扩展边缘像素,扩展距离为bianju
expanded_edges = expand_edges(edges, bianju)
# 创建一个新的图像,用红色填充边缘区域,背景为透明
result = Image.new('RGBA', image.size, (255, 255, 255, 0))
red_fill = Image.new('RGBA', image.size, (255, 255, 255, 255)) # 创建一个纯红色的图像
masked_red_fill = Image.composite(red_fill, Image.new('RGBA', image.size), expanded_edges) # 将红色图像与边缘图像合成
# 将原始图像与红色边缘图像合成
final_result = Image.alpha_composite(image, masked_red_fill)
# 创建一个临时图像,用于绘制黑色线条,不影响透明度
temp_image = Image.new('RGBA', final_result.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(temp_image)
pixels = final_result.load() # 加载最终结果的像素数据
for y in range(1, final_result.height - 1): # 遍历每一行,除了第一行和最后一行
for x in range(1, final_result.width - 1): # 遍历每一列,除了第一列和最后一列
r, g, b, a = pixels[x, y] # 获取当前像素的RGBA值
if a == 0: # 如果当前像素是透明的
continue # 跳过该像素
# 检查相邻的像素
neighbors = [
pixels[x-1, y], pixels[x+1, y],
pixels[x, y-1], pixels[x, y+1]
]
for nr, ng, nb, na in neighbors: # 遍历相邻的像素
if na == 0: # 如果相邻像素是透明的
draw.line([(x, y), (x-1, y)], fill=(0, 0, 0), width=bianju2) # 在透明侧绘制水平黑线
draw.line([(x, y), (x, y-1)], fill=(0, 0, 0), width=bianju2) # 在透明侧绘制垂直黑线
break # 跳出循环
# 将临时图像与最终结果合成
final_result = Image.alpha_composite(final_result, temp_image)
# 将原始图像与最终结果合成,保留透明度
final_result = Image.alpha_composite(final_result, image)
# 将处理后的图像保存到输出文件夹中
output_path = os.path.join(output_folder, filename)
final_result.save(output_path)
print(f"Processed {filename} and saved to {output_path}") # 打印处理完成的信息
if __name__ == '__main__':
path= r'C:\Users\jg2yXRZ\OneDrive\桌面\20250401边缘线剪纸'
input_folder =path+r'\png'
output_folder =path+r'\234'
os.makedirs(output_folder,exist_ok=True)
process_images(input_folder, output_folder)