PIL批量给图片加上字母序号

本文介绍如何使用Python的PIL库在图片上绘制指定的文字,并在圆圈中进行定位,包括处理特殊字符的偏移问题。

效果图

这里用的图片全是 240X240 的,按文件名的首字母作为序号,PIL 虽然可以计算文字的尺寸,但类似 D 这样的字符依然不能处于圆圈的正中,所以还对个别字符做了偏移设置,本来想用 aggdraw 画圆圈的,能平滑一些,不过安装了好几次,都以失败告终,最终放弃。

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import os, sys, fnmatch
import Image, ImageDraw, ImageFont

def process_picture(filename):
    seq = os.path.split(filename)[-1][0].upper()
    img = Image.open(os.path.join(input_dir, filename))

    draw = ImageDraw.Draw(img)

    # 在右下角画白底黑框圆圈
    draw.ellipse((215, 215, 235, 235), outline='black', fill='white')

    # 将字母序号写入到圆圈内
    font = ImageFont.truetype('fonts/Times New Roman.ttf', 20)

    # 计算文字居中的位置
    text_size = draw.textsize(seq, font)
    x = (20 / 2) - (text_size[0] / 2)
    y = (20 / 2) - (text_size[1] / 2)

    # 字母偏移量
    offsets = {'A': 1, 'B': 1, 'E': 1, 'D': 2}
    offset = offsets.get(seq, 0)
    draw.text((215 + x + offset, 215 + y), seq, font=font, fill='black')

    # save image
    img.save(os.path.join(output_dir, filename), 'JPEG')

if __name__ == '__main__':
    if len(sys.argv) < 3:
        print 'Usage: python drawseq.py <input_dir> <output_dir>'
        sys.exit(1)

    input_dir, output_dir = sys.argv[1:3]
    os.path.exists(output_dir) or os.makedirs(output_dir)

    for filename in os.listdir(input_dir):
        if fnmatch.fnmatch(filename.lower(), '*.jpg'):
            process_picture(filename)
转自:http://www.g2w.me/2012/08/draw-char-in-picture-using-pil/
from openpyxl import load_workbook from openpyxl.drawing.image import Image as OpenpyxlImage from PIL import Image as PilImage from io import BytesIO import os import shutil def export_images_by_row(excel_path, output_base_dir): """ 将Excel中每行的图片导出到单独的文件夹,并为有内容但无图片的行创建空文件夹 参数: excel_path: Excel文件路径 output_base_dir: 图片输出基础目录 """ # 创建基础输出目录 os.makedirs(output_base_dir, exist_ok=True) # 加载工作簿 wb = load_workbook(excel_path) # 存储所有有内容的行 content_rows = set() # 遍历所有工作表 for sheet_name in wb.sheetnames: ws = wb[sheet_name] print(f"处理工作表: {sheet_name}") # 行计数器字典 {行号: 该行图片数量} row_counter = {} # 存储有图片的行 image_rows = set() # 第一步:识别所有有内容的行 for row in ws.iter_rows(min_row=1): # 检查行是否有内容(任意单元格非空) if any(cell.value is not None for cell in row): content_rows.add((sheet_name, row[0].row)) # 存储(工作表名, 行号) # 第二步:处理图片 for img in ws._images: # 获取图片位置信息 anchor = img.anchor start_row = None # 根据不同的锚点类型获取起始行号 if hasattr(anchor, '_from') and hasattr(anchor._from, 'row'): start_row = anchor._from.row # 新版本openpyxl elif hasattr(anchor, 'from_row'): start_row = anchor.from_row # 旧版本openpyxl if start_row is None: print("无法确定图片位置,跳过") continue # 添加到有图片的行集合 image_rows.add(start_row) # 获取该行标识(使用第一列的值) row_identifier = ws.cell(row=start_row, column=1).value if row_identifier is None: row_identifier = f"row_{start_row}" # 创建行专属文件夹 row_folder = os.path.join(output_base_dir, f"{sheet_name}_{row_identifier}") os.makedirs(row_folder, exist_ok=True) # 更新行计数器 if start_row not in row_counter: row_counter[start_row] = 1 else: row_counter[start_row] += 1 # 获取图片二进制数据 try: img_data = img._data() # 旧版本openpyxl except TypeError: img_data = img._data # 新版本openpyxl # 使用PIL保存图片 try: img_pil = PilImage.open(BytesIO(img_data)) img_path = os.path.join(row_folder, f"image_{row_counter[start_row]}.png") img_pil.save(img_path) print(f"已保存: {img_path}") except Exception as e: print(f"保存图片失败: {str(e)}") # 第三步:为有内容但无图片的行创建空文件夹 for sheet, row_num in content_rows: if sheet == sheet_name and row_num not in image_rows: # 获取行标识 row_identifier = ws.cell(row=row_num, column=1).value if row_identifier is None: row_identifier = f"row_{row_num}" # 创建空文件夹 empty_folder = os.path.join(output_base_dir, f"{sheet_name}_{row_identifier}") os.makedirs(empty_folder, exist_ok=True) print(f"创建无图片行的空文件夹: {empty_folder}") wb.close() print(f"\n导出完成!所有内容行已处理,输出目录: {os.path.abspath(output_base_dir)}") # 使用示例 if __name__ == "__main__": excel_file = "E:/pythonproject313/转换/111.xlsx" # 替换为您的Excel文件路径 output_dir = "E:/pythonproject313/转换/pic" # 图片输出基础目录 export_images_by_row(excel_file, output_dir) 将该代码文件夹名称从序号1开始排练
最新发布
08-13
批量处理给图片添加序号通常是在图像数据集中进行预处理的步骤,特别是在机器学习项目中对大量图片进行标记以便训练模型。以下是使用Python及其一些常见库如Pandas、OpenCV和NumPy进行批量操作的一个简单流程: 1. 导入必要的库: ```python import os import cv2 import numpy as np from PIL import Image import pandas as pd ``` 2. 定义目录结构: 假设你有一个包含子目录的主目录,每个子目录代表一类图片,例如: ``` main_dir = 'images' class_dirs = ['class1', 'class2', 'class3'] ``` 3. 创建一个空列表保存文件信息: ```python image_info = [] ``` 4. 遍历所有类别和图片: ```python for class_dir in class_dirs: class_dir_path = os.path.join(main_dir, class_dir) for filename in os.listdir(class_dir_path): img_path = os.path.join(class_dir_path, filename) # 读取图片并获取宽度(假设高度固定) img = cv2.imread(img_path) width = img.shape[1] # 添加序号和文件路径到信息列表 image_info.append({ 'filename': filename, 'class': class_dir, 'number': len(image_info) + 1, # 序列号从1开始 'width': width }) ``` 5. 将信息转换为DataFrame并保存: ```python df_images = pd.DataFrame(image_info) df_images.to_csv('image_labels.csv', index=False) ``` 6. 如果需要在图片上显示序号,可以加载csv文件,读取图片并在适当位置添加文本: ```python def add_label_to_image(row, save_path): img = Image.open(os.path.join(main_dir, row['class'], row['filename'])) draw = ImageDraw.Draw(img) label_text = f'{row["number"]}' label_position = (10, 10) # 可调整位置 draw.text(label_position, label_text, font=..., fill=(255, 255, 255)) img.save(save_path) # 对DataFrame应用函数 df_images.apply(lambda x: add_label_to_image(x, f'image_{x["number"]}.jpg'), axis=1) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值