python pillow 把图片切成拼图块
Posted zbbzb
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python pillow 把图片切成拼图块相关的知识,希望对你有一定的参考价值。
契机:
当我看到这个视频里的素材, 很馋, 但是原作者也没有发素材文件, 只能自己弄素材了, 3D就直接pass了, 不熟和学习成本过高, 那就2D的来, 目的是脚本文件可以批量把照片分隔成拼图块
分解需求
最简易的矩形ROI分割(剪裁),其本质是多维数组(矩阵)的切片
1. 分隔成n*m个方块
2. 拿出一个方块, 获取左右方块 之间的中心圆心坐标, 还有上下方块 之间的中心圆心坐标, 然后补满这个圆就可以获得拼图的凸出, 消减这个圆可以获得拼图的凹入
3. 增加圆心偏移
也就是让凸出和凹进更加好看点
4. 随机凹凸
先了解下怎么切圆
python3切割圆形图片
看完这篇文章可知如何生成圆形图片
新建一个图像b, 然后把a中符合这个圆的点复制b中, 输出图像b, 就生成了圆形图像
如何符合圆, 要用到初中的知识点, 点到圆心的距离 <= 半径
分隔成n*m个方块
import os
from PIL import Image
# 分割几行几列, 二维数组保存
def SplitImages(img_path, row, col):
path_name = os.path.dirname(img_path)
img = Image.open(img_path).convert("RGBA")
imgSize = img.size
splitW = int(imgSize[0]/col)
splitL = int(imgSize[1]/row)
pimg = img.load()
imbList = []
for i in range(row):
rowList = []
l = (i + 1) * splitL
for j in range(col):
w = (j + 1) * splitW
imb = Image.new('RGBA', (splitW, splitL),(255,255,255,0))
pimb = imb.load()
for k in range(j * splitW, w):
for z in range(i * splitL, l):
pimb[k - splitW * j, z - i * splitL] = pimg[k,z]
dirPath = path_name + "/" + str(i*10 + j) + ".png"
# imb.save(dirPath)
rowList.append(imb)
imbList.append(rowList)
return imbList
简单版
不考虑随机凹凸, 不考虑圆心偏移, 凹凸都是固定的, 从第一个开始向右凸出, 向下凸出
def SplitCircle(imbList, imgPath):
path_name = os.path.dirname(imgPath)
img = Image.open(imgPath).convert("RGBA")
imgSize = img.size
col = len(imbList[0])
row = len(imbList)
if col == 1 and row == 1:
return
splitW = int(imgSize[0]/col)
splitL = int(imgSize[1]/row)
minV = min(splitW, splitL)
r_d = int(minV / 4) # 要计算 两个不能比 l 长 并且加上 offset 也不能超过 l
#r_offset = int(minV / 8)
#pSplitW = splitW + (r_d + r_offset) * 2
#pSplitL = splitL + (r_d + r_offset) * 2
pimg = img.load()
pointList = []
for i in range(row):
colPointList = []
for j in range(col):
colPoint = []
rowPoint = []
if j != col - 1:
colPoint = [splitW * (j + 1), int(splitL/2) + i * splitL]
if i != row - 1:
rowPoint = [int(splitW / 2) + j * splitW, splitL * (i + 1)]
colPointList.append({'colPoint': colPoint, 'rowPoint': rowPoint})
pointList.append(colPointList)
for i in range(row):
for j in range(col):
imbImg = imbList[i][j]
new_img = imbImg
if j != col - 1 and i != row - 1:
l = imbImg.size[1]
w = imbImg.size[0]
l = l + r_d
w = w + r_d
new_img = Resize(imbImg, w, l)
elif j == col - 1 and i != row - 1:
new_img = Resize(imbImg, splitW, splitL + r_d)
elif j != col - 1 and i == row - 1:
new_img = Resize(imbImg, splitW + r_d, splitL)
new_img_imb = new_img.load()
if j != col - 1:
new_next_img = imbList[i][j + 1]
new_next_img_imb = new_next_img.load()
# 左右
for k in range((j + 1) * splitW, (j + 1) * splitW + r_d):
for z in range(i * splitL, (i + 1) * splitL):
r_w = pointList[i][j]['colPoint'][0]
r_l = pointList[i][j]['colPoint'][1]
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_img_imb[k - j * splitW , z - i * splitL] = pimg[k, z]
new_next_img_imb[k - (j + 1) * splitW, z - i * splitL] = (255,255,255,0)
imbList[i][j + 1] = new_next_img
if i!= row - 1:
new_down_img = imbList[i + 1][j]
new_down_img_imb = new_down_img.load()
# 上下
for k in range(j * splitW, (j + 1) * splitW):
for z in range((i + 1) * splitL, (i + 1) * splitL + r_d):
r_w = pointList[i][j]['rowPoint'][0]
r_l = pointList[i][j]['rowPoint'][1]
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_img_imb[k - j * splitW, z - i * splitL] = pimg[k, z]
new_down_img_imb[k - j * splitW, z - (i + 1) * splitL] = (255,255,255,0)
imbList[i + 1][j] = new_down_img
imbList[i][j] = new_img
for i in range(row):
for j in range(col):
dirPath = path_name + "/" + str(i*10 + j) + ".png"
imbList[i][j].save(dirPath)
最终版
随机凹凸, 考虑圆心偏移
import os
from PIL import Image
import random
# 分割几行几列, 二维数组保存
def SplitImages(img_path, row, col):
path_name = os.path.dirname(img_path)
img = Image.open(img_path).convert("RGBA")
imgSize = img.size
splitW = int(imgSize[0]/col)
splitL = int(imgSize[1]/row)
pimg = img.load()
imbList = []
for i in range(row):
rowList = []
l = (i + 1) * splitL
for j in range(col):
w = (j + 1) * splitW
imb = Image.new('RGBA', (splitW, splitL),(255,255,255,0))
pimb = imb.load()
for k in range(j * splitW, w):
for z in range(i * splitL, l):
pimb[k - splitW * j, z - i * splitL] = pimg[k,z]
dirPath = path_name + "/" + str(i*10 + j) + ".png"
# imb.save(dirPath)
rowList.append(imb)
imbList.append(rowList)
return imbList
def Resize(img, rizeW, rizel, pastePoint=None):
if pastePoint is None:
pastePoint = [0, 0]
new_im = Image.new('RGBA', [rizeW, rizel],(255,255,255,0))
new_im.paste(img, pastePoint)
return new_im
def SplitCircle(imbList, imgPath):
path_name = os.path.dirname(imgPath)
img = Image.open(imgPath).convert("RGBA")
imgSize = img.size
col = len(imbList[0])
row = len(imbList)
if col == 1 and row == 1:
return
splitW = int(imgSize[0]/col)
splitL = int(imgSize[1]/row)
minV = min(splitW, splitL)
r_d = int(minV / 4) # 要计算 两个不能比 l 长 并且加上 offset 也不能超过 l
r_offset = int(minV / 8)
pSplitW = splitW + (r_d + r_offset) * 2
pSplitL = splitL + (r_d + r_offset) * 2
pimg = img.load()
# 存(row - 1) * (col - 1) 个中心点
pointList = []
for i in range(row):
colPointList = []
for j in range(col):
colPoint = []
rowPoint = []
if j != col - 1:
colPoint = [splitW * (j + 1), int(splitL/2) + i * splitL]
if i != row - 1:
rowPoint = [int(splitW / 2) + j * splitW, splitL * (i + 1)]
colPointList.append({'colPoint': colPoint, 'rowPoint': rowPoint})
imbList[i][j] = Resize(imbList[i][j], pSplitW, pSplitL, [r_d + r_offset, r_d + r_offset])
dirPath = path_name + "/" + str(i*10 + j) + ".png"
# imbList[i][j].save(dirPath)
pointList.append(colPointList)
for i in range(row):
for j in range(col):
imbImg = imbList[i][j]
new_img = imbImg
# 圆心靠左 靠右, 默认靠右
lrandNum = random.randint(0, 999999)
drandNum = random.randint(0, 999999)
lrRight = True
drRight = True
if lrandNum < 500000:
lrRight = False
if drandNum < 500000:
drRight = False
new_img_imb = new_img.load()
if j != col - 1:
if lrRight :
new_next_img = imbList[i][j + 1]
new_next_img_imb = new_next_img.load()
# 左右
for k in range((j + 1) * splitW, (j + 1) * splitW + r_d + r_offset):
for z in range(i * splitL, (i + 1) * splitL):
r_w = pointList[i][j]['colPoint'][0] + r_offset
r_l = pointList[i][j]['colPoint'][1]
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_img_imb[k - j * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = pimg[k, z]
new_next_img_imb[k - (j + 1) * splitW + r_d + r_offset, z - i * splitL + r_d + r_offset] = (255,255,255,0)
imbList[i][j + 1] = new_next_img
else:
new_next_img = imbList[i][j + 1]
new_next_img_imb = new_next_img.load()
# 左右
for k in range((j + 1) * splitW - r_d - r_offset, (j + 1) * splitW):
for z in range(i * splitL, (i + 1) * splitL):
r_w = pointList[i][j]['colPoint'][0] - r_offset
r_l = pointList[i][j]['colPoint'][1]
r = ((pow(abs(k - r_w),2) + pow(abs(z - r_l),2))) ** 0.5
if r < r_d:
new_next_img_imb[k - (j + 1) * splitW + r_d + r_offset, z - i 以上是关于python pillow 把图片切成拼图块的主要内容,如果未能解决你的问题,请参考以下文章