Python按照指定大小和比例居中裁剪和缩放图片
Python 图片 指定 大小 居中 缩放 按照 裁剪
2023-09-11 14:21:25 时间
2022.5.10 更新:
- 要求手动输入图片源文件夹(支持
~
符号作为用户主目录)- 转换后的文件名增加了新尺寸
- 修复了代码中的一处算法错误
- 自动删除源文件夹和目标文件夹中讨厌的
.DS_Store
文件(如果有的话)- 移除了不必要的time库
To Do:
- 增加不同方位剪裁的功能(不按比例缩放时)
- 做成GUI界面的(等我学会了QT再说吧…)
这个脚本的需求,源于某些场景下机器学习需要预先处理数据,例如端侧目标检测如果将训练数据集处理成与端侧图像输入相同的尺寸,会明显提高准确率。
上代码,使用了pillow
和pathlib
。最后显示源文件夹、目标文件夹,转换的文件数量,以及文件列表。代码会自动遍历子文件夹,但对文件类型不进行检测,对不同子文件夹存在的重名文件也不进行检测,如果子文件夹有重名文件,会默认覆盖同名的输出文件。
运行完毕后,会显示原始图片文件夹,目标文件夹,目标分辨率,转换文件数量,以及转换的文件列表。
版本要求:
Python版本 >=3.6(我用了f表达式)
先看效果:
Github地址(如果有更新会更新到仓库)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 将文件夹下的图片居中剪裁为指定比例并缩放到指定大小
###
from PIL import Image
from pathlib import Path
import sys
# 目标尺寸
dst_w = 224
dst_h = 224
def remove_ds_store(path):
# print('检查 %s 内是否存在 .DS_Store 文件'%str(path))
target = path/'.DS_Store'
if (target.exists()):
Path.unlink(target)
print(f'{target} 文件已自动删除。')
else:
# print(f'.DS_Store 文件不存在,继续操作。')
pass
def resize_dir_images(src_path):
global filecount
remove_ds_store(src_path)
for f in src_path.glob('**/*'): # 也可以用src_path.rglob('*')
if f.is_file():
filecount += 1
print('正在转换第 %d 个文件:%s \r'%(filecount,f.name),end='')
crop_and_resize(f)
def crop_and_resize(fp):
''' 图片按照目标比例裁剪并缩放 '''
global dst_w,dst_h,dst_path,option
im = Image.open(str(fp))
src_w,src_h = im.size
dst_scale = float(dst_h / dst_w) #目标高宽比
src_scale = float(src_h / src_w) #原高宽比
if src_scale >= dst_scale:
#过高
# print("原图过高")
width = src_w
height = int(width*dst_scale)
x = 0
y = (src_h - height) / 2
else:
#过宽
# print("原图过宽\n")
height = src_h
width = int(height/dst_scale)
x = (src_w - width) / 2
y = 0
#裁剪
box = (x,y,width+x,height+y)
#这里的参数可以这么认为:从某图的(x,y)坐标开始截,截到(width+x,height+y)坐标
newIm = im.crop(box)
im = None
#压缩
ratio = float(dst_w) / width
newWidth = int(width * ratio)
newHeight = int(height * ratio)
# dst_file = dst_path/fp.name # 保持原文件名
dst_file = dst_path/f'{fp.stem}_{dst_w}x{dst_h}{fp.suffix}' # 文件名添加新尺寸
newIm.resize((newWidth,newHeight),Image.Resampling.LANCZOS).save(dst_file,quality=100)
def get_src_path():
src_dir = input('请输入图片文件夹位置(输入Q或q退出):')
if src_dir == "Q" or src_dir == 'q':
sys.exit()
src_path = Path(src_dir)
src_path = src_path.expanduser()
print("输入的文件夹:",src_path)
return src_path
def main():
global src_path,dst_path,filecount
src_path = get_src_path()
while (not src_path.exists()):
print(f'文件夹{src_path}不存在,请检查输入的文件夹名称是否正确。')
src_path = get_src_path()
dst_dir = f'{src_path}_{dst_w}x{dst_h}'
dst_path = Path(dst_dir)
filecount = 0
# 此参数规定了最后文件列表每行显示的文件名数量。
display_each_line = 10
cnt = 0
# print('原始图片文件夹:',src_path)
print('目标文件夹:',dst_path)
if dst_path.exists():
print(f'目标文件夹 {dst_path} 已经存在...')
pass
else:
# print(f'创建目标文件夹: {dst_path} ')
dst_path.mkdir(parents=True)
print(f'目标分辨率:{dst_w}x{dst_h}')
resize_dir_images(src_path)
remove_ds_store(dst_path)
# dst_file_list = dst_path.iterdir() #
# 直接遍历目标文件夹下的jpg/jpeg文件(使用*.jp*g来匹配两种后缀名)。
dst_file_list = dst_path.glob('*.jp*g')
print(f'\n一共转换了{filecount}个文件\n已转换的文件列表:',end='')
line_count = 0
for f in sorted(dst_file_list, key = lambda f : f.stem):
cnt += 1
if cnt%display_each_line == 1:
line_count += 1
print('\n%d | %10s'%(line_count,f.name),end='')
else:
print('%10s'%f.name,end='')
if __name__ == '__main__':
main()
参考文献:
python使用pil进行图像处理(等比例压缩、裁剪)实例代码
注意上述参考文献页面的代码算法有误
相关文章
- Python opencv提取视频中的图片
- 【Python成长之路】python 基础篇 -- 装饰器【华为云分享】
- Python学习--06切片
- python 图片和base64互相转换
- python中学习K-Means和图片压缩
- Python学习小技巧之列表项的排序
- python实现基于两张图片生成圆角图标效果的方法
- paddle 44 用onnxruntime实现ppyoloe模型的部署(含python和c++版本),支持batchsize
- Python之schedule:schedule库的简介、安装、使用方法之详细攻略
- Python语言学习:利用python获取当前/上级/上上级目录路径(获取路径下的最后叶目录的文件名、合并两个不同路径下图片文件名等目录/路径案例、正确加载图片路径)之详细攻略
- 已解决Python调用免费申请的百度图形识别接口案例
- python让你再也不为文章配图与素材发愁,让高清图片占满你的硬盘! #华为云·寻找黑马程序员#
- 从零开始学python | 什么是Python JSON?
- python 指定日期图片文件删除
- Python编程:socket模块
- Python编程:pyenv管理多个python版本环境
- Python编程:loguru管理日志输出
- Python科学计算库演示
- Python标准库:内置函数dict(mapping, **kwarg)
- python实战===2017年30个惊艳的Python开源项目 (转)
- python使用技巧(二十六):批量复制图片或文件到另一文件目录
- removebg图片换背景_Python版