目标
通过Python语言和相关技术库实现 快乐源泉小瓶子的自动生成。
程序文件
包括Python代码文件 main.py, bottle.json生成小瓶子的配置信息文件,以及bottle.jpg小瓶子图像,bottle2.jpg生成后的快乐源泉小瓶子
bottle.jpg
从网上找的小瓶子图像
bottle.json 配置文件
{
"title":"快乐源泉小瓶子",
"bottle_path":"./bottle.jpg",
"list":[
["第一个","第二个","第三个","第四个","第五个","第六个","第七个","第八个"],
["第一个","第二个","第三个","第四个","第五个","第六个","第七个"],
["第一个","第二个","第三个","第四个","第五个","第六个","第七个","第八个"],
["第一个","第二个","第三个","第四个","第五个","第六个","第七个"],
["第一个","第二个","第三个","第四个","第五个","第六个","第七个","第八个"]
],
"font_size":120,
"fontpath":"C:\\WINDOWS\\FONTS\\MSYHL.TTC"
}
其中 title 是标题, bottle_path 是小瓶子路径, font_size 是 标签瓶子字体大小, fontpath是字体路径,想用什么可以自行更换。
list是最重要的,是想生成瓶子的标签列表,按照这个格式替换即可,注意要是字符形状,标签不能太长。
main.py
最关键的代码部分,
环境支持
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
import json
配置参数读取设置
读取json文件中设置的相关参数,读取瓶子图像等...
with open('bottle.json', 'r', encoding='utf-8') as fp:
bottle_configure = json.load(fp)
title=bottle_configure['title']
bottle_list=bottle_configure['list']
fontpath=bottle_configure['fontpath']
font_size=bottle_configure['font_size']
bottle_path=bottle_configure['bottle_path']
#字体设置
font = ImageFont.truetype(fontpath, font_size)
font_title=ImageFont.truetype(fontpath, int(font_size*2.5))
#读取瓶子图像
bottle=cv2.imread(bottle_path)
#可在此处自行添加滤波操作(可选) bottle2=.....
bottle2=bottle
# 瓶子左右间距、上下间距
span_w = 0.4
span_h = 0.8
行列计算、总体图像大小、第一个瓶子起始点设置
根据输入的list 自动判断行数和列数,根据输入的小瓶子图像和计算的行数,列数生成相应的幕布(用于绘制图像和文字),并设置第一个瓶子的起始点。
row=len(bottle_list)
col=0
#计算最大列
for l in bottle_list:
if len(l)>col:
col=len(l)
(bottle_h, bottle_w, _) = bottle2.shape
background = np.ones((int((row+row*span_h-span_h+2+1)*bottle_h),
int(((col+1)*span_w+col)*bottle_w),
3), dtype="uint8")*250
# 起始点
stx = span_w * bottle_w
sty = bottle_h*2
绘制
#背景色一致
Background_color=np.mean(bottle2[0:3,0:3,0:3])
(background_h,background_w,_)=background.shape
for i in range(0,background_h-1):
for j in range(0,background_w-1):
background[i,j]=Background_color
# 绘制瓶子
for r in range(row):
for c in range(min(col,len(bottle_list[r]))):
stx2 = int(stx + (1+span_w)*bottle_w*c)
sty2 = int(sty + (1+span_h)*bottle_h*r)
# print(stx2, sty2)
for i in range(0, bottle_h-1):
for j in range(0, bottle_w-1):
background[sty2+i, stx2+j] = bottle2[i, j]
#绘制文字
img_pil = Image.fromarray(background)
draw = ImageDraw.Draw(img_pil)
##标题
draw.text((int(0.32*background_w), int(0.5*bottle_h)), title, font = font_title, fill = (0,0,0))
##标签
for r in range(row):
for c in range(min(col,len(bottle_list[r]))):
stx2 = int(stx + (1+span_w)*bottle_w*c)
sty2 = int(sty + (1+span_h)*bottle_h*r)
# background = cv.putText(background, bottle_list[num], (stx2+int(0.1*bottle_w), sty2+int(1.3*bottle_h)), cv.FONT_HERSHEY_COMPLEX, 0.8, (0,0,0), 2)
string=bottle_list[r][c]
string_len=len(string)
print(string,string_len)
#根据字数调整绘制的位置
if string_len<=2:
draw.text((stx2+int(0.25*bottle_w), sty2+int(1.2*bottle_h)), bottle_list[r][c], font = font, fill = (0,0,0))
elif string_len==3:
draw.text((stx2+int(0.14*bottle_w), sty2+int(1.2*bottle_h)), bottle_list[r][c], font = font, fill = (0,0,0))
elif string_len==4:
draw.text((stx2+int(0.03*bottle_w), sty2+int(1.2*bottle_h)), bottle_list[r][c], font = font, fill = (0,0,0))
else:
draw.text((stx2+int(-0.10*bottle_w), sty2+int(1.2*bottle_h)), bottle_list[r][c], font = font, fill = (0,0,0))
完整代码
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
import json
with open('bottle.json', 'r', encoding='utf-8') as fp:
bottle_configure = json.load(fp)
title=bottle_configure['title']
bottle_list=bottle_configure['list']
fontpath=bottle_configure['fontpath']
font_size=bottle_configure['font_size']
bottle_path=bottle_configure['bottle_path']
font = ImageFont.truetype(fontpath, font_size)
font_title=ImageFont.truetype(fontpath, int(font_size*2.5))
bottle=cv2.imread(bottle_path)
#滤波
# bottle2 = .....(bottle)
bottle2=bottle
# 瓶子左右间距、上下间距、行数、列数
span_w = 0.4
span_h = 0.8
row=len(bottle_list)
col=0
#计算最大列
for l in bottle_list:
if len(l)>col:
col=len(l)
print(col)
(bottle_h, bottle_w, _) = bottle2.shape
background = np.ones((int((row+row*span_h-span_h+2+1)*bottle_h),
int(((col+1)*span_w+col)*bottle_w),
3), dtype="uint8")*250
# 起始点
stx = span_w * bottle_w
sty = bottle_h*2
#背景色一致
Background_color=np.mean(bottle2[0:3,0:3,0:3])
(background_h,background_w,_)=background.shape
for i in range(0,background_h-1):
for j in range(0,background_w-1):
background[i,j]=Background_color
# 绘制小瓶子
for r in range(row):
for c in range(min(col,len(bottle_list[r]))):
stx2 = int(stx + (1+span_w)*bottle_w*c)
sty2 = int(sty + (1+span_h)*bottle_h*r)
# print(stx2, sty2)
for i in range(0, bottle_h-1):
for j in range(0, bottle_w-1):
background[sty2+i, stx2+j] = bottle2[i, j]
#绘制文字
img_pil = Image.fromarray(background)
draw = ImageDraw.Draw(img_pil)
##标题
draw.text((int(0.32*background_w), int(0.5*bottle_h)), title, font = font_title, fill = (0,0,0))
##标签
for r in range(row):
for c in range(min(col,len(bottle_list[r]))):
stx2 = int(stx + (1+span_w)*bottle_w*c)
sty2 = int(sty + (1+span_h)*bottle_h*r)
# background = cv.putText(background, bottle_list[num], (stx2+int(0.1*bottle_w), sty2+int(1.3*bottle_h)), cv.FONT_HERSHEY_COMPLEX, 0.8, (0,0,0), 2)
string=bottle_list[r][c]
string_len=len(string)
print(string,string_len)
if string_len<=2:
draw.text((stx2+int(0.25*bottle_w), sty2+int(1.2*bottle_h)), bottle_list[r][c], font = font, fill = (0,0,0))
elif string_len==3:
draw.text((stx2+int(0.14*bottle_w), sty2+int(1.2*bottle_h)), bottle_list[r][c], font = font, fill = (0,0,0))
elif string_len==4:
draw.text((stx2+int(0.03*bottle_w), sty2+int(1.2*bottle_h)), bottle_list[r][c], font = font, fill = (0,0,0))
else:
draw.text((stx2+int(-0.10*bottle_w), sty2+int(1.2*bottle_h)), bottle_list[r][c], font = font, fill = (0,0,0))
bk_img = np.array(img_pil)
cv2.imwrite('./bottle2.jpg',bk_img)
cv2.waitKey(0)
代码有疑问的地方可以私信/留言,收到后我会补充。 如果支持的人多,会更新下一版本,让标签文字大小和文字位置自动化、智能化 以及 添加多个瓶子 样式 支持。
谢谢各位。