【教学类-102-12】蝴蝶外轮廓02——Python对黑白图片进行PS填充三种颜色+图案黑色描边(RBG160-250)+内部图案填充白色+制作1图2图6图24图

背景需求:

1、黑色描边没有在透明与非透明的交界线上,而是向外扩展了10磅,所以原始的灰色边缘还是显示了。


解决方向:把黑色描边画在边界线上,如果线宽10磅,透明部分5磅、非透明部分5磅


2、三色图有三色(透明、黑色、蓝色),黑色与蓝色之间的边线也是灰色的。

解决方向:只显示透明、黑色、白色,其他灰色不要。

【教学类-102-11】蝴蝶外轮廓01——Python对黑白图片进行PS填充三种颜色+图案描边+图案填充白色+制作1图2图6图24图-优快云博客文章浏览阅读899次,点赞25次,收藏6次。【教学类-102-11】蝴蝶外轮廓01——Python对黑白图片进行PS填充三种颜色+图案描边+图案填充白色+制作1图2图6图24图 https://blog.youkuaiyun.com/reasonsummer/article/details/147234191?spm=1011.2415.3001.5331

关键词

'''
优化版
剪纸外轮廓描边虚线制作(黑点虚线)沿线剪——最终稳定版
将图片变成三色(透明、黑色、蓝色)
先把255白背景图片背景部分白色放大,然后(蝴蝶)做成透明图,及点状虚线,透明\切边\统一大小,保存1图2图4图24图,虚线与上下左右有空隙
黑线在透明与非透明交界线上,透明部分5磅,非透明不放呢5磅,
将非透明部分改成纯白色,没有任何灰色。
deepseek,阿夏
20250415
'''
from PIL import Image, ImageDraw
import os
import math


print('------0、基本信息-----')
# 主路径
path = r'C:\Users\jg2yXRZ\OneDrive\桌面\20250401边缘线剪纸'
a='15'
b='蝴蝶三色'
c='实线黑边白色图'

all=path+fr'\{a}{b}合并图'

# 参数设置
white_border_width = 10  # 黑边宽度(像素)
transparent_edge = 20   # 裁剪时不保留额外透明边距
target_width = 2000     # 统一宽度
target_height = 2000    # 统一高度
background_expand = 1000 # 白色背景放大尺寸

# 定义文件夹路径
in_folder = os.path.join(path,f'{a}_01{b}白背景')  # 原始图片(白背景)
big_folder = os.path.join(path, f'{a}_02{b}{c}放大背景')  # 放大背景输出
transparent_folder = os.path.join(path, f'{a}_03{b}{c}透明背景')  # 透明背景输出
output_folder = os.path.join(path, f'{a}_04{b}{c}黑边轮廓')  # 最终输出
input_folder = output_folder  # 原始图片文件夹
cropped_folder = os.path.join(path,f'{a}_05{b}{c}切边') # 裁剪后的透明图片
final_folder  = os.path.join(path,f'{a}_06{b}{c}切边统一图')

# 创建输出文件夹
os.makedirs(all, exist_ok=True)
os.makedirs(output_folder,exist_ok=True)
os.makedirs(big_folder,exist_ok=True)
os.makedirs(cropped_folder, exist_ok=True)
os.makedirs(final_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 + background_expand
            new_height = original_height + background_expand
            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))
        elif item[0] == 254 and item[1] == 255 and item[2] == 255:
            new_data.append((254, 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、添加黑色实线轮廓-----')

print('------3、添加黑色实线轮廓-----')

white_border_width = 10  # 总黑边宽度(像素),透明部分5px,非透明部分5px

def convert_to_white(image):
    """将所有非透明像素强制转换为纯白色,并确保完全透明像素为(0,0,0,0)"""
    img = image.convert("RGBA")
    datas = img.getdata()
    
    new_data = []
    for item in datas:
        if item[3] > 0:  # 不透明像素
            new_data.append((255, 255, 255, 255))  # 纯白
        else:
            new_data.append((0, 0, 0, 0))  # 完全透明
    img.putdata(new_data)
    return img

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:  # 不透明像素
                for dx, dy in [(-1,0),(1,0),(0,-1),(0,1)]:  # 4邻域检查
                    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 create_border_mask(edge_pixels, width, height):
    """创建边框遮罩,使边框位于透明与非透明交界中间"""
    # 创建两个扩展区域:向内5px和向外5px
    inner_pixels = set()
    outer_pixels = set()
    
    for x, y in edge_pixels:
        # 向内扩展5px(非透明区域)
        for dy in range(-5, 6):
            for dx in range(-5, 6):
                nx, ny = x+dx, y+dy
                if 0 <= nx < width and 0 <= ny < height:
                    dist = (dx**2 + dy**2)**0.5
                    if dist <= 5:
                        inner_pixels.add((nx, ny))
        
        # 向外扩展5px(透明区域)
        for dy in range(-5, 6):
            for dx in range(-5, 6):
                nx, ny = x+dx, y+dy
                if 0 <= nx < width and 0 <= ny < height:
                    dist = (dx**2 + dy**2)**0.5
                    if dist <= 5:
                        outer_pixels.add((nx, ny))
    
    # 合并两个区域得到10px宽的边框
    border_pixels = inner_pixels.union(outer_pixels)
    return border_pixels

def draw_centered_border(image, border_pixels):
    """绘制居中于边缘的10px宽黑色边框"""
    border_layer = Image.new('RGBA', image.size, (0, 0, 0, 0))
    pixels = border_layer.load()
    
    # 标记所有边框像素为黑色
    for x, y in border_pixels:
        pixels[x, y] = (0, 0, 0, 255)
    
    return border_layer

def add_centered_border(input_path, output_path):
    """处理单个图像,添加居中黑色边框"""
    original = Image.open(input_path).convert('RGBA')
    
    # 1. 先将所有非透明部分转为纯白色
    white_image = convert_to_white(original)
    width, height = white_image.size
    
    # 2. 获取原始边缘
    edge_pixels = get_edge_pixels(white_image)
    
    # 3. 创建居中边框遮罩
    border_pixels = create_border_mask(edge_pixels, width, height)
    
    # 4. 绘制黑色边框
    border_layer = draw_centered_border(white_image, border_pixels)
    
    # 5. 合成结果(黑色边框在白色图像上方)
    result = Image.alpha_composite(white_image, border_layer)
    
    # 6. 最终清理,确保只有纯黑、纯白或透明
    result_data = result.getdata()
    final_data = []
    for item in result_data:
        if item[3] == 0:  # 透明
            final_data.append((0, 0, 0, 0))
        elif item[:3] == (0, 0, 0):  # 黑色
            final_data.append((0, 0, 0, 255))
        else:  # 白色
            final_data.append((255, 255, 255, 255))
    result.putdata(final_data)
    
    result.save(output_path, format='PNG')
    print(f"已添加居中黑边: {os.path.basename(input_path)}")

# 处理所有透明背景图片,添加居中黑色边框
for file_name in os.listdir(transparent_folder):
    if file_name.lower().endswith('.png'):
        input_path = os.path.join(transparent_folder, file_name)
        output_path = os.path.join(output_folder, file_name)
        add_centered_border(input_path, output_path)

# 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:  # 不透明像素
#                 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 []
    
#     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_solid_border(image, contour, border_width):
#     """在轮廓上绘制实心黑边"""
#     border_layer = Image.new('RGBA', image.size, (0, 0, 0, 0))
#     draw = ImageDraw.Draw(border_layer)
    
#     if len(contour) < 2:
#         return border_layer
    
#     # 绘制粗实线
#     for i in range(len(contour)):
#         p1 = contour[i]
#         p2 = contour[(i+1)%len(contour)]
#         draw.line([p1, p2], fill=(0, 0, 0, 255), width=border_width)
    
#     return border_layer

# def add_solid_border(input_path, output_path):
#     """处理单个图像,添加实线黑色边框"""
#     original = Image.open(input_path).convert('RGBA')
#     # 复制原来的图像
#     original_copy = original.copy()
#     width, height = original.size
    
#     # 获取边缘并扩展黑边区域
#     edge_pixels = get_edge_pixels(original)
#     border_pixels = expand_edge_pixels(edge_pixels, white_border_width, width, height)
    
#     # 获取精确的外轮廓
#     contour = get_contour_pixels(border_pixels, width, height)
    
#     # 绘制实心黑边
#     border_layer = draw_solid_border(original, contour, white_border_width)
    
#     # 合成结果
#     result = Image.alpha_composite(original, border_layer)
#     # 复制原图
#     result = Image.alpha_composite(result, original_copy)
    
#     result.save(output_path, format='PNG')
#     print(f"已添加{c}轮廓: {os.path.basename(input_path)}")

# # 处理所有透明背景图片,添加黑色实线轮廓
# for file_name in os.listdir(transparent_folder):
#  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿夏reasonsummer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值