一、解决的问题
1.图片指定位置和大小切割
2.指定大小切割
3.指定按照原大小比例切割
4.压缩图片为指定大小
二、具体原理、代码及执行结果
1.图片指定位置和大小切割
需要指定剪切的部分在原图片的位置,本代码是设置box1 = (0, 50, 100, 100)来设置左,上,右,下四个参数来实现剪切。
话不多说直接上代码
# coding: utf-8
from PIL import Image
import os
import os.path
import numpy as np
import cv2
#指明被遍历的文件夹
rootdir = r"D:/soft/Notebook_workspace/myself/photo_add/01/"
for parent, dirnames, filenames in os.walk(rootdir):#遍历每一张图片
for filename in filenames:
print('parent is :' + parent)
print('filename is :' + filename)
currentPath = os.path.join(parent, filename)
print('the fulll name of the file is :' + currentPath)
img = Image.open(currentPath)
print (img.format, img.size, img.mode)
box1 = (0, 50, 100, 100)#设置左、上、右、下的像素
image1 = img.crop(box1) # 图像裁剪
image1.save(r"D:/soft/Notebook_workspace/myself/photo_add/05/"+'\\'+filename) #存储裁剪得到的图像
执行结果:
2.指定大小切割
在指定大小切割时,我们会有一个问题,那就是原图片大小与需要切割的大小不成整数比时,无法完美切割,本文以图片完整性优先,在不成整数比时采用从边界开始反向剪裁来保证图片数据的完整性,当然,你可以自己更改代码将其舍弃。
(1)正方形
将原图片切割成边长为w的正方形,通过设置参数w设置需要切成图片块的大小,默认大小为w*w
代码部分如下:
import os
from PIL import Image
#用PIL库批量裁剪指定大小的图像(自动填充)
def img_crop(img_path, save_path):
files = os.listdir(img_path)
for file in files:
a, b = os.path.splitext(file)
img = Image.open(os.path.join(img_path + "/" + file))
width, hight = img.size
w = 100 # 需要切成图片块的大小,默认大小为w*w,可以自己设置
id = 1
i = 0
padw = padh = 0 # 当宽高除不尽切块大小时,对最后一块进行填充
if width % w != 0:
padw = 1 # 宽除不尽的情况
if hight % w != 0:
padh = 1 # 高除不尽的情况
# 默认从最左上角向右裁剪,再向下裁剪
while i + w <= hight:
j = 0
while j + w <= width:
new_img = img.crop((j, i, j + w, i + w))
new_img.save(save_path + a + "_" + str(id) + b)
id += 1
j += w
if padw == 1: # 宽有除不尽的情况
new_img = img.crop((width - w, i, width, i + w))
new_img.save(save_path + a + "_" + str(id) + b)
id += 1
i = i + w
if padh == 1: # 高除不尽的情况
j = 0
while j + w <= width:
new_img = img.crop((j, hight - w, j + w, hight))
new_img.save(save_path + a + "_" + str(id) + b)
id += 1
j += w
if padw == 1:
new_img = img.crop((width - w, hight - w, width, hight))
new_img.save(save_path + a + "_" + str(id) + b)
id += 1
if __name__ == '__main__':
# img_path:输入图像的路径
img_path = r"D:/soft/Notebook_workspace/myself/photo_add/01/"
# save_path:图像保存的位置
save_path = r"D:/soft/Notebook_workspace/myself/photo_add/03/"
if not os.path.exists(save_path): # 如果没有这个文件夹,就新建
os.makedirs(save_path)
img_crop(img_path, save_path)
执行结果:
(2)矩形
与切割成为正方形类似,唯一的区别是需要设置横向长度w1和纵向长度w2两个参数。
函数代码部分如下(其他部分与上方相同):
def img_crop(img_path, save_path):
files = os.listdir(img_path)
for file in files:
a, b = os.path.splitext(file)
img = Image.open(os.path.join(img_path + "/" + file))
width, hight = img.size
w1 = 120 # 需要切成图片块的大小,默认大小为w*w,可以自己设置
w2=80
id = 1
i = 0
padw = padh = 0 # 当宽高除不尽切块大小时,对最后一块进行填充
if width % w1 != 0:
padw = 1 # 宽除不尽的情况
if hight % w2 != 0:
padh = 1 # 高除不尽的情况
# 默认从最左上角向右裁剪,再向下裁剪
while i + w2 <= hight:
j = 0
while j + w1 <= width:
new_img = img.crop((j, i, j + w1, i + w2))
new_img.save(save_path + a + "_" + str(id) + b)
id += 1
j += w1
if padw == 1: # 宽有除不尽的情况
new_img = img.crop((width - w1, i, width, i + w2))
new_img.save(save_path + a + "_" + str(id) + b)
id += 1
i = i + w2
if padh == 1: # 高除不尽的情况
j = 0
while j + w1 <= width:
new_img = img.crop((j, hight - w2, j + w1, hight))
new_img.save(save_path + a + "_" + str(id) + b)
id += 1
j += w1
if padw == 1:
new_img = img.crop((width - w1, hight - w2, width, hight))
new_img.save(save_path + a + "_" + str(id) + b)
id += 1
3.指定按照原大小比例切割
可以将原图片的长高按照比例切割,你只需要设置两个参数就可以 heightCutNum = 2; widthCutNum = 2; 其中heightCutNum是将剪裁后的图片的高变为的1/heightCutNum倍,另一个也是一样的;
代码部分如下:
import cv2
import os
# Cutting the input image to h*w blocks
heightCutNum = 2;
widthCutNum = 2;
# The folder path of input and output
inPath = r"D:/soft/Notebook_workspace/myself/photo_add/01/"
outPath = r"D:/soft/Notebook_workspace/myself/photo_add/04/"
for f in os.listdir(inPath):
path = inPath + f.strip()
print(path)
img = cv2.imread(path)
# The size of each input image
height = img.shape[0]
width = img.shape[1]
# The size of block that you want to cut
heightBlock = int(height / heightCutNum)
widthBlock = int(width / widthCutNum)
for i in range(0,heightCutNum):
for j in range(0,widthCutNum):
cutImage = img[i*heightBlock:(i+1)*heightBlock, j*widthBlock:(j+1)*widthBlock]
savePath = outPath + f.strip()[0:5] + "_" + str(i) + str(j) + ".jpg"
cv2.imwrite(savePath,cutImage)
执行结果:
4.压缩图片为指定大小
将大小不同的图片压缩成指定大小,只需要对 pic_new = pic_org.resize((w1, w2), Image.ANTIALIAS) 的两个参数进行更改就好,w1为长,w2为高。
代码部分如下:
# 图片压缩 压缩到相同的大小
from PIL import Image
import os
file_path = r"D:/soft/Notebook_workspace/myself/photo_add/01/" # 原始图像路径
save_path = r"D:/soft/Notebook_workspace/myself/photo_add/02/" # 修改后图像存储的路径
if not os.path.exists(save_path): # 如果没有这个文件夹,就新建
os.makedirs(save_path)
for root, dirs, files in os.walk(file_path):
for file in files: # 展现各文件
picture_path = os.path.join(root, file) # 得到图像的绝对路径
pic_org = Image.open(picture_path) # 打开图像
pic_new = pic_org.resize((100, 50), Image.ANTIALIAS) # 图像尺寸修改
pic_new_path = os.path.join(save_path, file) # 新图像存储绝对路径
pic_new.save(pic_new_path) # 存储文件
print("%s 已裁切完成!" %pic_new_path)
执行结果: