python將多張圖片合并成一張圖片的過程
說明:
今天想著把圖片如何合并成一張圖片,然后我就搜到了一篇博客,博主寫的很好,我仔細(xì)看了,還能用,就是效果不太好(就是原圖的形狀比例變了,看著很不爽),然后我重新優(yōu)化了下。
合并圖片的三個(gè)過程
1、參考原博主的:
import os
import PIL.Image as Image
IMAGES_PATH = r'E:\000photo\漫畫柜\\' # 圖片集地址
IMAGES_FORMAT = ['.jpg', '.JPG'] # 圖片格式
IMAGE_SIZE = 256 # 每張小圖片的大小
IMAGE_ROW = 4 # 圖片間隔,也就是合并成一張圖后,一共有幾行
IMAGE_COLUMN = 6 # 圖片間隔,也就是合并成一張圖后,一共有幾列
IMAGE_SAVE_PATH = r'E:\000photo\漫畫柜\final.jpg' # 圖片轉(zhuǎn)換后的地址
# 獲取圖片集地址下的所有圖片名稱
image_names = [name for name in os.listdir(IMAGES_PATH) for item in IMAGES_FORMAT if
os.path.splitext(name)[1] == item]
print("image_names", image_names)
# 簡(jiǎn)單的對(duì)于參數(shù)的設(shè)定和實(shí)際圖片集的大小進(jìn)行數(shù)量判斷
if len(image_names) != IMAGE_ROW * IMAGE_COLUMN:
raise ValueError("合成圖片的參數(shù)和要求的數(shù)量不能匹配!")
# 定義圖像拼接函數(shù)
def image_compose():
to_image = Image.new('RGB', (IMAGE_COLUMN * IMAGE_SIZE, IMAGE_ROW * IMAGE_SIZE)) # 創(chuàng)建一個(gè)新圖
# 循環(huán)遍歷,把每張圖片按順序粘貼到對(duì)應(yīng)位置上
for y in range(1, IMAGE_ROW + 1):
for x in range(1, IMAGE_COLUMN + 1):
from_image = Image.open(IMAGES_PATH + image_names[IMAGE_COLUMN * (y - 1) + x - 1]).resize(
(IMAGE_SIZE, IMAGE_SIZE), Image.ANTIALIAS)
to_image.paste(from_image, ((x - 1) * IMAGE_SIZE, (y - 1) * IMAGE_SIZE))
return to_image.save(IMAGE_SAVE_PATH) # 保存新圖
image_compose() # 調(diào)用函數(shù)
我的原圖片:


其實(shí)這個(gè)代碼有倆個(gè)我覺得要優(yōu)化的地方:
第一個(gè)就是:要求的圖片的數(shù)量,我想改成合并的圖片的列自己定義,行隨著數(shù)量的增加自動(dòng)往下增加。
第二個(gè)就是:我想把原圖片的形狀保持不變。
2、優(yōu)化第一個(gè)數(shù)量問題:
這個(gè)代碼改動(dòng)較少,不過已經(jīng)達(dá)到了數(shù)量問題。
import os
import PIL.Image as Image
IMAGES_PATH = r'E:\000photo\漫畫柜\\' # 圖片集地址
IMAGES_FORMAT = ['.jpg', '.JPG'] # 圖片格式
IMAGE_SIZE = 256 # 每張小圖片的大小
IMAGE_COLUMN = 5 # 圖片間隔,也就是合并成一張圖后,一共有幾列
IMAGE_SAVE_PATH = r'E:\000photo\漫畫柜final.jpg' # 圖片轉(zhuǎn)換后的地址
# 獲取圖片集地址下的所有圖片名稱
image_names = [name for name in os.listdir(IMAGES_PATH) for item in IMAGES_FORMAT if
os.path.splitext(name)[1] == item]
# IMAGE_ROW = 4 # 圖片間隔,也就是合并成一張圖后,一共有幾行
IMAGE_ROW_yu = len(image_names) % IMAGE_COLUMN
if IMAGE_ROW_yu == 0:
IMAGE_ROW = len(image_names) // IMAGE_COLUMN
else:
IMAGE_ROW = len(image_names) // IMAGE_COLUMN + 1
print("image_names", image_names)
# 定義圖像拼接函數(shù)
def image_compose():
to_image = Image.new('RGB', (IMAGE_COLUMN * IMAGE_SIZE, IMAGE_ROW * IMAGE_SIZE)) # 創(chuàng)建一個(gè)新圖
# 循環(huán)遍歷,把每張圖片按順序粘貼到對(duì)應(yīng)位置上
total_num = 0
for y in range(1, IMAGE_ROW + 1):
for x in range(1, IMAGE_COLUMN + 1):
from_image = Image.open(IMAGES_PATH + image_names[IMAGE_COLUMN * (y - 1) + x - 1]).resize(
(IMAGE_SIZE, IMAGE_SIZE), Image.ANTIALIAS)
to_image.paste(from_image, ((x - 1) * IMAGE_SIZE, (y - 1) * IMAGE_SIZE))
total_num += 1
if total_num == len(image_names):
break
return to_image.save(IMAGE_SAVE_PATH) # 保存新圖
image_compose() # 調(diào)用函數(shù)

可以看到,當(dāng)我圖片不是正好是行列的倍數(shù)時(shí),不影響圖片的拼接合并。
3、優(yōu)化倆個(gè)問題(數(shù)量不限+性狀按比例變小)
這個(gè)代碼幾乎全部改了,我重新按自己想要的效果邏輯改動(dòng)的,最后合并的像素寬和高是從圖片列表中去80%的位置圖片的寬和高(排序之后),這樣可以百分之80的圖片是完全顯示的,可能其他的不是全部顯示,但是原圖的形狀是沒有變化。
import os
import PIL.Image as Image
def resize_by_width(infile, image_size):
"""按照寬度進(jìn)行所需比例縮放"""
im = Image.open(infile)
(x, y) = im.size
lv = round(x / image_size, 2) + 0.01
x_s = int(x // lv)
y_s = int(y // lv)
print("x_s", x_s, y_s)
out = im.resize((x_s, y_s), Image.ANTIALIAS)
return out
def get_new_img_xy(infile, image_size):
"""返回一個(gè)圖片的寬、高像素"""
im = Image.open(infile)
(x, y) = im.size
lv = round(x / image_size, 2) + 0.01
x_s = x // lv
y_s = y // lv
# print("x_s", x_s, y_s)
# out = im.resize((x_s, y_s), Image.ANTIALIAS)
return x_s, y_s
# 定義圖像拼接函數(shù)
def image_compose(image_colnum, image_size, image_rownum, image_names, image_save_path, x_new, y_new):
to_image = Image.new('RGB', (image_colnum * x_new, image_rownum * y_new)) # 創(chuàng)建一個(gè)新圖
# 循環(huán)遍歷,把每張圖片按順序粘貼到對(duì)應(yīng)位置上
total_num = 0
for y in range(1, image_rownum + 1):
for x in range(1, image_colnum + 1):
from_image = resize_by_width(image_names[image_colnum * (y - 1) + x - 1], image_size)
# from_image = Image.open(image_names[image_colnum * (y - 1) + x - 1]).resize((image_size,image_size ), Image.ANTIALIAS)
to_image.paste(from_image, ((x - 1) * x_new, (y - 1) * y_new))
total_num += 1
if total_num == len(image_names):
break
return to_image.save(image_save_path) # 保存新圖
def get_image_list_fullpath(dir_path):
file_name_list = os.listdir(dir_path)
image_fullpath_list = []
for file_name_one in file_name_list:
file_one_path = os.path.join(dir_path, file_name_one)
if os.path.isfile(file_one_path):
image_fullpath_list.append(file_one_path)
else:
img_path_list = get_image_list_fullpath(file_one_path)
image_fullpath_list.extend(img_path_list)
return image_fullpath_list
def merge_images(image_dir_path,image_size,image_colnum):
# 獲取圖片集地址下的所有圖片名稱
image_fullpath_list = get_image_list_fullpath(image_dir_path)
print("image_fullpath_list", len(image_fullpath_list), image_fullpath_list)
image_save_path = r'{}.jpg'.format(image_dir_path) # 圖片轉(zhuǎn)換后的地址
# image_rownum = 4 # 圖片間隔,也就是合并成一張圖后,一共有幾行
image_rownum_yu = len(image_fullpath_list) % image_colnum
if image_rownum_yu == 0:
image_rownum = len(image_fullpath_list) // image_colnum
else:
image_rownum = len(image_fullpath_list) // image_colnum + 1
x_list = []
y_list = []
for img_file in image_fullpath_list:
img_x, img_y = get_new_img_xy(img_file, image_size)
x_list.append(img_x)
y_list.append(img_y)
print("x_list", sorted(x_list))
print("y_list", sorted(y_list))
x_new = int(x_list[len(x_list) // 5 * 4])
y_new = int(x_list[len(y_list) // 5 * 4])
image_compose(image_colnum, image_size, image_rownum, image_fullpath_list, image_save_path, x_new, y_new) # 調(diào)用函數(shù)
# for img_file in image_fullpath_list:
# resize_by_width(img_file,image_size)
if __name__ == '__main__':
image_dir_path = r'E:\000photo\美女' # 圖片集地址
image_size = 128 # 每張小圖片的大小
image_colnum = 10 # 合并成一張圖后,一行有幾個(gè)小圖
merge_images(image_dir_path, image_size, image_colnum)
因?yàn)閳D片整的比較多。

截圖小部分:

最后可以看出,原圖片的形狀沒有變化,至此,弄了倆個(gè)小時(shí),總算弄成我想要的效果了。
4、優(yōu)化黑行高度問題
最近有三個(gè)小伙伴私信我,說黑白行問題,今天決定再擼下一年多前的代碼。
然后開始過一遍之前的代碼,發(fā)現(xiàn)之前有個(gè)地方寫錯(cuò)了,我當(dāng)時(shí)也沒有發(fā)現(xiàn),竟然這么多人看我代碼了,也沒有懂Python的小伙伴給我提醒下么???
主要就是之前的:
y_new = int(x_list[len(y_list) // 5 * 4])
這個(gè)地方x_list應(yīng)該是y_list,改下就可以了。
y_new = int(y_list[len(y_list) // 5 * 4])
感覺小伙伴們也不咋動(dòng)手,我還是吧完整的粘貼出來(lái)吧。
import os
import PIL.Image as Image
def resize_by_width(infile, image_size):
"""按照寬度進(jìn)行所需比例縮放"""
im = Image.open(infile)
(x, y) = im.size
lv = round(x / image_size, 2) + 0.01
x_s = int(x // lv)
y_s = int(y // lv)
print("x_s", x_s, y_s)
out = im.resize((x_s, y_s), Image.ANTIALIAS)
return out
def get_new_img_xy(infile, image_size):
"""返回一個(gè)圖片的寬、高像素"""
im = Image.open(infile)
(x, y) = im.size
lv = round(x / image_size, 2) + 0.01
x_s = x // lv
y_s = y // lv
# print("x_s", x_s, y_s)
# out = im.resize((x_s, y_s), Image.ANTIALIAS)
return x_s, y_s
# 定義圖像拼接函數(shù)
def image_compose(image_colnum, image_size, image_rownum, image_names, image_save_path, x_new, y_new):
to_image = Image.new('RGB', (image_colnum * x_new, image_rownum * y_new)) # 創(chuàng)建一個(gè)新圖
# 循環(huán)遍歷,把每張圖片按順序粘貼到對(duì)應(yīng)位置上
total_num = 0
for y in range(1, image_rownum + 1):
for x in range(1, image_colnum + 1):
from_image = resize_by_width(image_names[image_colnum * (y - 1) + x - 1], image_size)
# from_image = Image.open(image_names[image_colnum * (y - 1) + x - 1]).resize((image_size,image_size ), Image.ANTIALIAS)
to_image.paste(from_image, ((x - 1) * x_new, (y - 1) * y_new))
total_num += 1
if total_num == len(image_names):
break
return to_image.save(image_save_path) # 保存新圖
def get_image_list_fullpath(dir_path):
file_name_list = os.listdir(dir_path)
image_fullpath_list = []
for file_name_one in file_name_list:
file_one_path = os.path.join(dir_path, file_name_one)
if os.path.isfile(file_one_path):
image_fullpath_list.append(file_one_path)
else:
img_path_list = get_image_list_fullpath(file_one_path)
image_fullpath_list.extend(img_path_list)
return image_fullpath_list
def merge_images(image_dir_path,image_size,image_colnum):
# 獲取圖片集地址下的所有圖片名稱
image_fullpath_list = get_image_list_fullpath(image_dir_path)
print("image_fullpath_list", len(image_fullpath_list), image_fullpath_list)
image_save_path = r'{}.jpg'.format(image_dir_path) # 圖片轉(zhuǎn)換后的地址
# image_rownum = 4 # 圖片間隔,也就是合并成一張圖后,一共有幾行
image_rownum_yu = len(image_fullpath_list) % image_colnum
if image_rownum_yu == 0:
image_rownum = len(image_fullpath_list) // image_colnum
else:
image_rownum = len(image_fullpath_list) // image_colnum + 1
x_list = []
y_list = []
for img_file in image_fullpath_list:
img_x, img_y = get_new_img_xy(img_file, image_size)
x_list.append(img_x)
y_list.append(img_y)
print("x_list", sorted(x_list))
print("y_list", sorted(y_list))
x_new = int(x_list[len(x_list) // 5 * 4])
y_new = int(y_list[len(y_list) // 5 * 4])
print(" x_new, y_new", x_new, y_new)
image_compose(image_colnum, image_size, image_rownum, image_fullpath_list, image_save_path, x_new, y_new) # 調(diào)用函數(shù)
# for img_file in image_fullpath_list:
# resize_by_width(img_file,image_size)
if __name__ == '__main__':
image_dir_path = r'C:\Users\user\Downloads\archives\趙麗穎壁紙_-_國(guó)內(nèi)版_Bing_images' # 圖片集地址
image_size = 128 # 每張小圖片的大小
image_colnum = 10 # 合并成一張圖后,一行有幾個(gè)小圖
merge_images(image_dir_path, image_size, image_colnum)
給大家上個(gè)效果圖:

5、合成圖片不清晰問題:
這個(gè)主要是像素同比例縮小導(dǎo)致的,我這里image_size = 128 ,該我720,就特別清晰了。

總結(jié)下:
給學(xué)習(xí)編程的小伙伴一個(gè)建議:學(xué)習(xí)人家代碼時(shí)候,大家可以先讀懂人家的代碼,自己嘗試修改,看效果。
最后可以看出,原圖片的形狀沒有變化,至此,黑白問題已經(jīng)修改。
以上就是python將多張圖片合并成一張圖片的過程的詳細(xì)內(nèi)容,更多關(guān)于python多張圖片合成的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Pandas數(shù)據(jù)清洗的實(shí)現(xiàn)
在處理數(shù)據(jù)的時(shí)候,需要對(duì)數(shù)據(jù)進(jìn)行一個(gè)清洗過程,本文就來(lái)介紹一下Pandas數(shù)據(jù)清洗的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11
Python高級(jí)編程之繼承問題詳解(super與mro)
這篇文章主要介紹了Python高級(jí)編程之繼承問題,結(jié)合實(shí)例形式詳細(xì)分析了Python多繼承、MRO順序及super調(diào)用父類等相關(guān)操作技巧,需要的朋友可以參考下2019-11-11
Python TKinter如何自動(dòng)關(guān)閉主窗口
這篇文章主要介紹了Python TKinter如何自動(dòng)關(guān)閉主窗口,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Python使用Spire.XLS for Python輕松實(shí)現(xiàn)將Excel轉(zhuǎn)換為PDF
在許多商務(wù)工作流程中,Excel 文件常用于存儲(chǔ)和分析數(shù)據(jù),然而,在共享報(bào)告或發(fā)票時(shí),將其轉(zhuǎn)換為 PDF 能確保內(nèi)容在不同設(shè)備上保持固定和可讀,下面我們就來(lái)看看如何使用Python實(shí)現(xiàn)Excel到PDF的轉(zhuǎn)換吧2025-11-11
在Python下進(jìn)行UDP網(wǎng)絡(luò)編程的教程
這篇文章主要介紹了在Python下進(jìn)行UDP網(wǎng)絡(luò)編程的教程,UDP編程是Python網(wǎng)絡(luò)編程部分的基礎(chǔ)知識(shí),示例代碼基于Python2.x版本,需要的朋友可以參考下2015-04-04

