Python裁剪序列帧空白区域-CutImage
问题
思路:读取该序列帧每张图片的区域,计算出可以包住所有图片的外圈范围,在1024*1024的大图基础上裁剪每张图片,生成统一的大小。。单张图片就当做只有一帧的序列帧来处理。如下图:三张序列帧的范围frame1,frame2,frame3,最终导出3张最外圈大小的图片。
代码实现
1、复制图片到输出目录
# 遍历目录封装
def traverse_dirs(dirname, callback, params):
names = os.listdir(dirname)
for name in names:
if name == ".svn" or name == ".git":
continue;
subdirname = os.path.join(dirname, name)
try:
if os.path.isdir(subdirname):
traverse_dirs(subdirname, callback, params)
else:
callback(subdirname, params)
except:
raise;
# 拷贝到输出目录
def copy_files(outpath):
if not os.path.exists(outpath):
os.makedirs(outpath)
filePaths = [];
traverse_dirs(dirpath, func_traverse_dirs, filePaths)
for filepath in filePaths:
shutil.copy2(filepath, outpath + '/' + os.path.basename(filepath))
2、计算目录下序列帧的四个边界
# 四个边界
def get_cropped_boxes(dirpath, crop_onebyone):
filePaths = [];
traverse_dirs(dirpath, func_traverse_dirs, filePaths)
x, y, w, h = 2048, 2048, 0, 0
for filepath in filePaths:
if is_filter_file(filepath, dirpath): continue
image = Image.open(filepath)
image.load()
imageSize = image.size
imageBox = image.getbbox()
imageComponents = image.split()
if len(imageComponents) < 4: continue #don't process images without alpha
rgbImage = Image.new("RGB", imageSize, (0,0,0))
rgbImage.paste(image, mask=imageComponents[3])
croppedBox = rgbImage.getbbox()
if croppedBox[0] < x: x = croppedBox[0]
if croppedBox[1] < y: y = croppedBox[1]
if croppedBox[2] > w: w = croppedBox[2]
if croppedBox[3] > h: h = croppedBox[3]
3、 处理图片 按照上一步计算出来的边界来裁剪
# crop 裁剪
for filepath in filePaths:
if is_filter_file(filepath, dirpath):
continue
image = Image.open(filepath)
image.load()
imageSize = image.size
imageBox = image.getbbox()
imageComponents = image.split()
if len(imageComponents) < 4: continue #don't process images without alpha
croppedBox = (x, y, w, h)
# UI图片非序列帧可以把crop_onebyone设置为True
if crop_onebyone:
rgbImage = Image.new("RGB", imageSize, (0,0,0))
rgbImage.paste(image, mask=imageComponents[3])
croppedBox = rgbImage.getbbox()
else:
print("crop_onebyone == false")
cropped = image.crop(croppedBox)
cropped.save(filepath)
4、大小如果超标可以等比缩放
# 限制图片大小
maxsize = (512,512)
def resize_files(outpath):
filePaths = [];
traverse_dirs(outpath, func_traverse_dirs, filePaths);
for filepath in filePaths:
if is_filter_file(filepath, outpath):
continue
image = Image.open(filepath)
image.thumbnail(maxsize, Image.ANTIALIAS)
image.save(filepath)
其他
- UI图片这种单张图片可以设置
crop_onebyone
为True。 - 执行get_cropped_boxes("./xxx", True)就ok了。
后记
-
后来想想美术打开.bat或者.py编辑目录有点麻烦,于是查了下python导出exe选择目录去执行的方法,使用Tkinter或者Wxpython实现,下一篇再探讨细节hohoho。。
-
看到有人实现的单张图片裁剪的,只需要裁剪单张可以这样:
https://blog.csdn.net/qq_24226819/article/details/73716482#!/usr/bin/env python # coding: utf-8 from PIL import Image import types def get(path, i): im = Image.open(path, 'r') width, height = im.size pix = im.load() minx = 10000 miny = 10000 maxx = -1 maxy = -1 for x in range(0, width): for y in range(0, height): if pix[x, y][3] != 0: if minx > x: minx = x if miny > y: miny = y; if maxx < x: maxx = x if maxy < y: maxy = y; print i,minx, miny #print maxx, maxy cut(path, minx, miny, maxx, maxy) def cut(path, minx, miny, maxx, maxy): im = Image.open(path) box = (minx, miny, maxx, maxy) # 设定裁剪区域 region = im.crop(box) # 裁剪图片,并获取句柄region region.save(path, 'png') for i in range(1,95): path = "D:\\mytest\\cut\\1111\\100"+str(i)+".png" get(path, i)