python圖片拼接
這兩天看到一張圖片,想用python來實現類似的圖片拼接

先分析圖片:
- 很明顯,這張圖片是由多張圖片疊加拼接而成
- 從最后一張開始開始疊加,之后的每張圖片都往上平移了一個固定的距離並且附着在原有的圖片上
- 我們要做的就是控制這個距離,將所有需要的圖片完成這個拼接
實操:
- 獲取所有需要的圖片的資源
1 def getAllImg(path): 2 result = [] 3 filelist = os.listdir(path) 4 for file in filelist: 5 if os.path.isfile(os.path.join(path, file)): 6 if file.split('.')[1] in ('jpg', 'png'): 7 result.append(os.path.join(path, file)) 8 return result
-
實現兩張圖片的拼接
1 result = '/root/lambda/static/result.png' 2 3 4 def join(png1, png2, size): 5 img1, img2 = Image.open(png1), Image.open(png2) 6 size1, size2 = img1.size, img2.size # 獲取兩張圖片的大小 7 joint = Image.new('RGB', (size1[0], size1[1] + size2[1] - size)) 8 # 新建一張新的圖片 9 # 因為拼接的圖片的寬都是一樣,所以寬為固定值 10 # 高為兩張圖片的高相加再減去需要縮進的部分 11 loc1, loc2 = (0, 0), (0, size1[1] - size) 12 # 兩張圖片的位置 13 # a------------- 14 # | | 15 # | | 16 # | | 17 # | | 18 # | | 19 # b------------| 20 # | | 21 # | | 22 # | | 23 # | | 24 # |--------- --| 25 26 # 位置都是以該圖片的左上角的坐標決定 27 # 第一張圖片的左上角為a點,a的坐標為(0,0) 28 # 第二張圖片的左上角為b點,a的橫坐標為0,縱坐標為第一張圖片的縱坐標減去第二張圖片上移的size: (0, size[1]-size) 29 30 joint.paste(img2, loc2) 31 joint.paste(img1, loc1) 32 # 因為需要讓第一張圖片放置在圖層的最上面,所以讓第一張圖片最后最后附着上圖片上 33 joint.save(result)
-
循環遞歸調用
1 def start(items, size, first_path=None): 2 # 當first為None時,默認將第一張圖片設置為圖片列表的第一張圖片,第二張圖片設置為圖片列表的第二張 3 # 當這兩張圖片合成后,將圖片列表的已經合成的圖片元素移除 4 # 然后將合成的圖片設置為第一張圖片,將剩余的沒有合成的圖片列表繼續操作 5 # 當first_path不為None,將第一張圖片設置為first_path,第二張圖片設置為傳進來的列表的第一個元素 6 # 合成之后,將剛剛使用的列表的元素刪除 7 # 最后遞歸函數,知道列表為空 8 try: 9 if not first_path: 10 path1, path2 = items[0], items[1] 11 join(path1, path2, size) 12 items.remove(path1) 13 items.remove(path2) 14 return start(items, size, first_path=result) 15 else: 16 path2 = items[0] 17 join(first_path, path2, size) 18 items.remove(path2) 19 return start(items, size, first_path=result) 20 except: 21 pass
-
運行
1 if __name__ == '__main__': 2 s = getAllImg(path) 3 s.sort() 4 start(s, 100) 5 print('最后圖片尺寸--->', Image.open(result).size)
-
效果展示
- 圖片文件
- 1.png

-
2.png

- 3.png和1.png是同一張圖片
- 最終效果圖
- 這個中間的間隔是自己把握的,覺得不合適可以任意更換
- 完整代碼
-
1 import os 2 from PIL import Image 3 4 result = '/root/lambda/static/result.png' # 圖片保存路徑 5 6 7 def join(png1, png2, size): 8 img1, img2 = Image.open(png1), Image.open(png2) 9 size1, size2 = img1.size, img2.size # 獲取兩張圖片的大小 10 joint = Image.new('RGB', (size1[0], size1[1] + size2[1] - size)) 11 # 新建一張新的圖片 12 # 因為拼接的圖片的寬都是一樣,所以寬為固定值 13 # 高為兩張圖片的高相加再減去需要縮進的部分 14 loc1, loc2 = (0, 0), (0, size1[1] - size) 15 # 兩張圖片的位置 16 # a------------- 17 # | | 18 # | | 19 # | | 20 # | | 21 # | | 22 # b------------| 23 # | | 24 # | | 25 # | | 26 # | | 27 # |------------| 28 29 # 位置都是以該圖片的左上角的坐標決定 30 # 第一張圖片的左上角為a點,a的坐標為(0,0) 31 # 第二張圖片的左上角為b點,a的橫坐標為0,縱坐標為第一張圖片的縱坐標減去第二張圖片上移的size: (0, size[1]-size) 32 33 joint.paste(img2, loc2) 34 joint.paste(img1, loc1) 35 # 因為需要讓第一張圖片放置在圖層的最上面,所以讓第一張圖片最后最后附着上圖片上 36 joint.save(result) 37 38 39 def start(items, size, first_path=None): 40 # 當first為None時,默認將第一張圖片設置為圖片列表的第一張圖片,第二張圖片設置為圖片列表的第二張 41 # 當這兩張圖片合成后,將圖片列表的已經合成的圖片元素移除 42 # 然后將合成的圖片設置為第一張圖片,將剩余的沒有合成的圖片列表繼續操作 43 # 當first_path不為None,將第一張圖片設置為first_path,第二張圖片設置為傳進來的列表的第一個元素 44 # 合成之后,將剛剛使用的列表的元素刪除 45 # 最后遞歸函數,知道列表為空 46 try: 47 if not first_path: 48 path1, path2 = items[0], items[1] 49 join(path1, path2, size) 50 items.remove(path1) 51 items.remove(path2) 52 return start(items, size, first_path=result) 53 else: 54 path2 = items[0] 55 join(first_path, path2, size) 56 items.remove(path2) 57 return start(items, size, first_path=result) 58 except: 59 pass 60 61 62 path = '/root/lambda/' # 圖片文件夾路徑 63 64 65 def getAllImg(path): 66 result = [] 67 filelist = os.listdir(path) 68 for file in filelist: 69 if os.path.isfile(os.path.join(path, file)): 70 if file.split('.')[1] in ('jpg', 'png'): 71 result.append(os.path.join(path, file)) 72 return result 73 74 75 if __name__ == '__main__': 76 s = getAllImg(path) 77 s.sort() 78 start(s, 100) 79 print('最后圖片尺寸--->', Image.open(result).size)
