python向图片添加文字

329 阅读2分钟
from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageStat
from collections import Counter
import numpy as np
from skimage import measure
import os
import random


# 获取图片中颜色最多的颜色 并取反
def get_image_color(img_path):
    img = Image.open(img_path)
    img = img.convert('RGB')
    width, height = img.size
    # Initialize Variable
    r_total = 0
    g_total = 0
    b_total = 0
    count = 0
    # Iterate through each pixel
    for x in range(0, width):
        for y in range(0, height):
            # r,g,b value of pixel
            r, g, b = img.getpixel((x, y))
            r_total += r
            g_total += g
            b_total += b
            count += 1
    # 对三个变量进一取整
    r_total = 255 - int(r_total / count)
    g_total = 255 - int(g_total / count)
    b_total = 255 - int(b_total / count)
    return r_total, g_total, b_total


# 随机获取字体
def get_font(fonts_path):
    # 遍历./chara文件夹下所有文件 有多层
    font_list = []
    for root, dirs, files in os.walk(fonts_path):
        for file in files:
            font_list.append(os.path.join(root, file))
    # 随机选择一个字体
    return random.choice(font_list)


def determine_position(bbox, img_width, img_height):
    # 计算文本边界框的中心点
    x_center = (bbox[0] + bbox[2]) / 2
    y_center = (bbox[1] + bbox[3]) / 2

    # 计算图片的中心点
    img_center_x = img_width / 2
    img_center_y = img_height / 2

    # 判断文本中心点相对于图片中心点的位置
    if x_center < img_center_x and y_center < img_center_y:
        return "top left"
    elif x_center == img_center_x and y_center < img_center_y:
        return "top"
    elif x_center > img_center_x and y_center < img_center_y:
        return "top right"
    elif x_center < img_center_x and y_center == img_center_y:
        return "left"
    elif x_center == img_center_x and y_center == img_center_y:
        return "center"
    elif x_center > img_center_x and y_center == img_center_y:
        return "right"
    elif x_center < img_center_x and y_center > img_center_y:
        return "bottom left"
    elif x_center == img_center_x and y_center > img_center_y:
        return "bottom"
    else:
        return "bottom right"


def main():
    # json参数
    json_data = {"image_source_path": "./营销海报数据采集样例", "image_target_path": "./营销海报数据采集样例-new",
                 "font_path": "./chara",
                 "data_list": [{
                     "img_name": "1 (1).png",
                     "annotations": [
                         {
                             "polygon": (133, 210),
                             "text": "中国",
                             "language": "Chinese",
                         },
                         {
                             "polygon": (0, 310),
                             "text": "移动",
                             "language": "Chinese",
                         }
                     ]

                 }, {
                     "img_name": "1 (2).png",
                     "annotations": [
                         {
                             "polygon": (133, 110),
                             "text": "中国",
                             "language": "Chinese",
                         },
                         {
                             "polygon": (0, 110),
                             "text": "移动",
                             "language": "Chinese",
                         }
                     ]

                 }]}
    # 创建新文件夹
    if not os.path.exists(json_data['image_target_path']):
        os.makedirs(json_data['image_target_path'])

    # 获取图片文字列表
    for data in json_data["data_list"]:
        # 图片路径
        image_path = os.path.join(json_data['image_source_path'], data['img_name'])
        # 打开一个图片文件
        image = Image.open(image_path)
        # 获取随机字体
        font_file = get_font(json_data['font_path'])
        # 文字颜色
        text_color = get_image_color(image_path)
        # 文字大小
        image_size = image.size
        font_size = int((image_size[0] + image_size[1]) / 7)
        # 创建一个可以在给定图像上绘图的对象
        draw = ImageDraw.Draw(image)
        # 设置字体
        font = ImageFont.truetype(font_file, font_size)
        for annotation in data['annotations']:
            draw.text(annotation['polygon'], annotation['text'], font=font, fill=text_color)
            # 计算4
            bbox = draw.textbbox(annotation['polygon'], annotation['text'], font)
            # 获取图片尺寸
            text_position = determine_position(bbox, image_size[0], image_size[1])
            annotation['pos'] = text_position
            # 保存修改后的图片
            image.save(os.path.join(json_data['image_target_path'], data['img_name']))
    print(json_data)


if __name__ == "__main__":
    main()