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)

该代码实现的功能是:

  1. 从用户输入的文件夹路径中读取图片和坐标文件。
  2. 支持 JSON、XML 和 TXT 格式的坐标文件。
  3. 使用 OpenCV 或 PIL 库根据坐标信息截取图片。
  4. 在截取图片时,可以根据用户输入的变量扩展截取范围。
  5. 将截取到的图片保存到指定的文件夹,并根据相对坐标信息命名图片。

使用方法:

  1. 将代码保存为 Python 文件,例如 crop_image.py
  2. 运行代码,输入图片文件夹路径、坐标文件夹路径、扩展截图范围的变量、截图工具和保存截图的文件夹路径。
  3. 代码会自动根据坐标文件截取图片,并将截取到的图片保存到指定的文件夹。

代码示例:

假设图片文件夹路径为 images,坐标文件夹路径为 coords,扩展截图范围的变量为 10,截图工具选择 opencv,保存截图的文件夹路径为 cropped_images,则运行代码时的输入如下:

请输入图片文件夹路径:images
请输入坐标文件夹路径:coords
请输入扩展截图范围的变量(默认为10):10
请选择截图工具(1:opencv,2:PIL,默认为opencv):1
请输入保存截图的文件夹路径:cropped_images

代码会自动从 images 文件夹中读取图片,从 coords 文件夹中读取坐标文件,并根据坐标信息截取图片,将截取到的图片保存到 cropped_images 文件夹中。

注意:

  • 坐标文件的格式需要与代码中指定的格式一致。
  • 坐标文件中的坐标信息需要是相对于图片左上角的坐标。
  • 扩展截图范围的变量是指截取范围超出坐标范围的像素个数。
  • 可以根据需要修改代码中的截图工具和保存截图的文件夹路径。

希望以上内容对您有所帮助。如果您还有其他问题,请随时提出。

Python 图片截取工具:根据坐标从图片中截取指定区域

原文地址: https://www.cveoy.top/t/topic/nnhx 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录