很久以前我就种草了一个钩针作品:钩地球。
小红书上有个比较好的图解:【🌎钩针地球摆件玩偶(附图解) - 董阿萌】
成品图比较好看的有
成品图来源: 手心地球🌍饰品/摆件【附图解】
工程量真不小,我一直没有开工。但是我一直在想,如果地球可以钩,是不是八(九)大行星都可以钩呢?
于是稍微研究了一下,大概的成品如下:
准备工作
现有图(文字)解解构
原有的文字解如下:
来源水印已保留,具体还是来自于【🌎钩针地球摆件玩偶(附图解) - 董阿萌】
因为个人钩织的习惯问题,这个看了头还是很痛。我比较喜欢图解,而且在加针/减针的时候换色真的太折磨了,所以用Excel弄了个图解如下,加了个特别丑的水印,可点击放大,连接在一起的色块代表减针:
整理后得知,这个图解大概是这样的:
- 整个球纵向分为上中下3个部分
- 上面部分8行,进行了加针的操作,加针规律是第一行6短针,后面每行加1针
- 中间部分10行,不加不减
- 下面的部分8行,进行了减针的操作,减针规律是除了第4行,每行减1针
- 整个球横向平均分为6个部分,每部分最宽8针,最窄1针
(这样打出来就有一种傻乎乎的感觉)
素材图片准备
大多数的图片我都是从 Views of the Solar System这个网站上下载的
关于地球的图片我还参考了Planetary maps这个网站,不过最后还是没有使用
原来考虑直接从NASA上下载,结果反而太麻烦了
图片纵横比都是1:2,毕竟是墨卡托投影嘛。大多数大小是1440*720,天王星和海王星是720*360,也没什么大问题
代码逻辑思考
其实代码的最终需求是,把原图缩略成只有4个颜色的图并马赛克化,在两极的位置进行一下图片的缩放
所以本质上还是比较清晰的。大概就是这些模块:
- 把原图拆分为26*48的方格
- 上面8行和下面8行要根据加针和减针的规律,把每行的色块分成不同的部分
- 中间的10行每一格独立成一个部分
- 把各个部分的颜色全部混杂成一个颜色,用这个唯一的颜色填充这个部分
- 然后把整个图片颜色调整为整个图片只有4个颜色
- 输出需要的颜色,绘制图解
为了便于理解,我还画了这个测试图片,5个颜色,横向12个色块,纵向13个色块:
调整之后会变成这样的效果:
可以看到因为混色效果,黄色变得更绿,整个图片变得暗沉沉的
所以在后面的代码里面,我还调整了一下亮度和对比度让颜色能更接近原图
随手填了2个数值,大概是这样的效果,不过我觉得这个也只是在视觉上让自己好受一点,具体生成图解之后,还会受到毛线色号的制约
PIL函数准备
在这个“面向AI编程”的时代,写代码真的是越来越简单了。我在Copilet里面输入“我想用python把一张图片马赛克化,并且只用4个颜色,代码怎么写?”Copilet就噼噼啪啪回复一堆乱七八糟但是挺好用的代码
不过我还是整理了一下,主要用到的函数:
from PIL import Image, ImageDraw, ImageEnhance, ImageFont
-
Image.open(fp, mode=’r’)
打开图片
-
Image.save(fp, format=None, **params)
保存图片
-
Image.convert(mode=None, matrix=None, dither=None, palette=0, colors=256)
图像格式转换,主要用来缩色
-
Image.resize(size, resample=0)
调整图像(图块)大小
-
Image.crop((x1, y1, x2, y2))
截取图块
-
Image.getpixel(self, xy)
获取图像的像素点,主要是后面用来取色
-
obj = ImageEnhance.Brightness(image)
obj.enhance(factor)
调整图像的亮度
-
obj = ImageEnhance.Contrast(image)
obj.enhance(factor)
调整图像的对比度
-
ImageDraw.Draw(img)
准备在图像上乱涂乱画(bushi
-
ImageDraw.Draw.rectangle(xy, fill=None, outline=None)
在图像上绘制实心矩形或者矩形框
-
ImageDraw.Draw.text(xy, text, fill=None, font=None, anchor=None, spacing=0, align=’left’)
在图像上写字
代码
原图解构
from PIL import Image, ImageDraw, ImageEnhance, ImageFont
import math
import sys
input_image_path = "00-color.png" # 输入素材图路径
num_colors = 4 # 锁色为4色
brightness_e = 1.7 # 亮度调整
contrast_e = 1.7 # 对比度调整
outline = True # 是否画出外框
image = Image.open(input_image_path)
image = image.convert("RGB")
width, height = image.size
# 计算纵向切片高度
double_piece_height = height/(8 + 10 + 8)
拉伸绘图
# 把指定色块给压缩成1*1实现混色效果,然后用这个颜色填满这个色块
def fill_color(image, x1, y1, x2, y2):
crop_image = image.crop((x1, y1, x2, y2))
img_small = crop_image.resize((1, 1), Image.LANCZOS)
img_rgb = img_small.convert("RGB")
r, g, b = img_rgb.getpixel((0, 0))
draw = ImageDraw.Draw(image)
draw.rectangle([(x1, y1), (x2, y2)], fill=(r, g, b))
return image
# 上 8行 48 列
# 加针 1 2 3 4 5 6 7 8
for y in range(8):
# 计算当前切片宽度
double_piece_width = width / 6 / (y + 1.0)
for x in range(6 * (y + 1)):
image = fill_color(image,
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * y),
math.ceil(double_piece_width * (x + 1)),
math.ceil(double_piece_height * (y + 1))
)
# 中 10行 48 列
for y in range(10):
double_piece_width = width / 48.0
for x in range(48):
image = fill_color(image,
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * (y + 8)),
math.ceil(double_piece_width * (x + 1)),
math.ceil(double_piece_height * (y + 9))
)
# 下 8行 6*48列
# 减针 7 6 5 5 4 3 2 1
for y in range(8):
# 第四行不减针的特殊操作
real_y = y
if y < 3:
real_y += 1
double_piece_width = width / 6 / (8.0 - real_y)
for x in range(6 * (8 - real_y)):
image = fill_color(image,
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * (y + 18)),
math.ceil(double_piece_width * (x + 1)),
math.ceil(double_piece_height * (y + 19))
)
缩色
image = image.convert("P", palette=Image.ADAPTIVE, colors=num_colors)
image = image.convert("RGB")
调整亮度和对比度
brightness_enhancer = ImageEnhance.Brightness(image)
image = brightness_enhancer.enhance(brightness_e)
contrast_enhancer = ImageEnhance.Contrast(image)
image = contrast_enhancer.enhance(contrast_e)
取色获取文字解
color_array = []
color_line = []
# 上 8行 48 列
for y in range(8):
color_line = []
double_piece_width = width / 6 / (y + 1.0)
for x in range(6 * (y + 1)):
r, g, b = image.getpixel((
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * y))
)
color_line.append((r, g, b))
color_array.append(color_line)
# 中 10行 48 列
for y in range(10):
color_line = []
double_piece_width = width / 48.0
for x in range(48):
r, g, b = image.getpixel((
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * (y + 8)))
)
color_line.append((r, g, b))
color_array.append(color_line)
# 下 8行 6*48列
for y in range(8):
color_line = []
double_piece_width = width / 6 / (8.0 - y)
for x in range(6 * (8 - y)):
r, g, b = image.getpixel((
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * (y + 18)))
)
color_line.append((r, g, b))
color_array.append(color_line)
for i in range(len(color_array)):
print("[R%s] " % (i+1), end='')
color_line = color_array[i]
for color in color_line:
r, g, b = color
print('#{:02x}{:02x}{:02x}, '.format(r, g, b), end='')
print()
这时候获取的文字解是这样的格式,显然对人类非常不友好
[R1] #ff0801, #00ffff, #ff0801, #ffff00, #2d67ff, #ff0801,
[R2] #ff0801, #ffff00, #ffff00, #00ffff, #2d67ff, #ff0801, #ffff00, #ffff00, #00ffff, #2d67ff, #ff0801, #ffff00,
[R3] #2d67ff, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #00ffff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ffff00, #ffff00, #00ffff, #00ffff, #2d67ff, #ff0801, #ff0801,
[R4] #2d67ff, #2d67ff, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #2d67ff, #2d67ff, #ff0801, #ff0801,
[R5] #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff,
[R6] #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff,
[R7] #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff,
[R8] #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff,
[R9] #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00,
[R10] #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00,
[R11] #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00,
[R12] #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00,
[R13] #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801,
[R14] #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801,
[R15] #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff,
[R16] #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff,
[R17] #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff,
[R18] #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff,
[R19] #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00,
[R20] #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00,
[R21] #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00,
[R22] #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #00ffff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #2d67ff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ff0801, #ffff00, #ffff00,
[R23] #2d67ff, #2d67ff, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #ffff00, #00ffff, #00ffff, #2d67ff, #2d67ff, #ff0801, #ff0801,
[R24] #2d67ff, #ff0801, #ff0801, #ffff00, #ffff00, #ffff00, #00ffff, #2d67ff, #2d67ff, #ff0801, #ff0801, #ffff00, #ffff00, #00ffff, #00ffff, #2d67ff, #ff0801, #ff0801,
[R25] #00ffff, #2d67ff, #ff0801, #ffff00, #ffff00, #00ffff, #2d67ff, #ff0801, #ffff00, #ffff00, #00ffff, #2d67ff,
[R26] #2d67ff, #ff0801, #00ffff, #ff0801, #ffff00, #2d67ff,
[Finished in 1.1s]
不管怎么说,我是想要上面那个Excel差不多格式的图解对吧
调试用外框绘制
如果不绘制外框,这里一个中间产物就会是在下面这样的效果
感觉对人类不太友好,所以我画了点框
如果这里用行星的图片,会有一种莫名的教堂花窗玻璃的感觉
好像还挺好看
def fill_outline(image, x1, y1, x2, y2):
draw = ImageDraw.Draw(image)
draw.rectangle([(x1, y1), (x2, y2)], fill=None, outline="black", width=2)
return image
if outline:
# 上 8行 48 列
for y in range(8):
double_piece_width = width / 6 / (y + 1.0)
for x in range(6 * (y + 1)):
image = fill_outline(image,
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * y),
math.ceil(double_piece_width * (x + 1)),
math.ceil(double_piece_height * (y + 1))
)
# 中 10行 48 列
for y in range(10):
double_piece_width = width / 48.0
for x in range(48):
image = fill_outline(image,
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * (y + 8)),
math.ceil(double_piece_width * (x + 1)),
math.ceil(double_piece_height * (y + 9))
)
# 下 8行 6*48列
for y in range(8):
# 减针特殊算法
real_y = y
if y < 3:
real_y += 1
double_piece_width = width / 6 / (8.0 - real_y)
for x in range(6 * (8 - real_y)):
image = fill_outline(image,
math.ceil(double_piece_width * x),
math.ceil(double_piece_height * (y + 18)),
math.ceil(double_piece_width * (x + 1)),
math.ceil(double_piece_height * (y + 19))
)
image.save("filled_"+input_image_path)
设置图解长度和宽度
text_width = 50
offset = 30
max_length = 0
color_block_width = 30
font_size = 20
font = ImageFont.truetype("arial.ttf", font_size)
# 计算最大换色次数
for color_line in color_array:
color_count = 0
color_point = None
for color in color_line:
if color_point == color:
pass
else:
color_point = color
color_count +=1
if color_count > max_length:
max_length = color_count
image_diagram = Image.new(mode="RGB",
size=(offset + color_block_width * 48 + offset + text_width + text_width * max_length + offset,
offset + color_block_width * 26 + offset),
color="white")
draw_diagram = ImageDraw.Draw(image_diagram)
绘制图解
pattern_table = [
"X ",
"XX ",
"XX X ",
"XXX X ",
"XXX XX ",
"XXXX XX ",
"XXXX XXX",
"XXXXXXXX",
"X"*8,
"X"*8,
"X"*8,
"X"*8,
"X"*8,
"X"*8,
"X"*8,
"X"*8,
"X"*8,
"X"*8,
"XXXA XXX",
"XXXX XA ",
"XXA XX ",
"XXX XX ",
"XXX A ",
"XA X ",
"XA ",
"A "
]
for y in range(0, len(pattern_table)):
flag = 0
color_index = 0
for x in range(0, len(pattern_table[y]*6)):
if not pattern_table[y][x % 8].isspace():
w = 1
# 减针2倍宽,反正右边没东西了
if pattern_table[y][x % 8] == "A":
w = 2
draw_diagram.rectangle(
[(x * color_block_width + offset, y * color_block_width + offset),
((x + w) * color_block_width + offset, (y + 1) * color_block_width + offset)],
fill=color_array[y][flag], outline="black", width=1)
flag += 1
color_count = 0
color_point = None
index = 1
# 画文字解
# 行号
draw_diagram.rectangle([
(offset + (x + 1) * color_block_width + offset + text_width * color_index,
y * color_block_width + offset),
(offset + (x + 1) * color_block_width + offset + text_width * (color_index + 1),
y * color_block_width + offset + offset)
],
fill=None,
outline="black",
width=1)
draw_diagram.text(
xy=(offset + (x + 1) * color_block_width + offset + text_width * color_index + font_size/4,
y * color_block_width + offset + font_size/4),
text = 'R'+str(y+1),
fill = "black",
font = font)
# 文字和框
for i in range(0, len(color_array[y])):
color = color_array[y][i]
if color_point:
if color == color_point:
color_count += 1
else:
draw_diagram.rectangle(
[
(offset + (x + 1) * color_block_width + offset + text_width * (color_index + 1),
y * color_block_width + offset),
(offset + (x + 1) * color_block_width + offset + text_width * (color_index + 2),
y * color_block_width + offset + color_block_width)
],
fill=None,
outline="black",
width=1)
draw_diagram.text(
xy=(offset + (x + 1) * color_block_width + offset + text_width * (color_index + 1) + font_size/4,
y * color_block_width + offset + font_size/4),
text=str(color_count)+'X',
fill=color,
font=font
)
color_point = color
color_count = 1
color_index += 1
else:
color_point = color
color_count += 1
draw_diagram.rectangle(
[
(offset + (x + 1) * color_block_width + offset + text_width * (color_index + 1),
y * color_block_width + offset),
(offset + (x + 1) * color_block_width + offset + text_width * (color_index + 2),
y * color_block_width + offset + color_block_width)
],
fill=None,
outline="black",
width=1)
draw_diagram.text(
xy=(offset + (x + 1) * color_block_width + offset + text_width * (color_index + 1) + font_size/4,
y * color_block_width + offset + font_size/4),
text=str(color_count)+'X',
fill=color,
font=font
)
image_diagram.save("diagram_" + input_image_path)
图解成品
我根据自己的喜好调整了一下亮度和对比度
至于水印已经懒得上了,因为正常人看了这个图解也钩不出来,颜色太接近了,肉眼太难看清楚了,必须要和文字版配合才行
如果有感兴趣的人可以自己用代码跑了试试结果
五色色块图(用来调试)
亮度=1.7
对比度=1.7
太阳
亮度=1.3
对比度=1.3
月球
亮度=1.1
对比度=1.3
水星
亮度=1
对比度=1
金星
亮度=1
对比度=1
地球(无冰盖)
亮度=0.7
对比度=3
火星
亮度=0.9
对比度=1.5
土星
亮度=1
对比度=1
木星
亮度=1.3
对比度=1
天王星
亮度=1
对比度=1
海王星
亮度=0.9
对比度=1.1
图解生成好了,我几乎完全没有钩出来的欲望了。哦天王星和海王星好像挺简单的,说不定哪天可以动手试一试……