Files
jigsaw/01split.py
2024-12-03 11:34:51 +13:00

134 lines
3.7 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import cv2
import numpy as np
import os
# 读取输入图像
image = cv2.imread('input.jpg')
# 检查图像是否读取成功
if image is None:
print("无法读取 'input.jpg',请确保文件存在且路径正确。")
exit()
# 获取图像的尺寸
height, width = image.shape[:2]
# 创建九个掩码,初始化为全黑
masks = [np.zeros((height, width), dtype=np.uint8) for _ in range(9)]
# 定义曲线参数,增加弯曲程度
amplitude_h = height / 15 # 横向曲线的最大幅度
amplitude_v = width / 15 # 纵向曲线的最大幅度
# 定义 x 和 y 坐标
x = np.arange(width)
y = np.arange(height)
# 定义横向曲线(沿着 x 轴变化),在每个区域的中间进行一次弯曲
y_h1 = np.zeros_like(x, dtype=float)
y_h2 = np.zeros_like(x, dtype=float)
# 定义横向曲线的三个段
segment_width = width / 3
for i in range(3):
start_x = i * segment_width
end_x = (i + 1) * segment_width
center_x = (start_x + end_x) / 2
mask = (x >= start_x) & (x < end_x)
x_relative = x[mask] - center_x
amplitude_modifier = np.cos(np.pi * x_relative / (end_x - start_x)) ** 2
y_h1[mask] = (height / 3) + amplitude_h * amplitude_modifier * np.sin(np.pi * x_relative / (end_x - start_x))
y_h2[mask] = (2 * height / 3) + amplitude_h * amplitude_modifier * np.sin(np.pi * x_relative / (end_x - start_x))
# 确保 y 值在图像范围内
y_h1 = np.clip(y_h1, 0, height - 1).astype(int)
y_h2 = np.clip(y_h2, 0, height - 1).astype(int)
# 定义纵向曲线的三个段
segment_height = height / 3
x_v1 = np.zeros_like(y, dtype=float)
x_v2 = np.zeros_like(y, dtype=float)
for i in range(3):
start_y = i * segment_height
end_y = (i + 1) * segment_height
center_y = (start_y + end_y) / 2
mask = (y >= start_y) & (y < end_y)
y_relative = y[mask] - center_y
amplitude_modifier = np.cos(np.pi * y_relative / (end_y - start_y)) ** 2
x_v1[mask] = (width / 3) + amplitude_v * amplitude_modifier * np.sin(np.pi * y_relative / (end_y - start_y))
x_v2[mask] = (2 * width / 3) + amplitude_v * amplitude_modifier * np.sin(np.pi * y_relative / (end_y - start_y))
# 确保 x 值在图像范围内
x_v1 = np.clip(x_v1, 0, width - 1).astype(int)
x_v2 = np.clip(x_v2, 0, width - 1).astype(int)
# 创建网格
Y, X = np.meshgrid(np.arange(height), np.arange(width), indexing='ij')
# 获取对应的曲线值
y_curve1 = y_h1[X]
y_curve2 = y_h2[X]
x_curve1 = x_v1[Y]
x_curve2 = x_v2[Y]
# 计算区域索引
region = np.zeros((height, width), dtype=int)
# 定义区域编号如下:
# 0 | 1 | 2
# 3 | 4 | 5
# 6 | 7 | 8
# 上区域
upper = Y <= y_curve1
middle = (Y > y_curve1) & (Y <= y_curve2)
lower = Y > y_curve2
# 左、中、右区域
left = X <= x_curve1
center = (X > x_curve1) & (X <= x_curve2)
right = X > x_curve2
# 分配区域
region[upper & left] = 0
region[upper & center] = 1
region[upper & right] = 2
region[middle & left] = 3
region[middle & center] = 4
region[middle & right] = 5
region[lower & left] = 6
region[lower & center] = 7
region[lower & right] = 8
# 创建掩码
for idx in range(9):
masks[idx][region == idx] = 255
# 确保输出目录存在
output_dir = 'output'
if not os.path.exists(output_dir):
os.makedirs(output_dir)
# 应用掩码并保存带透明度的图片
for idx, mask in enumerate(masks):
# 提取 RGB 部分
img_part = cv2.bitwise_and(image, image, mask=mask)
# 转换为 BGRA
img_part = cv2.cvtColor(img_part, cv2.COLOR_BGR2BGRA)
# 设置 alpha 通道
img_part[:, :, 3] = mask
# 保存为 PNG 格式以保留透明度
cv2.imwrite(os.path.join(output_dir, f'output{idx + 1}.png'), img_part)
print("图片已成功切割成9张并保存到 'output' 目录下,带有透明背景。")