首頁 > 軟體

基於Python實現千圖成像工具的範例程式碼

2022-07-26 18:02:42

千圖成像也就是用N張圖片組成一張圖片的效果。製作方法有很多的,最常見的如用ps、懶人圖雲、foto-mosaik-edda這些製作。

千圖成像的效果我大致分為兩類:一為直接用N張圖片根據底圖的畫素顏色、大小,一張張的組成底圖,如foto-mosaik-edda;二為用N張圖片根據底圖的畫素大小,組成一張與底圖大小相仿的圖片,再把二者合成,經調整透明度而成的圖片,如ps。

第一種算是真正意義的千圖成像,但如果選的圖片不夠底圖的畫素顏色匹配,就會造成生成的圖片畸形,但如果選擇的圖片夠好,最終的效果會非常好;第二種的效果就比較平淡了,但對選擇的圖片沒什麼要求,生成的圖片比較正常。

二者的效果各有千秋,而本文使用python實現的是第二種方法,最後製成GUI。

前置

本文使用PySimpleGUI進行GUI設計,PIL、numpy、random 進行圖片處理,os進行檔案操作:

import PySimpleGUI as sg
from PIL import Image
import os
import numpy as np
import random

相關庫使用pip命令安裝即可:

pip install 庫名

GUI製作

為了以後方便使用,不用一次次跑程式,而在原有的程式基礎上進行GUI製作,最後打包成.exe可執行檔案。

GUI介面設計

對於GUI介面的功能只需要設定五個功能即可:

  • 選擇底圖功能
  • 選擇組圖功能
  • 事件展示區域
  • 啟動工具按鈕
  • 退出工具按鈕

最終設計程式碼如下:

# 主題設定
sg.theme('LightBrown3')

# 佈局設定
layout = [
    [sg.Frame(layout=[
        [sg.InputText(key='image_file', size=(32, 1), font=("微軟雅黑", 10), enable_events=True),
        # 設定能選擇的圖片格式
         sg.FileBrowse('選擇底圖',
                       file_types=(("Text Files", "*.png*"), ("Text Files", "*.jpg*"), ("Text Files", "*.jpeg*")),
                       font=("微軟雅黑", 12)),

         sg.Button('選擇組圖', font=("微軟雅黑", 12)),
         ],
    ],
        title='內容選擇', title_color='blue', font=("微軟雅黑", 10), relief=sg.RELIEF_SUNKEN, )],
    [sg.Frame(layout=[
        [sg.Output(size=(51, 10), font=("微軟雅黑", 10))],
    ],
        title='資訊展示', title_color='blue', font=("微軟雅黑", 10), relief=sg.RELIEF_SUNKEN, )],

    [sg.Button('開始生成', font=("微軟雅黑", 12)),
     sg.Text('', font=("微軟雅黑", 12), size=(27, 0)), sg.Button('退出程式', font=("微軟雅黑", 12), button_color='red')]
]
# 建立視窗
window = sg.Window('千圖成像', layout, font=("微軟雅黑", 12), default_element_size=(80, 1))
while True:
    # 退出按鈕
    event, values = window.read()
    if event in (None, '退出程式'):
        break
window.close()

介面效果如下:

GUI介面效果

邏輯設計

獲取圖片時,因為可以輸入路徑,可能會造成儲存,所以這裡加個判斷;最後把得到的圖片路徑存入列表中。

if event == 'image_file':
    files = values['image_file']
    if os.path.exists(files):
        img_Main_file.append(files)
    else:
        print('圖片不存在,請重新選擇圖片!')
        # 彈窗
        sg.popup('圖片不存在,請重新選擇圖片!')

獲取組圖所在的資料夾路徑,依然把得到的路徑存入列表中:

if event == '選擇組圖':
    files = sg.popup_get_folder('請選擇選擇組圖路徑:')
    if os.path.exists(files):
        img_secondary_file.append(files)
    else:
        print('檔案不存在,請重新選擇檔案')
        sg.popup('檔案不存在,請重新選擇檔案')

啟動按鈕,點選時把兩個列表傳入圖片處理常式中:

if event == '開始生成':
    if len(img_Main_file) and len(img_secondary_file) != 0:
        img_save(img_Main_file, img_secondary_file)
    else:
        sg.popup('未選擇!')

圖片處理

因為無法保證所有圖片的大小都一樣,所以需要經過一定的處理。圖片處理使用的庫是PIL和numpy。

修改底圖大小

對於底圖,我們可以稱之為‘容器’,底圖的大小決定其組成圖片的多少,也可以決定組成圖片的畫素大小、是否清晰。取出底圖的高寬越多,圖片越大,圖片越清晰;取出底圖百分之十的大小,這個數值可以增大,但最好不要超過百分之三十。

open_img = Image.open('./底圖.jpg')
# 獲取圖片本身寬度、高度
width, height = open_img.size
# 重新計算底圖高寬,加大底圖的畫素。取出底圖的10%的高寬,用int進行取整
Increase_width = int(width * 0.10) * int(height * 0.10)
Increase_height = ((Increase_width / width) * height // round(height * 0.10)) * round(height * 0.10)
# 更改為重新計算的大小
open_img = open_img.resize((int(Increase_width), int(Increase_height)), Image.ANTIALIAS)

修改組圖大小

把組成圖片的大小修改為底圖的百分之十的大小,這個數值也可以增大:

# 讀取檔案路徑下的圖片,並修改大小
img_matrix = []
for e in os.listdir('./image'):
    # 防止資料夾中出現並圖片格式的檔案
    try:
        img_matrix.append(np.array(Image.open(os.path.join(str(img_files_list[0]), e)).convert('RGB').resize(
            (int(width * 0.10), int(height * 0.10)), Image.ANTIALIAS)))
    except OSError as e:
        print(e)

計算圖片填充次數

上面說過,底圖的大小決定了組成圖片的多少,而下面的程式碼就是根據底圖的大小以及組成圖片的大小計算出主圖能填充多少圖片:

# 計算主圖高寬能填充多少圖片
width_picture_Fill_frequency = int(Increase_width / int(width * 0.10))
height_picture_Fill_frequency = int(Increase_height / int(height * 0.10))

組圖合成

根據底圖高寬的10%以及圖片填充次數,得出矩陣,然後把組圖隨機填充到矩陣中:

array_img = np.zeros_like(np.array(open_img))
for i in range(width_picture_Fill_frequency):
    for x in range(height_picture_Fill_frequency):
        array_img[x * int(height * 0.10):(x + 1) * int(height * 0.10),
        i * int(width * 0.10):(i + 1) * int(width * 0.10), :] = random.choice(img_matrix)
array_img = Image.fromarray(array_img)

生成的圖片清晰度還是很高的,不過在手機上看比較模糊:

組圖效果

圖片合成

把底圖和組圖進行合併,alpha可以調整二者的透明度,最佳為0.7、0.8、0.9。

img = Image.blend(array_img, open_img, alpha=0.8)  # 0.7,0.8,0.9
img.save('千圖成像.jpg')

圖片效果

GUI打包

打包可以直接使用pyinstaller進行安裝;如果你不知道怎麼打包,或者不熟悉命令列操作,可以使用前面文章:打包工具,這款打包工具可以簡單的滿足打包需求。

使用pyinstaller庫打包,啟動命令列視窗,在命令列視窗cd到檔案所在的檔案目錄中,最後用下面命令進行打包:

pyinstaller -F -w 名稱.py

打包時可能會報錯:

報錯範例

報錯源於一個hook-sqlalchemy.py檔案,一個簡單的解決方法是找到它直接回收刪除它(最後暫未發現刪除它對打包後的exe檔案有什麼影響),等打包完成後在放回去即可:

打包過程沒出現什麼狀況,會得到幾個檔案,進入dist資料夾,就可以看見.exe檔案了。

至此,我們就成功利用Python實現了製作千圖成像工具。

到此這篇關於基於Python實現千圖成像工具的範例程式碼的文章就介紹到這了,更多相關Python千圖成像內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com