python和php合成,Python照片合成的方法详解

7564a382302caadbf67182436c1b296d.png

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

文章目录前言

Github

效果

实现过程

整体代码

前言

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

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

Github

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

效果

babda74441bacb321f9bef0374c71267.gif

88569e6a328ce94a79be008deb60db8f.gif

实现过程

1.获取图片文件夹的图片个数N,将底图拆分成XY块区域,且使X * Y

(为了保证整体的协调,会舍弃几张图片,比如5张时可能只取22的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 的总图片数量

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

faad0df95c84dca1cdaa4b64a2b7717a.png

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”)

a27c24bf29db313542d1458e15d5fed2.png

a4bf7cac95b7dc4396160429c9f6e24c.png

4.建立可视化界面

163da4876c3701436ef28155077fbb52.png

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 的总图片数量

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培训栏目!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/560408.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux系统运行pbs出现ntf,Linux系统启动故障修复

Linux在启动过程中会出现一些故障&#xff0c;导致系统无法正常启动&#xff0c;本文列举了几个应用单用户模式、GRUB命令操作、Linux救援模式的典型故障修复案例。一、单用户模式Linux提供了单用户模式(类似Windows安全模式)&#xff0c;可以在最小环境中进行系统维护。在单用…

在安卓手机上下载linux系统,如何在安卓手机上运行Ubuntu系统

Ubuntu是一款linux系统&#xff0c;一般我们都是将其运行在电脑中&#xff0c;可不可以在手机端也能运行Ubuntu呢&#xff1f;也是可以的&#xff0c;想知道如何实现的&#xff0c;就跟我来吧。第一步:首先, 你的手机需要获取root权限. 如果不知道如何获取, 可以到搜索一下安卓…

linux系统如何挂载新硬盘,Linux系统挂载新硬盘操作流程

1、登录后输入fdisk -l命令看当前磁盘信息2、可以看到除了当前的第一块硬盘外还有一块sdb的第二块硬盘&#xff0c;然后用fdisk /dev/sdb 进行分区3、进入fdisk命令&#xff0c;输入h可以看到该命令的帮助&#xff0c;按n进行分区4、这里输入e即分为逻辑分区&#xff0c;按p即分…

linux长期版本维护内容,[图]Linux Kernel 4.20首个维护版本更新发布 已稳定可广泛部署...

Linux Kernel 4.20内核系列由Linus Torvalds于2018年12月23日发布&#xff0c;是目前Linux内核最新的分支。目前在Kernel.org网站上4.20.1版本标记已经从“Mainline”调整为“stable”&#xff0c;意味着可以被大部分Linux发行版本使用。而Arch Linux是首个装备4.20.1的发行版本…

三角函数和反三角函数图像、导数、积分、等式关系

之前对三角函数的理解仅局限于sin&#xff0c;cos&#xff0c;tan。但是目前遇到的都是些csc&#xff0c;sec&#xff0c;cot&#xff0c;arctan&#xff0c;arccos&#xff0c;arcsin。积分和求导还有一堆公式 最近看到了一个六边形记忆法&#xff0c;更加简便。 1.倒三角&am…

linux分区后盘符找不到,为什么我的磁盘不见了,怎么找回来啊?

2006-03-24 02:14:35找不回来了&#xff0c;因为你已经删除了这个分区&#xff0c;也就是说这个分区已经不存在了&#xff0c;文件分配表也被删掉了&#xff0c;所以没有办法找回来。动态、不可读取的意思就是这个空间还没有建立分区。全部2006-03-24 02:14:352006-03-23 12:36…

ds18b20温度传感器驱动编写

协议 DS18B20的一线工作协议流程是&#xff1a;初始化→ROM操作指令→存储器操作指令→数据传输&#xff0c;其工作时序包括&#xff1a;初始化时序、写时序、读时序。 黑色部分表示单片机操作&#xff0c;蓝色部分表示18b20操作&#xff0c;每次主机操作完成之后等待18b20状…

SHT1x/SHT7x数字温湿度传感器驱动编写

结构图 启动传输时序图 SHT10串行通信IO初始化 其中SDA和SCL分别是数据线和时钟线。分别对应单片机的1.1口和1.0口 #define SCL P1_0 //SHT10时钟 #define SDA P1_1 //SHT10数据线由时序图可知&#xff0c;一开始SDA和SCL分别高电平和低电平 /****…

zigbee板子:lcd显示汉字

main函数 #include <ioCC2530.h> #include "LCD.h"void main() {//unsigned char i0; LCD_Init(); //oled 初始化 LCD_CLS(); //屏全亮 LCD_welcome();while(1){} } 首先呢。我们运行这个程序&#xff0c;然后可…

matlab实时采集串口数据并分析串口数据传送格式

下位机 zigbee代码 最近在做基于zigbee的RSSI实时定位系统。这个系统需要我们实时的测量得到每一个位置的rssi值。首先&#xff0c;我需要研究怎么把这个rssi值通过串口传到我们的上位机上。 我们可以看到我们下位机&#xff0c;里面有一个传送数据包的一个东西&#xff0c;在…

matlab guide 打开图像并将图像显示到界面

最近又用到matlab做GUI&#xff0c;之前学的全忘了&#xff0c;还好两年前留了大实验源码。 下面我来通过源码分析一下matlab怎么做GUI。这次我来分析如何通过matlab打开图像并将图像显示到界面。 实验效果 原理 打开菜单编辑器看这个属性&#xff1a; 找到回调 可以看到回调…

matlab guide 将matlab处理过的图片保存

最近又用到matlab做GUI&#xff0c;之前学的全忘了&#xff0c;还好两年前留了大实验源码。 这次我来分析如何将matlab处理过的图片保存。 实验效果 经过灰度转换&#xff0c;图象被处理&#xff0c;并显示到另一个地方。 点击保存 图片被保存 实验原理 查看保存的回调函…

深圳linux测试题库,Linux认证考试题库及答案

Linux认证考试题库及答案1、一个文件的权限是-rw-rw-r--&#xff0c;这个文件所有者的权限是什么()a、read-onlyb、read-writec、write答案 b2、下面哪个值代表多用户启动()a、1b、0c、3d、5答案 c3、下面哪个文件代表系统初始化信息()a、/etc/inittabb、/etc/initc、/etc/proc…

matlab guide 打开excel并对其中数据进行处理

最近又用到matlab做GUI&#xff0c;之前学的全忘了&#xff0c;还好两年前留了大实验源码。 这次我来分析如何通过matlab处理excel数据 实验结果 对excel处理的效果&#xff1a; 实验原理 打开excel回调函数 function openexc_Callback(hObject, eventdata, handles) [fil…

linux 显示文件名写到txt,C++获取某个路径下所有文件的文件名,读写TXT文件到新的文件...

好久没写io操作了&#xff0c;手生了好多&#xff0c;最简单实用的C代码也push上来吧。环境&#xff1a;mac&#xff0c;xcode(注意mac环境下Windows的函数不能用)功能&#xff1a;打开一个文件目录&#xff0c;把所有文件名读取到一个TXT文件中#include #include #include #in…

生成超清分辨率视频,南洋理工开源Upscale-A-Video

大模型在生成高质量图像方面表现出色,但在生成视频任务中&#xff0c;经常会面临视频不连贯、图像模糊、掉帧等问题。 这主要是因为生成式抽样过程中的随机性,会在视频序列中引入无法预测的帧跳动。同时现有方法仅考虑了局部视频片段的时空一致性,无法保证整个长视频的整体连贯…

matlab 文件之间相互调用实例

效果&#xff1a; 找到按钮的回调 function pushbutton1_Callback(hObject, eventdata, handles) cd Deploy Nodes %square_random(100,100,0.03);%布置节点 GPS误差为0 %square_random(1000,300,0.2,30) %GPS误差为30m %C_random([1000,300,300,700],240,0.2); square_regul…

linux+虚拟机上的wdcp,linux虚拟主机服务器wdcp系统教程

满意答案eslct2017.01.29采纳率&#xff1a;47% 等级&#xff1a;9已帮助&#xff1a;1264人linux虚拟主机服务器wdcp系统教程在我们安装了网络服务管理系统wdcp后&#xff0c;可能会有不少疑问还有就是使用过程中出现的问题&#xff0c;下面为大家总结几点比较常见的&#…

matlab guide实现多级界面

matlab如何实现多级界面呢&#xff1f;也就是说&#xff0c;在一个界面点击某个地方&#xff0c;就弹出来另一个界面&#xff0c;在另一个界面还可以再进行操作。 实验结果 实验原理 首先建立两个gui&#xff0c;并且每个gui都进行如下设置&#xff1a; 然后我们找到test.f…

常见积分和导数的推导

导数&#xff1a; 1.yarcsinxyarcsinxyarcsinx的导数&#xff1a; yarcsin⁡x→xsin⁡y→1y′cos⁡y→y′1cos⁡y→y′11−x2\\y\arcsin x\\ \rightarrow x\sin y\\ \rightarrow 1{y}\cos y\\ \rightarrow {y}\frac{1}{\cos y}\\ \rightarrow {y}\frac{1}{\sqrt{1-x^{2}}}yarc…