龙空技术网

惊爆!Python打造花式照片墙!

博学多才的叶慢慢 75

前言:

而今小伙伴们对“用python做一张图片”大体比较关切,兄弟们都需要知道一些“用python做一张图片”的相关知识。那么小编也在网络上收集了一些有关“用python做一张图片””的相关知识,希望小伙伴们能喜欢,朋友们一起来学习一下吧!

前段时间在看照片墙,感觉用照片拼成各种形状还是蛮有意思的,将所有故事浓缩在一张图上。

于是做了2个张含韵的照片墙视频。照片墙1:女神做照片墙背景,可以将自己的背影放上去

照片墙2:照片翻页,欣赏女神的无敌美颜

最终照片墙的效果还可以,但是用手动方式制作还是有些费时费力的。最近,看到python制作文字照片墙的简便方法,我们选3张图片:

让玫瑰花组成照片墙,代码运行效果图如下:

有点小惊艳呀,怎么这么好看,放到视频中做素材:

多选几张图片效果又如何呢,30张刘亦菲的靓照组成照片墙:

整体色调不如3张照片的玫瑰花那么统一了,单张照片都好看,拼一起怎么乱糟糟呢?

虽然如此,

但是玫瑰花开,美女成群,还是蛮有氛围的。

经过我的简单尝试,可以粗谈一下制作照片墙的两种方式了。

用Excel制作照片墙模板

这种方式来做简单的字符还好,如果制作汉字有些费事。

首先需要填充颜色,在Excel中画出需要的文字,再填充0,1数字,最后再制作数字矩阵二维数组。出问题时,需要反复地修改模板。总之,这一部分很耗时。

有没有不需要手动制作汉字模板,自动生成照片墙的方法呢?答案是通过点阵字的方式来实现汉字照片墙。

点阵字照片墙制作

点阵字是汉字在计算机中的存储形式,效果就如像素图。HZK16字库是符合GB2312标准的1616点阵字库,每个汉字模型需要1616共256个像素点来显示。效果如下图所示:

照片墙制作

1.生成点阵字照片墙模板——一个二维数组,需要调用字库文件,本次运用了HZK16的字库文件。

2.用照片替换模板中的的符号,形成照片墙。

第一部分代码:生成点阵字照片墙模板

import binasciiimport osfrom PIL import Imageimport randomimport numpy as npKEYS = [0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01]'''获取多个汉字点阵字'''def get_multiple_word_img(textStr):    # 初始化16*16的点阵位置,每个汉字需要16*16=256个点来表示,需要32个字节才能显示一个汉字    # 之所以32字节:256个点每个点是0或1,那么总共就是2的256次方,一个字节是2的8次方    rect_list = [] * 16    for i in range(16):        rect_list.append([] * 16)    for text in textStr:        #获取中文的gb2312编码,一个汉字是由2个字节编码组成        gb2312 = text.encode('gb2312')        #将二进制编码数据转化为十六进制数据        hex_str = binascii.b2a_hex(gb2312)        #将数据按unicode转化为字符串        result = str(hex_str, encoding='utf-8')        #前两位对应汉字的第一个字节:区码,每一区记录94个字符        area = eval('0x' + result[:2]) - 0xA0        #后两位对应汉字的第二个字节:位码,是汉字在其区的位置        index = eval('0x' + result[2:]) - 0xA0        #汉字在HZK16中的绝对偏移位置,最后乘32是因为字库中的每个汉字字模都需要32字节        offset = (94 * (area-1) + (index-1)) * 32        font_rect = None        #读取HZK16汉字库文件        with open(r"D:\360极速浏览器下载\字库\16x16\hzk16H", "rb") as f:            #找到目标汉字的偏移位置            f.seek(offset)            #从该字模数据中读取32字节数据            font_rect = f.read(32)        #font_rect的长度是32,此处相当于for k in range(16)        for k in range(len(font_rect) // 2):            #每行数据            row_list = rect_list[k]            for j in range(2):                for i in range(8):                    asc = font_rect[k * 2 + j]                    #此处&为Python中的按位与运算符                    flag = asc & KEYS[i]                    #数据规则获取字模中数据添加到16行每行中16个位置处每个位置                    row_list.append(flag)    #根据获取到的16*16点阵信息,打印到控制台    for row in rect_list:        for i in row:            if i:                print('o', end=' ')            else:                print('.', end=' ')        print()    print('{}'.format(rect_list))    #返回值为点阵二维列表    return rect_listget_multiple_word_img('爱')
输出的数字矩阵二维数组如下:[[0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 32, 16, 8, 0, 0, 0], [0, 64, 32, 16, 8, 4, 2, 1, 128, 64, 32, 16, 8, 0, 0,0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

需要注意的是:1.其中的数字128、64、32、16、8、4、2需要替换成1

2.再把1替换成5(或其它不是0和1的数字)

3.然后把0替换成1,目的是去掉背景,只显示汉字 4.最后把第二步的5替换成0 这样一番操作后,输出的二维数组就可以给第二部分代码用了。

第二部分代码:用照片替换模板中的指定字符,形成照片墙

此部分代码就是循环第一部分代码输出的二维数组列表, 用变量HEART_FRAME等于它。

注意:要提前从网上下载HZK16文件(资源不好找,我上传了) ,并在代码中修改文件对应的路径。

from PIL import Imageimport os'''根据指定的frame_name 获取photo_wall_FRAME# 定义绘制图形的框架,1表示不填充,0表示用头像填充'''def get_photo_wall_FRAME(frame_name):    FRAME_DIC = {}    #Heart frame 21*17,Heart形状共128个0    HEART_FRAME=[[1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1]]    FRAME_DIC["HEART_FRAME"]=HEART_FRAME    # FRAME_DIC["LOVE_FRAME"]=LOVE_FRAME    return FRAME_DIC[frame_name]'''生成照片墙'''def generate_photo_wall(FRAME,img_path,photo_folder_name):    #导入图片    #需要拼接的照片文件夹完整路径    photo_folder = r'{}\{}'.format(img_path,photo_folder_name)    #将以.jpg的图片放置于新键的列表中,为后续生成照片墙使用,目的是过滤掉非图片格式的文件    pic_list = [] #存放图片位置    for i in os.listdir(photo_folder):        print(i)        if i.endswith('.jpg') or i.endswith('.png') or i.endswith('.webp'):            pic_list.append(i)    total_photo =len(pic_list)    print("文件夹中共有{}张照片".format(total_photo))    print('正在创建照片墙...')    # 设置图片的尺寸,所有图片尺寸要保持统一    img_h = img_w = 192    # 计算行数,即子列表的个数    rows = len(FRAME)    # 计算列数,即子列表中元素的个数    columns = len(FRAME[0])    #画图    #使用Image.new()方法创建一个画布,一个白色图片    # 第一个参数RGB    # 第二个参数需要传入一个元组,元组的第一个参数是画布的宽,第二个是高    # 第三个参数传入的是画布的颜色    figure = Image.new("RGB", (img_w*columns, img_h*rows),"white")    #将图片放在画布对应的位置,即数组中元素为0的位置    # 表示图片的下标    count = 0    # 遍历行    for i in range(len(FRAME)):        # 遍历每行中的所有元素        for j in range(len(FRAME[i])):            # 如果元素是1,就不管它            if FRAME[i][j] == 1:                continue            # 如果元素是非1,即0就放图片上去            else:                # 做个异常处理,防止有些图片打开失败,导致程序中断                try:                    #当照片数量不够时,循环使用已用过的照片,added by yimi on 20220521                    if count == total_photo:                        count = 0                    # 使用Image.open("图片路径")方法获取图片对象                    image = Image.open(os.path.join(photo_folder, pic_list[count]))                except:                    continue                # resize((新的宽,新的高))用来改变图片的尺寸,接收一个元组                image = image.resize((img_w, img_h))                # 将修改尺寸后的图片(image)粘贴(paste)到画布(figure)上                # 第一个参数 是图片对象                # 第二个参数是 图片在画布上的位置,相当于单元格的位置                figure.paste(image, (img_w*j, img_h*i))                # 使用完一张图片就要记录下来,并开始使用下一张图片                count += 1    # 当循环结束,即表示照片墙图片已经完成    # 将画好的画布显示出来    figure.show()    # 需要告知程序图片保存的路径    figure.save(r'{}\{}_photo_wall1.png'.format(img_path,photo_folder_name),format="png")    print('照片墙创建成功!')#程序入口if __name__=='__main__':    #图片存放的路径(当前项目是所有图片统一放在了程序所在的文件夹路径下方了,运用代码时可以改成自己照片存放的路径即可。)    img_path =r'Photo\img'    #存放很多张照片集合的文件夹名称,将路径和文件夹名称分开保存在变量中是为了后续生成照片墙照片要用文件夹的名称    photo_folder_name = 'baby'    #照片墙框架类型:"LOVE_FRAME","HEART_FRAME"    frame_name = "HEART_FRAME"    #获取指定的照片墙框架    FRAME = get_photo_wall_FRAME(frame_name)    #生成照片墙    generate_photo_wall(FRAME,'C:/drf2/drf2/图片',photo_folder_name)

标签: #用python做一张图片 #python图片素材 #1616点阵算法 #16乘16点阵代码在线生成器