问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

Python如何将多图片拼

发布网友 发布时间:2022-04-28 04:33

我来回答

2个回答

懂视网 时间:2022-04-28 08:54

【相关学习推荐:python教程】

文章目录

  • 前言
  • Github
  • 效果
  • 实现过程
  • 整体代码
  • 前言

    看电影的时候发现一个照片墙的功能,觉得这样生成照片挺好玩的,于是就动手用Python做了一下,觉得用来作照片纪念的效果可能会不错。

    P:后面了解到我想做的功能叫蒙太奇拼图,所以这篇博客记录先留着,闲下来会去看一下蒙太奇拼图的算法

    Github

    https://github.com/jiandi1027/photo.git

    效果

    在这里插入图片描述
    在这里插入图片描述

    实现过程

    1.获取图片文件夹的图片个数N,将底图拆分成XY块区域,且使X * Y<N
    (为了保证整体的协调,会舍弃几张图片,比如5张时可能只取2
    2的4张图片)

    	# 打开图片 
    	base = Image.open(baseImgPath)
     base = base.convert('RGBA')
     # 获取图片文件夹图片并打乱顺序
     files = glob.glob(imagesPath + '/*.*') 
     random.shuffle(files)
     # 图片数量
     num = len(files)
    	# 底图大小
     x = base.size[0]
     y = base.size[1]
     # 每张图片数量 这个公式是为了xNum * yNum 的总图片数量<num又成比例的最大整数
     yNum = int((num / (y / x)) ** 0.5)
     if yNum == 0:
     yNum = 1
     xNum = int(num / yNum)
     # 图片大小 因为像素没有小数点 为防止黑边所以+1
     xSize = int(x / xNum) + 1
     ySize = int(y / yNum) + 1

    在这里插入图片描述

    2.遍历文件夹的图片,依次填充生成最终合成图

    for file in files:
     fromImage = Image.open(file)
     i = int(num % xNum)
     j = int(num / xNum)
     out = fromImage.resize((xSize, ySize), Image.ANTIALIAS).convert('RGBA')
     toImage.paste(out, (i * xSize, j * ySize))
     toImage = toImage.convert('RGBA')
     img = Image.blend(base, toImage, 0.3)
     # 显示图片
     photo = ImageTk.PhotoImage(img)
     showLabel.config(image=photo)
     showLabel.image = photo
     if num < xNum * yNum:
      num = num + 1

    3.生成结束后保存图片
    toImage.save(‘generator.png’)
    img.save(“final.png”)
    在这里插入图片描述
    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190805150649966.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoaWppYW5kaQ==,size_16,color_FFFFFF,t_70
    4.建立可视化界面
    在这里插入图片描述
    5.Pyinstaller生成exe可执行文件
    安装pyinstaller模块,执行命令生成exe文件

    pyinstaller -F -w test.py (-w就是取消窗口)

    整体代码

    Python的语法和设计规范还没学过,所以代码规范代码复用之类的可能会有点不到位,本博文主要是一个思路与整体流程的记录。
    后续又优化了一下一些特效,比如合成图片采用随机位置,增加黑白,流年等显示特效,透明度自选等。

    import PIL.Image as Image
    import glob
    import random
    import tkinter.filedialog
    from tkinter.filedialog import askdirectory, Label, Button, Radiobutton, Entry
    import threading
    
    import numpy as np
    from PIL import ImageTk
    
    alpha = 0.3
    imagesPath = ''
    
    
    # 滑动条回调 修改透明度
    def resize(ev=None):
     global alpha
     alpha = scale.get() / 100
    
    
    # 黑白
    def blackWithe(image):
     # r,g,b = r*0.299+g*0.587+b*0.114
     im = np.asarray(image.convert('RGB'))
     trans = np.array([[0.299, 0.587, 0.114], [0.299, 0.587, 0.114], [0.299, 0.587, 0.114]]).transpose()
     im = np.dot(im, trans)
     return Image.fromarray(np.array(im).astype('uint8'))
    
    
    # 流年
    def fleeting(image, params=12):
     im = np.asarray(image.convert('RGB'))
     im1 = np.sqrt(im * [1.0, 0.0, 0.0]) * params
     im2 = im * [0.0, 1.0, 1.0]
     im = im1 + im2
     return Image.fromarray(np.array(im).astype('uint8'))
    
    
    # 旧电影
    def oldFilm(image):
     im = np.asarray(image.convert('RGB'))
     # r=r*0.393+g*0.769+b*0.189 g=r*0.349+g*0.686+b*0.168 b=r*0.272+g*0.534b*0.131
     trans = np.array([[0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131]]).transpose()
     # clip 超过255的颜色置为255
     im = np.dot(im, trans).clip(max=255)
     return Image.fromarray(np.array(im).astype('uint8'))
    
    
    # 反色
    def reverse(image):
     im = 255 - np.asarray(image.convert('RGB'))
     return Image.fromarray(np.array(im).astype('uint8'))
    
    
    def chooseBaseImagePath():
     name = tkinter.filedialog.askopenfilename()
     if name != '':
     global baseImgPath
     baseImgPath = name
     baseImageLabel.config(text=name)
     baseImg = Image.open(baseImgPath)
     widthEntry.delete(0, tkinter.END)
     heightEntry.delete(0, tkinter.END)
     widthEntry.insert(0, baseImg.size[0])
     heightEntry.insert(0, baseImg.size[1])
     else:
     baseImageLabel.config(text="您没有选择任何文件")
    
    
    def chooseImagesPath():
     name = askdirectory()
     if name != '':
     global imagesPath
     imagesPath = name
     ImagesLabel.config(text=name)
     else:
     ImagesLabel.config(text="您没有选择任何文件")
    
    
    def thread_it(func, *args):
     # 创建
     t = threading.Thread(target=func, args=args)
     # 守护 !!!
     t.setDaemon(True)
     # 启动
     t.start()
    
    
    def test():
     MyThread(1, "Thread-1", 1).start()
    
    
    baseImgPath = ''
    
    
    def generator():
     baseImg = Image.open(baseImgPath)
     baseImg = baseImg.convert('RGBA')
     files = glob.glob(imagesPath + '/*.*') # 获取图片
     random.shuffle(files)
     num = len(files)
     # 模板图片大小
     x = baseImg.size[0]
     y = baseImg.size[1]
     # 每张图片数量 这个公式是为了xNum * yNum 的总图片数量<num又成比例的最大整数
     yNum = int((num / (y / x)) ** 0.5)
     if yNum == 0:
     yNum = 1
     xNum = int(num / yNum)
     # 图片大小 因为像素没有小数点 为防止黑边所以+1
     xSize = int(x / xNum) + 1
     ySize = int(y / yNum) + 1
     # 生成数量的随机列表 用于随机位置合成图片
     l = [n for n in range(0, xNum * yNum)]
     random.shuffle(l)
     toImage = Image.new('RGB', (x, y))
     num = 1
     for file in files:
     if num <= xNum * yNum:
      num = num + 1
     else:
      break
     fromImage = Image.open(file)
    
     temp = l.pop()
     i = int(temp % xNum)
     j = int(temp / xNum)
     out = fromImage.resize((xSize, ySize), Image.ANTIALIAS).convert('RGBA')
     toImage.paste(out, (i * xSize, j * ySize))
     toImage = toImage.convert('RGBA')
     img = Image.blend(baseImg, toImage, alpha)
     # 特效 但是会读取像素会降低效率
     choose = v.get()
     if choose == 1:
      img = blackWithe(img)
     elif choose == 2:
      img = fleeting(img)
     elif choose == 3:
      img = oldFilm(img)
     elif choose == 4:
      img = reverse(img)
    
     resize = img.resize((300, 300), Image.ANTIALIAS).convert('RGBA')
     # 显示图片
     photo = ImageTk.PhotoImage(resize)
     showLabel.config(image=photo)
     showLabel.image = photo
     toImage.save('generator.png')
     img = img.resize((int(widthEntry.get()),int(heightEntry.get())), Image.ANTIALIAS).convert('RGBA')
     img.save("final.png")
     resize.save("resize.png")
    
    
    class MyThread(threading.Thread): # 继承父类threading.Thread
     def __init__(self, threadID, name, counter):
     threading.Thread.__init__(self)
     self.threadID = threadID
     self.name = name
     self.counter = counter
    
     def run(self): # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
     generator()
    
    
    root = tkinter.Tk()
    root.title('generator')
    root.geometry('500x550')
    baseImageLabel = Label(root, text='')
    baseImageLabel.place(x=10, y=10)
    baseImageBtn = Button(root, text="选择底图", command=chooseBaseImagePath).place(x=10, y=30)
    ImagesLabel = Label(root, text='')
    ImagesLabel.place(x=10, y=60)
    ImagesBtn = Button(root, text="选择合成图文件夹", command=chooseImagesPath).place(x=10, y=80)
    
    v = tkinter.IntVar()
    v.set(0)
    Radiobutton(root, variable=v, text='默认', value=0, ).place(x=10, y=120)
    Radiobutton(root, variable=v, text='黑白', value=1, ).place(x=110, y=120)
    Radiobutton(root, variable=v, text='流年', value=2, ).place(x=210, y=120)
    Radiobutton(root, variable=v, text='旧电影', value=3, ).place(x=310, y=120)
    Radiobutton(root, variable=v, text='反色', value=4, ).place(x=410, y=120)
    
    scaleLabel = Label(root, text='透明度').place(x=10, y=170)
    scale = tkinter.Scale(root, from_=0, to=100, orient=tkinter.HORIZONTAL, command=resize)
    scale.set(30) # 设置初始值
    scale.pack(fill=tkinter.X, expand=1)
    scale.place(x=70, y=150)
    Label(root, text='宽(像素)').place(x=180, y=170)
    widthEntry = Entry(root, bd=1)
    widthEntry.place(x=230, y=173, width=100)
    Label(root, text='高(像素)').place(x=320, y=170)
    heightEntry = Entry(root, bd=1)
    heightEntry.place(x=370, y=173, width=100)
    
    generatorBtn = Button(root, text="生成", command=test).place(x=10, y=220)
    showLabel = Label(root)
    showLabel.place(x=100, y=220)
    root.mainloop()

    想了解更多编程学习,敬请关注php培训栏目!

    热心网友 时间:2022-04-28 06:02

    opencv可以,自己学习怎么用
    声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
    在公交车上实施扒窃,会受到怎样的处罚? 交通违法行为识别 公交车扒窃会如何处罚? 郑州鱼缸清洗找哪家公司做得比较好? 郑州有没有专业维修鱼缸,清洗鱼缸的? ...的鱼缸,放在办公室养些鱼水草之类的。郑州哪里有卖这样的鱼缸。_百... 我们公司想要定做个观赏鱼缸,不知道郑州哪家公司最专业? 谁知道郑州生态鱼缸定做哪家做的效果最好? 联想电脑启用无线功能的功能键? 笔记本电脑怎么连接网笔记本电脑怎样连接无线网 Python数据容器中,字典与列表,元组,字符串这三种容器有什么本质区别? python 字符串和元组一样吗 Python中除了字符串以外,还有哪些常用的序列类型呢? 关于Python的序列、列表和元组 python的元组和列表有什么区别 python中什么是序列,列表,元组,字符串,索引,区别是什么 python中的and和c语言中的&的区别是什么 python中// 和/有什么区别 python中&quot;&quot;和&#39;什么区别 python中&#39;和&quot;&quot;的区别 Python里面的和的区别 什么是python中的自省 Python中用isinstance判断多个变量的类型,如何简洁表述呢 Python中继承的理解与运用? type和isinstance函数的区别 python 中instance是什么类型 isinstance python2.7是什么函数 python 语句isinstance是在判断什么?type是什么类型 python当中isinstance()的作用以及用法,能详细的说说吗?谢谢 python 3 isinstance函数的用法,下面的代码如何解释? 怎么用python把多个图片变成gif 格式? 把有透明区域的png图片和另外一个图片合并成一个,如何在web程序端实现,如php,python等 使用 python photogrammetry toolbox 进行照片3d重建使用什么软件 请使用Python语言完成图片内容,答对重谢! 根据抓来的数据包 怎么用python 实现图片上 Python制作一个BMP图片为什么不可以超过3W*3W像素,是图片格式原因么? 怎么把微信里公众号作者录的文章导出来呢?好迫切想知道,知道的人们告诉我吧谢谢 python怎么抓取搜狗的微信文章 新手怎么轻松搭建http网站服务器? 怎么搭建一个自己的网站了?’ 新手入门 想做自己做一个网站 求一个制作网站的教程 php 常用的数组函数都有哪些? 作用是什么?有什么特点? 怎么使用? php数组函数序列之array_splice() - 在数组任意位置插入元素 PHP为什么使用array 怎么PHP用array()作为参数 php toarray函数怎么用 PHP获取数组中某元素的位置及array_keys函数应用 怎么将字符串转换为INT类型 php cookie 时间设置失效? 如何设置cookie的有效期