最新版本,点这里
之前一时兴起,写了个生成心形贴图的程序【链接在这里】 但是只是把功能实现了,有很多鸡肋还有逻辑之类混乱的,于是又重新整理了一下。
需要用到的库
import os
import os. path as op
import numpy as np
from PIL import Image
from tkinter import Tk
from tkinter. filedialog import asksaveasfilename, askopenfilename, askdirectory
说明 获取贴图形状(不一定是心形 输入图片路径(图片为严格黑白,获取黑色部分横向像素条数据 获取完整数据(每一行单独黑色像素的纵坐标、起始 获取的数据单个元素[y,x0,x1] ,y并非从一定0开始
def heart_get ( self, source_path) :
img = Image. open ( source_path)
pix = img. load( )
self. s_size = size = img. size
for y in range ( 0 , size[ 1 ] ) :
index = 0
for x in range ( 0 , size[ 0 ] - 1 ) :
if ( pix[ x, y] != pix[ x+ 1 , y] and ( 255 , 255 , 255 ) in [ pix[ x, y] , pix[ x+ 1 , y] ] ) or ( pix[ x, y] != pix[ x+ 1 , y] and ( 255 , 255 , 255 , 255 ) in [ pix[ x, y] , pix[ x+ 1 , y] ] ) :
if index:
self. lst[ - 1 ] . append( x)
index = 0
else :
self. lst. append( [ y, x+ 1 ] )
index = 1
函数
def mkit ( self, leap, imgs_path,
source_path, out= None ,
show= True , per_size= None ,
bg= ( 0 , 0 , 0 ) , ) :
说明 每隔leap行取一行像素贴图 source:心形图地址 out: 字典类型。key有:path(输出路径)、quality(输出图片质量) per_size:每张贴图的尺寸(后续会将源图压缩为该尺寸的方形图) bg:顾名思义,背景(底图)颜色 贴图时图间横、纵间距皆可调整(类方法里) 贴完图是选择是否展示
(xx, yy) 为底图尺寸
lst 为像素条数据列表
top_yblank 为顶部留白
dx, dy 为贴图时横、纵间距
canv = Image. new( 'RGB' , ( int ( xx) , int ( yy) ) , bg)
lst = np. array( lst, dtype= 'int' )
top_yblank = int ( top_yblank)
for line in lst:
if not ( line[ 0 ] - top_yblank) % leap:
column = int ( ( line[ 0 ] - top_yblank) // leap)
print ( f'\rget__ { column+ 1 } / { lst[ - 1 ] [ 0 ] // leap} __!' , end= '' )
for x in range ( line[ 1 ] , line[ 2 ] + 1 , per_size+ self. dx) :
s_img = Image. open ( next ( imgs) ) . resize( ( per_size, per_size) )
canv. paste( s_img, ( x, top_yblank+ column* int ( per_size+ self. dy) ) )
else :
print ( '\rAll Done!' , end= '' )
if out:
canv. save( out[ 'path' ] , quality= out[ 'quality' ] )
print ( '\rSaved it!' )
if show:
canv. show( )
问题 底图大小需要计算(比例应与心形图保持一致) 由于照像素条贴图后像素条“厚度”增加,心形比例失协,所以需要提前将获取到的像素条横向放大,保证比例 由于底图、心心相素条位置并不匹配(心形位置不居中),所以需要将像素条平移使心形居中。 需要从所给路径获取图集(地址),滤除非图片路径后制作迭代器
Ⅰ . 图集迭代器
imgs_list = [
op. join( imgs_path, name) for name in os. listdir( imgs_path)
]
def is_pic ( self, path) :
if path. endswith( ( '.jpg' , '.png' , '.gif' , '.jpeg' ) ) :
return 1
else :
return 0
def img_generator ( self, imgs_list) :
while 1 :
for path in imgs_list:
yield path
imgs_list = list ( filter ( self. is_pic, imgs_list) )
imgs = self. img_generator( imgs_list)
Ⅱ . 底图大小计算(xx, yy)
yy = ( self. y_more + self. lst[ - 1 ] [ 0 ] // leap) * ( per_size+ self. dy)
xx = int ( yy* ( self. s_size[ 0 ] / self. s_size[ 1 ] ) )
Ⅲ. 像素条横向放大系数计算
end_x = sorted ( self. lst, key= lambda x: x[ 2 ] )
x_up_size = xx// end_x[ - 1 ] [ 2 ]
lst = lst* [ 1 , x_up_size, x_up_size]
xx += 2 * per_size
Ⅳ. 平移使居中
像素条全部存于 lst(ndarray对象) 中
dy、dx 分别为纵、横向贴图间距
x_start = sorted ( lst, key= lambda x: x[ 1 ] )
x_end = sorted ( lst, key= lambda x: x[ 2 ] )
max_len = x_end[ - 1 ] [ 2 ] - x_start[ 0 ] [ 1 ]
max_xpic = max_len/ ( per_size+ self. dx) + .6
max_piclen = max_xpic* ( per_size+ self. dx)
all_xblank = xx - max_piclen
left_xblank = all_xblank/ 2
most_left = x_start[ 0 ] [ 1 ]
ddx = most_left - left_xblank
all_yblank = self. y_more* ( per_size+ self. dy) + self. dy
top_yblank = all_yblank/ 2
top_yblank = all_yblank/ 2
lst = lst + [ - lst[ 0 ] [ 0 ] + top_yblank, - ddx, - ddx]
至此已经解决的差不多了
来使用一下
框架
class Heart ( ) :
def __init__ ( self) :
self. lst = [ ]
self. s_size = None
self. pencolor = 'black'
self. out_path = None
self. dx = 20
self. dy = 20
self. y_more = 3
def img_generator ( self, imgs_list) :
def heart_get ( self, source_path) :
def get_outpath ( self) :
self. out_path = asksaveasfilename(
title= '选择图片保存路径' ,
initialdir= r'c:\users\pxo\desktop' ,
filetypes= [ ( 'pic' , '.jpg .png .gif .jpeg' ) , ] ,
defaultextension= '.png'
)
def is_pic ( self, path) :
def mkit ( self, leap, imgs_path, source_path, out= None , show= True , per_size= None , bg= ( 0 , 0 , 0 ) ) :
if not per_size:
per_size = 100
if not out[ 'path' ] :
while not self. out_path:
self. get_outpath( )
out[ 'path' ] = self. out_path
imgs_list = [ op. join( imgs_path, name) for name in os. listdir( imgs_path) ]
imgs_list = list ( filter ( self. is_pic, imgs_list) )
imgs = self. img_generator( imgs_list)
self. heart_get( source_path)
lst = np. array( self. lst)
示例
if __name__ == '__main__' :
root = Tk( )
root. withdraw( )
imgs_path = askdirectory( )
bg = ( 0 , 0 , 0 )
out = {
'path' : None ,
'quality' : 50 ,
}
one_test = Heart( )
oen_test. dx = 20
one_test. dy = 22
one_test. y_more = 3
完整代码-需要直接Copy
不恰当的地方欢迎指教啊,一起学习学习!!
'''
@project:PYTHON
@IDE:PyCharm
@file: heart_s.py
@time: 2020-02-23 10:26
'''
import os
import os. path as op
import turtle as t
import numpy as np
from PIL import Image
from random import *
from tkinter. filedialog import asksaveasfilename, askopenfilename, askdirectory
from tkinter import Tk
class Heart ( ) :
def __init__ ( self) :
self. lst = [ ]
self. s_size = None
self. out_path = None
self. dx = 20
self. dy = 20
self. y_more = 3
def img_generator ( self, imgs_list) :
while 1 :
for path in imgs_list:
yield path
def heart_get ( self, source_path) :
img = Image. open ( source_path)
pix = img. load( )
self. s_size = size = img. size
for y in range ( 0 , size[ 1 ] ) :
index = 0
for x in range ( 0 , size[ 0 ] - 1 ) :
if ( pix[ x, y] != pix[ x+ 1 , y] and ( 255 , 255 , 255 ) in [ pix[ x, y] , pix[ x+ 1 , y] ] ) or ( pix[ x, y] != pix[ x+ 1 , y] and ( 255 , 255 , 255 , 255 ) in [ pix[ x, y] , pix[ x+ 1 , y] ] ) :
if index:
self. lst[ - 1 ] . append( x)
index = 0
else :
self. lst. append( [ y, x+ 1 ] )
index = 1
if get_it:
ts = t. getscreen( )
file_out = ''
while not len ( file_out) :
file_out = asksaveasfilename(
title= '选择图片保存路径' ,
filetypes= [ ( 'Pic' , '.eps' ) ] ,
defaultextension= '.eps' ,
initialdir= r'c:\users\pxo\desktop'
)
ts. getcanvas( ) . postscript( file = file_out)
t. mainloop( )
def get_outpath ( self) :
self. out_path = asksaveasfilename(
title= '选择图片保存路径' ,
initialdir= r'c:\users\pxo\desktop' ,
filetypes= [ ( 'pic' , '.jpg .png .gif .jpeg' ) , ] ,
defaultextension= '.png'
)
def is_pic ( self, path) :
if path. endswith( ( '.jpg' , '.png' , '.gif' , '.jpeg' ) ) :
return 1
else :
return 0
def mkit ( self, leap, imgs_path, source_path, out= None , show= True , per_size= None , bg= ( 0 , 0 , 0 ) ) :
if not per_size:
per_size = 100
if not out[ 'path' ] :
while not self. out_path:
self. get_outpath( )
out[ 'path' ] = self. out_path
imgs_list = [ op. join( imgs_path, name) for name in os. listdir( imgs_path) ]
imgs_list = list ( filter ( self. is_pic, imgs_list) )
imgs = self. img_generator( imgs_list)
self. heart_get( source_path)
lst = np. array( self. lst)
if per_size >= min ( self. s_size) :
per_size = 100
yy = ( self. y_more + self. lst[ - 1 ] [ 0 ] // leap) * ( per_size+ self. dy)
xx = int ( yy* ( self. s_size[ 0 ] / self. s_size[ 1 ] ) )
end_x = sorted ( self. lst, key= lambda x: x[ 2 ] )
x_up_size = xx// end_x[ - 1 ] [ 2 ]
lst = lst* [ 1 , x_up_size, x_up_size]
xx += 2 * per_size
x_start = sorted ( lst, key= lambda x: x[ 1 ] )
x_end = sorted ( lst, key= lambda x: x[ 2 ] )
max_len = x_end[ - 1 ] [ 2 ] - x_start[ 0 ] [ 1 ]
max_xpic = max_len/ ( per_size+ self. dx) + .6
max_piclen = max_xpic* ( per_size+ self. dx)
all_xblank = xx - max_piclen
left_xblank = all_xblank/ 2
most_left = x_start[ 0 ] [ 1 ]
ddx = most_left - left_xblank
all_yblank = self. y_more* ( per_size+ self. dy) + self. dy
top_yblank = all_yblank/ 2
lst = lst + [ - lst[ 0 ] [ 0 ] + top_yblank, - ddx, - ddx]
canv = Image. new( 'RGB' , ( int ( xx) , int ( yy) ) , bg)
lst = np. array( lst, dtype= 'int' )
top_yblank = int ( top_yblank)
''' 调试段
x_start = sorted(lst, key=lambda x: x[1])
y_start = sorted(lst, key=lambda x: x[0])
print(f'最左起始坐标{x_start[0][1]}, 最顶起始坐标{y_start[0][0]}', f'{top_yblank=}')
'''
for line in lst:
if not ( line[ 0 ] - top_yblank) % leap:
column = int ( ( line[ 0 ] - top_yblank) // leap)
print ( f'\rget__ { column+ 1 } / { lst[ - 1 ] [ 0 ] // leap} __!' , end= '' )
for x in range ( line[ 1 ] , line[ 2 ] + 1 , per_size+ self. dx) :
s_img = Image. open ( next ( imgs) ) . resize( ( per_size, per_size) )
canv. paste( s_img, ( x, top_yblank+ column* int ( per_size+ self. dy) ) )
else :
print ( '\rAll Done!' , end= '' )
if out:
canv. save( out[ 'path' ] , quality= out[ 'quality' ] )
print ( '\rSaved it!' )
if show:
canv. show( )
if __name__ == '__main__' :
root = Tk( )
root. withdraw( )
imgs_path = askdirectory( title= '请选择图片文件夹路径' )
bg = ( 0 , 0 , 0 )
out = {
'path' : None ,
'quality' : 50 ,
}
one_test = Heart( )
oen_test. dx = 20
one_test. dy = 22
one_test. y_more = 3
one. mkit( leap= 20 , imgs_path= imgs_path, source_path= 'heart.png' , bg= bg, show= True , out= out, per_size= 100 )