Python 图片截取工具:根据坐标从图片中截取指定区域
import os
import json
import xml.etree.ElementTree as ET
from PIL import Image
import cv2
def read_coordinates(filepath, file_type):
'''
根据文件类型读取坐标信息
'''
if file_type == 'json':
with open(filepath, 'r') as f:
data = json.load(f)
if 'coordinates' in data:
return data['coordinates']
elif file_type == 'xml':
root = ET.parse(filepath).getroot()
coord_list = []
for obj in root.iter('object'):
coords = obj.find('bndbox')
coord_list.append([
int(coords.find('xmin').text),
int(coords.find('ymin').text),
int(coords.find('xmax').text),
int(coords.find('ymax').text)
])
return coord_list
elif file_type == 'txt':
with open(filepath, 'r') as f:
coords = f.readline().strip()
coords = [int(coord) for coord in coords.split(',')]
return coords
else:
raise ValueError('Unknown file type')
return None
def capture_image(image_path, coords, var, save_path, method='cv2'):
'''
实现根据坐标截取图像
'''
if method == 'cv2':
img = cv2.imread(image_path)
xmin, ymin, xmax, ymax = coords
xmin = max(0, xmin - var)
ymin = max(0, ymin - var)
xmax = min(img.shape[1], xmax + var)
ymax = min(img.shape[0], ymax + var)
img = img[ymin:ymax, xmin:xmax]
cv2.imwrite(save_path, img)
elif method == 'PIL':
img = Image.open(image_path)
xmin, ymin, xmax, ymax = coords
xmin = max(0, xmin - var)
ymin = max(0, ymin - var)
xmax = min(img.width, xmax + var)
ymax = min(img.height, ymax + var)
img = img.crop((xmin, ymin, xmax, ymax))
img.save(save_path)
if __name__ == '__main__':
image_dir = input('请输入图片文件夹路径:').strip()
if not os.path.isdir(image_dir):
print('无效的图片文件夹路径')
exit(1)
coord_dir = input('请输入坐标文件夹路径:').strip()
if not os.path.isdir(coord_dir):
print('无效的坐标文件夹路径')
exit(1)
var = int(input('请输入扩展截图范围的变量(默认为10):').strip() or '10')
method = input('请选择截图工具(1:opencv,2:PIL,默认为opencv):').strip()
method = 'cv2' if method != '2' else 'PIL'
save_dir = input('请输入保存截图的文件夹路径:').strip()
if not os.path.isdir(save_dir):
print('无效的保存文件夹路径')
exit(1)
for filename in os.listdir(image_dir):
if filename.endswith(('jpg', 'jpeg', 'png', 'JPG', 'JPEG', 'PNG')):
basename = os.path.splitext(filename)[0]
coord_path = os.path.join(coord_dir, basename + '.xml')
if not os.path.isfile(coord_path):
coord_path = os.path.join(coord_dir, basename + '.json')
if not os.path.isfile(coord_path):
coord_path = os.path.join(coord_dir, basename + '.txt')
if not os.path.isfile(coord_path):
continue
coords = read_coordinates(coord_path, os.path.splitext(coord_path)[-1][1:])
if coords is None:
continue
img_path = os.path.join(image_dir, filename)
img = Image.open(img_path) if method == 'PIL' else cv2.imread(img_path)
for i, coord in enumerate(coords):
xmin = max(0, coord[0] - var)
ymin = max(0, coord[1] - var)
xmax = min(img.width if method == 'PIL' else img.shape[1], coord[2] + var)
ymax = min(img.height if method == 'PIL' else img.shape[0], coord[3] + var)
xmin = min(xmin, xmax-var)
ymin = min(ymin, ymax-var)
save_path = os.path.join(save_dir, '{}_{}_{}_{}_{}_{}.{}'.format(basename, xmin-coord[0], ymin-coord[1], xmax-coord[2], ymax-coord[3], i, filename.split('.')[-1]))
capture_image(img_path, [xmin, ymin, xmax, ymax], var, save_path, method)
print('保存截图:', save_path)
该代码实现的功能是:
- 从用户输入的文件夹路径中读取图片和坐标文件。
- 支持 JSON、XML 和 TXT 格式的坐标文件。
- 使用 OpenCV 或 PIL 库根据坐标信息截取图片。
- 在截取图片时,可以根据用户输入的变量扩展截取范围。
- 将截取到的图片保存到指定的文件夹,并根据相对坐标信息命名图片。
使用方法:
- 将代码保存为 Python 文件,例如
crop_image.py。 - 运行代码,输入图片文件夹路径、坐标文件夹路径、扩展截图范围的变量、截图工具和保存截图的文件夹路径。
- 代码会自动根据坐标文件截取图片,并将截取到的图片保存到指定的文件夹。
代码示例:
假设图片文件夹路径为 images,坐标文件夹路径为 coords,扩展截图范围的变量为 10,截图工具选择 opencv,保存截图的文件夹路径为 cropped_images,则运行代码时的输入如下:
请输入图片文件夹路径:images
请输入坐标文件夹路径:coords
请输入扩展截图范围的变量(默认为10):10
请选择截图工具(1:opencv,2:PIL,默认为opencv):1
请输入保存截图的文件夹路径:cropped_images
代码会自动从 images 文件夹中读取图片,从 coords 文件夹中读取坐标文件,并根据坐标信息截取图片,将截取到的图片保存到 cropped_images 文件夹中。
注意:
- 坐标文件的格式需要与代码中指定的格式一致。
- 坐标文件中的坐标信息需要是相对于图片左上角的坐标。
- 扩展截图范围的变量是指截取范围超出坐标范围的像素个数。
- 可以根据需要修改代码中的截图工具和保存截图的文件夹路径。
希望以上内容对您有所帮助。如果您还有其他问题,请随时提出。
原文地址: https://www.cveoy.top/t/topic/nnhx 著作权归作者所有。请勿转载和采集!