目錄
文章目錄
前言
Github
效果
實作過程
整體程式碼
首頁 後端開發 Python教學 Python照片合成的方法詳解

Python照片合成的方法詳解

Aug 29, 2020 pm 04:26 PM
python

Python照片合成的方法詳解

相關學習推薦:python教學

文章目錄

      • 前言
      • Github
      • 效果
      • 實作過程
      • #整體程式碼

前言

看電影的時候發現一個照片牆的功能,覺得這樣生成照片挺好玩的,於是就動手用Python做了一下,覺得用來做照片紀念的效果可能會不錯。

P:後面了解到我想做的功能叫蒙太奇拼圖,所以這篇部落格記錄先留著,閒下來會去看一下蒙太奇拼圖的演算法

Github

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

效果

Python照片合成的方法詳解
Python照片合成的方法詳解

實作過程

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 的总图片数量<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
登入後複製

Python照片合成的方法詳解

#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(&#39;RGBA&#39;)
        toImage.paste(out, (i * xSize, j * ySize))
        toImage = toImage.convert(&#39;RGBA&#39;)
        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”)
Python照片合成的方法詳解
![Python照片合成的方法詳解](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.建立視覺化介面
Python照片合成的方法詳解
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 = &#39;&#39;


# 滑动条回调 修改透明度
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(&#39;RGB&#39;))
    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(&#39;uint8&#39;))


# 流年
def fleeting(image, params=12):
    im = np.asarray(image.convert(&#39;RGB&#39;))
    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(&#39;uint8&#39;))


# 旧电影
def oldFilm(image):
    im = np.asarray(image.convert(&#39;RGB&#39;))
    # 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(&#39;uint8&#39;))


# 反色
def reverse(image):
    im = 255 - np.asarray(image.convert(&#39;RGB&#39;))
    return Image.fromarray(np.array(im).astype(&#39;uint8&#39;))


def chooseBaseImagePath():
    name = tkinter.filedialog.askopenfilename()
    if name != &#39;&#39;:
        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 != &#39;&#39;:
        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 = &#39;&#39;


def generator():
    baseImg = Image.open(baseImgPath)
    baseImg = baseImg.convert(&#39;RGBA&#39;)
    files = glob.glob(imagesPath + &#39;/*.*&#39;)  # 获取图片
    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(&#39;RGB&#39;, (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(&#39;RGBA&#39;)
        toImage.paste(out, (i * xSize, j * ySize))
        toImage = toImage.convert(&#39;RGBA&#39;)
        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(&#39;RGBA&#39;)
        # 显示图片
        photo = ImageTk.PhotoImage(resize)
        showLabel.config(image=photo)
        showLabel.image = photo
    toImage.save(&#39;generator.png&#39;)
    img = img.resize((int(widthEntry.get()),int(heightEntry.get())), Image.ANTIALIAS).convert(&#39;RGBA&#39;)
    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(&#39;generator&#39;)
root.geometry(&#39;500x550&#39;)
baseImageLabel = Label(root, text=&#39;&#39;)
baseImageLabel.place(x=10, y=10)
baseImageBtn = Button(root, text="选择底图", command=chooseBaseImagePath).place(x=10, y=30)
ImagesLabel = Label(root, text=&#39;&#39;)
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=&#39;默认&#39;, value=0, ).place(x=10, y=120)
Radiobutton(root, variable=v, text=&#39;黑白&#39;, value=1, ).place(x=110, y=120)
Radiobutton(root, variable=v, text=&#39;流年&#39;, value=2, ).place(x=210, y=120)
Radiobutton(root, variable=v, text=&#39;旧电影&#39;, value=3, ).place(x=310, y=120)
Radiobutton(root, variable=v, text=&#39;反色&#39;, value=4, ).place(x=410, y=120)

scaleLabel = Label(root, text=&#39;透明度&#39;).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=&#39;宽(像素)&#39;).place(x=180, y=170)
widthEntry = Entry(root, bd=1)
widthEntry.place(x=230, y=173, width=100)
Label(root, text=&#39;高(像素)&#39;).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培訓欄位!

#

以上是Python照片合成的方法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1325
25
PHP教程
1273
29
C# 教程
1252
24
PHP和Python:解釋了不同的範例 PHP和Python:解釋了不同的範例 Apr 18, 2025 am 12:26 AM

PHP主要是過程式編程,但也支持面向對象編程(OOP);Python支持多種範式,包括OOP、函數式和過程式編程。 PHP適合web開發,Python適用於多種應用,如數據分析和機器學習。

在PHP和Python之間進行選擇:指南 在PHP和Python之間進行選擇:指南 Apr 18, 2025 am 12:24 AM

PHP適合網頁開發和快速原型開發,Python適用於數據科學和機器學習。 1.PHP用於動態網頁開發,語法簡單,適合快速開發。 2.Python語法簡潔,適用於多領域,庫生態系統強大。

sublime怎麼運行代碼python sublime怎麼運行代碼python Apr 16, 2025 am 08:48 AM

在 Sublime Text 中運行 Python 代碼,需先安裝 Python 插件,再創建 .py 文件並編寫代碼,最後按 Ctrl B 運行代碼,輸出會在控制台中顯示。

Python vs. JavaScript:學習曲線和易用性 Python vs. JavaScript:學習曲線和易用性 Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

PHP和Python:深入了解他們的歷史 PHP和Python:深入了解他們的歷史 Apr 18, 2025 am 12:25 AM

PHP起源於1994年,由RasmusLerdorf開發,最初用於跟踪網站訪問者,逐漸演變為服務器端腳本語言,廣泛應用於網頁開發。 Python由GuidovanRossum於1980年代末開發,1991年首次發布,強調代碼可讀性和簡潔性,適用於科學計算、數據分析等領域。

Golang vs. Python:性能和可伸縮性 Golang vs. Python:性能和可伸縮性 Apr 19, 2025 am 12:18 AM

Golang在性能和可擴展性方面優於Python。 1)Golang的編譯型特性和高效並發模型使其在高並發場景下表現出色。 2)Python作為解釋型語言,執行速度較慢,但通過工具如Cython可優化性能。

vscode在哪寫代碼 vscode在哪寫代碼 Apr 15, 2025 pm 09:54 PM

在 Visual Studio Code(VSCode)中編寫代碼簡單易行,只需安裝 VSCode、創建項目、選擇語言、創建文件、編寫代碼、保存並運行即可。 VSCode 的優點包括跨平台、免費開源、強大功能、擴展豐富,以及輕量快速。

notepad 怎麼運行python notepad 怎麼運行python Apr 16, 2025 pm 07:33 PM

在 Notepad 中運行 Python 代碼需要安裝 Python 可執行文件和 NppExec 插件。安裝 Python 並為其添加 PATH 後,在 NppExec 插件中配置命令為“python”、參數為“{CURRENT_DIRECTORY}{FILE_NAME}”,即可在 Notepad 中通過快捷鍵“F6”運行 Python 代碼。

See all articles