來得瑟一下!用Python做一個縮放自如的聖誕老人

2021-02-19 菜鳥學Python

聖誕節又要到了,雖說我們中國人不提倡過西方的節日,但是商家們還是很喜歡的,估計有對象的男孩紙女孩紙們也很喜歡吧

今天的主題是為大家展示如何用python做一個不斷變大的聖誕老人,就像西遊記中能夠隨意變幻大小的神仙妖怪那樣,算是送給大家的小禮物,先上個圖吧!

不要心急,盯著圖片看5秒


思路要點:

通過縮放獲取等比大小的一組圖片

將上述圖片疊加到固定大小的底圖中

按順序組合圖片生成動圖



圖片縮放


本篇文章的大部分工作都是基於opencv實現,而opencv進行圖片縮放是極其容易的,不過這次我們要生成的是一組等比縮放的圖片,所以在cv2.resize方法的使用上可能跟以往略有出入,先來看函數原型:


cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])


其中src是原圖片,dsize是目標圖片大小,當dsize為0的時候,我們就可以通過fx和fy兩個參數來分別設置水平軸和垂直軸方向的縮放比例了。這樣說可能有些抽象,我們舉個例子來說明:

for i in range(1, 40, 1):
  img = cv2.resize(image, (0, 0), fx=i/30, fy=i/30)
  cv2.imwrite(str(i)+'.png', img)


運行上面這段代碼會生成39張不同比例的圖片,目標圖片的大小由縮放比例fx和fy來控制,最小的一幅圖邊長是原圖的1/30,最大的圖片邊長是原圖的1.3倍(下圖):

既然等比縮放的圖片有了,是不是可以選定一個坐標原點,直接合成動圖呢?答案是不行,因為常規的動圖生成方法要求素材圖片必須是相同的尺寸(像素),下面我們就來著重解決這一問題。


底圖疊加

python中實現兩幅圖片疊加的辦法有很多,但是他們都存在缺陷——要麼疊加的圖片必須是相同大小,要麼難以控制圖片疊加的具體位置。對此,小編採取的辦法是在兩幅圖之間進行「像素級」的替換。


1).生成底圖

待疊加的圖片中,上層圖片就使用剛才獲取到的一系列等比縮放圖,下層圖片我們就生成一張固定大小的空白圖片。需要注意,這裡生成的空白圖片必須大於最大的一幅縮放圖。

生成空白底圖分兩步完成,第一步生成固定大小(垂直軸和水平軸的長度)的二維數組;第二步使用cv2.cvtColor進行顏色空間變換。代碼如下:


blank = np.ones((blankh, blankw), dtype=np.uint8) * 255
ret = cv2.cvtColor(blank, cv2.COLOR_GRAY2BGR)


其實上面代碼中的ret本質上是一個三維數組,我們可以把它列印出來查看(下圖),但是通過cv2.imshow方法展示出來就是一張空白圖片了。這其中涉及一些較為底層的內容,大家了解就好,文中不再贅述。

2).像素替換

正如剛才所說,opencv中的一幅圖其實是一個三維數組,其實也可以把它看作是二維數組,數組中的

每個元素是形如 [255, 255, 255] 的列表,其中存放的是圖片每個像素的顏色參數。也就是說,如果我們想實現一幅圖片疊加到另一幅圖片這樣的視覺效果,可以對被疊加圖片對應位置的

像素進行替換賦值。代碼形式如下圖所示,其中i和j分別為圖片在垂直方向和水平方向的坐標。


ret[i, j, 0] = image[i, j, 0]
ret[i, j, 1] = image[i, j, 1]
ret[i, j, 2] = image[i, j, 2]


對一幅圖片而言,坐標原點是在左上角(下圖所示)。此外,為了保證最終得到動圖的效果,不能簡單的將圖片以坐標原點為基準進行疊加,最好的辦法是把疊加原點設在底圖下邊緣的中心位置。


原理搞清楚後就可以開始圖片疊加操作了,在此期間需要進行一些像素對應位置的計算,雖然稍微有點繞但是並不複雜,詳細的轉化公式就不寫了,我們直接看代碼:

上面代碼中的image是已經縮放完畢的聖誕老人圖片,blankh和blankw分別是空白圖片的高度和寬度,這個尺寸可以根據需求自行設置。

下圖展示的是一幅縮放比例1/2左右的圖片和底圖疊加後的效果,為了觀察方便,我給圖片加了一個邊框。


生成動圖

之前我們已經解決了單幅圖片與底圖的疊加,為了準備合成動圖所需素材,還要對多個等比縮放的圖片進行底圖疊加操作。縮放比例間隔越小、準備的圖片素材越多,生成的動圖也就越平滑。

當然,動圖的效果如何還要綜合考慮多個因素,這裡小編還是採用39幅圖片組合動圖。其中最小的圖形高度是原圖的1/30,最大的圖形高度是原圖的1.3倍。與底圖疊加後的圖片就是下面這個樣子。

下面來說說動圖的合成,將多個相同尺寸的圖片合成動圖可以使用imageio這個庫來實現,核心代碼只有一條:


imageio.mimwrite('目標文件名稱.gif', gifList, duration=0.15)


其中第一個參數是git目標文件名稱;gifList是一組列待合成的圖片,也就是上面圖片中展示的那些;最後一個參數duration表示畫面切換間隔,單位為秒。

現在通過下面這段代碼進行動圖合成。


file_path = 'pic'
imgList = os.listdir(file_path)
imgList = ['pic/'+img for img in imgList]
gifList = [imageio.imread(img) for img in imgList]
imageio.mimwrite('gif.gif', gifList, duration=0.15)


來看合成後的動圖效果(下圖),仔細看看好像有點問題,怎麼圖中的聖誕老人忽大忽小?這跟我們預想的不一樣啊。

其實這個問題是出在合成圖片的順序上,我們嘗試列印上面代碼中的imgList變量,結果如下:

可以看到,素材圖片並不是按照我們預想的順序排序。這在python的文件處理中也算是個比較常見的問題,解決方案之一是可以按照圖片的創建時間排序,具體操作是在上面的第二行代碼之後插入一條語句:


imgList = sorted(imgList,key=lambda x: os.path.getmtime(os.path.join(file_path, x)))


現在再次進行動圖合成,就可以實現文章開頭的效果了。

當然了,這種動圖製作方法不僅限於聖誕老人,任何圖片理論上都是可以的。比如說,我們還可以做一棵不斷長大的聖誕樹

看下面的視頻,一睹為快

趣味遊戲文章:

太好玩了!用Python寫個彈球遊戲2.0

巧妙的Python數據結構玩法|實戰德州撲克

手把手教你,菜鳥也能用Python寫一個2048遊戲

用Python做個美少女大戰小怪獸

強烈推薦,用Python輕鬆打造定製款《植物大戰殭屍》

Python心得和技巧:

零基礎學了8個月的Python,到底有啥感悟

我珍藏的一些好的Python代碼,技巧

菜鳥寫Python程序,如何從新手變老手

菜鳥必收藏,13個Python慣用小技巧

相關焦點

  • 用Python做一個哆來A夢分身
    今天Python來實現一個簡單的哆啦A夢分身術,看看python是如何實現影分身之術。01.技術設計要達到影分身的效果,需要一個背景圖片和一個前景圖片。我們以背景圖片為基礎,然後不斷的在背景圖片上添加前景圖片,從而達到影分身的效果。
  • 如何用 Python 寫一個安卓 APP ?
    22點24分準時推送,第一時間送達  編輯:技術君 | 來源:youerning  上一篇:  正文  前言  用 Python 寫安卓 APP 肯定不是最好的選擇,目前用Java和 kotlin
  • python能做什麼
    python能做什麼?書聲琅琅Python培訓老師介紹,最近許多的朋友諮詢,聽說python很火,甚至可以超越JAVA,因此很想學這個python,但是不知道python能做什麼,能完成一些什麼項目呢?針對這個問題,今天徐老師跟大家來聊一聊python能做什麼的話題。
  • 平安夜聖誕創意料理,義大利麵,聖誕老人湯,在家輕鬆做
    平安夜義大利麵&聖誕老人湯/耶誕創意料理聖誕節想自己在家來點不一樣的嗎發揮一點小小的創意就能使餐點帶來節慶應有的氣氛使的食物也變的可口美好的同時視覺上也很療愈整個氛圍都沉浸在歡樂的耶誕夜裡湯碗裡的聖誕老人是否讓你捨不得喝他呢
  • 利用python做串口通訊上位機
    畢竟,一個USB轉串口工具,淘寶網上只要幾十塊就可以買一個,而LIN總線或CAN總線轉換接口,成本至少在幾百元以上。要實現上位機和ECU之間的串口通訊,除了一個USB轉串口硬體工具以外,還需要一個上位機軟體。
  • 今年聖誕老人又要來我家了!
    在小朋友2歲的時候給他讀了本《特別的聖誕節》,他知道除了他的生日,還有一個聖誕節,同樣可以得到禮物,不同的是這是一個從來沒有見過面的老爺爺給的。從那時候起,每年的25號聖誕老公公也會光顧我們家了。如何讓他過一個難忘的聖誕節呢?
  • 聖誕節,聖誕老人生日蛋糕的製作方法,用淡奶油做口感更好吃
    歡迎來到峰哥美食自媒體,聖誕節越來越近了,過聖誕節怎麼能少了聖誕老人生日蛋糕呢,今天峰哥就朋友們分享聖誕老人生日蛋糕的做法,製作也非常簡單,就是抹面的時候對於新手來說有一點點難度,如果是自己吃的話就沒有那麼多講究,只要能抹上去就行。
  • 聖誕老人撲朔迷離的身世
    尼古拉斯最喜歡在暗中幫助別人,聖誕老人是他後來的別號,這個名字出自他暗自送金子,幫助三個女孩子的故事。 據說在尼古拉斯家不遠處,住著三個美麗的少女。她們的父親是一位清寒的學者,經常靠借貸過日子。因為沒有能力還債,父親只好狠心把美麗的三個女兒賣給債主,帶到非洲去做女僕人。三個女兒知道了這件事前,便擁抱在一起傷心的痛哭著。
  • 5個無聊Python程序,用Python整蠱你的朋友們吧
    來源:https://dream.blog.csdn.net/Python 能做很多無聊,但有意思的事情,例如接下來的一些案例
  • 糖豆人終極淘汰賽聖誕老人怎麼獲得 糖豆人聖誕老人皮膚獲取方法
    糖豆人終極淘汰賽聖誕老人怎麼獲得?糖豆人的一大特色就是這種皮膚外觀了,而官方也經常會送一些皮膚獎勵。最近聖誕節到了,最新皮膚當然就是聖誕老人了。那我這個皮膚的獲取方法是什麼呢?下面小編來給大家介紹具體內容。糖豆人終極淘汰賽聖誕老人怎麼獲得聖誕老人皮膚是免費贈送的,只要玩家在活動期間登錄遊戲即可。
  • 如何用PYTHON代碼寫出音樂
    我一直在做這樣的嘗試,就是通過人工智慧算法實現機器自動的作詞和編曲(在這裡預告下,通過深度學習寫歌詞已經實現了,之後會分享給大家),本文我們主要聊下如何寫曲。說到用代碼寫曲子,有一個東西大家一定要了解就是MIDI。MIDI是一種樂器數字接口,是編曲界最廣泛的音樂標準格式。MIDI並不是真正意義上的音樂文件,大家可以把它理解成樂譜,需要有環境編譯MIDI文件,才可以生成音樂。
  • 曾經綠過的聖誕老人
    一個紅衣服、白鬍子,背著禮物駕著雪橇的胖老頭,相信大家都不陌生。但聖誕老人的形象其實並不是一直都這樣。第一個起源是真實的人物,4世紀米拉城的大主教聖尼古拉斯(Saint Nicholas),他生活在呂基亞,也就是現在的土耳其。如今聖誕節時,孩子們把長筒襪掛在壁爐旁,相信聖誕老人會用禮物塞滿襪子,這個傳統也源自於聖尼古拉斯。
  • 畫一畫,剪一剪,DIY一個聖誕老人筆筒
    當然是我們慈祥的聖誕老人啦!說幹就幹,畫一畫,剪一剪,DIY一個聖誕老人筆筒,創意無處不在也算廢物利用啦!【準備材料】硬紙板、筆、橡皮擦、剪刀、毛線、膠水、紙筒。【步驟】取一張硬紙板,先畫聖誕老人的帽子,有帽身、帽沿和帽子小圓球裝飾。在畫好的聖誕帽子下面畫大大的波浪鬍子。
  • 初學者如何用「python爬蟲」技術抓取網頁數據?
    在當今社會,網際網路上充斥著許多有用的數據。我們只需要耐心觀察並添加一些技術手段即可獲得大量有價值的數據。而這裡的「技術手段」就是指網絡爬蟲。 今天,小編將與您分享一個爬蟲的基本知識和入門教程:什麼是爬蟲?網絡爬蟲,也叫作網絡數據採集,是指通過編程從Web伺服器請求數據(HTML表單),然後解析HTML以提取所需的數據。
  • Merry Christmas (聖誕老人由來+聖誕歌曲+動畫)
    也許這個傳說帶了點宗教色彩,但聖誕老人給孩子們送禮物這事卻很美好,因為只有好孩子good boys and good girls才會收到禮物哦,這是鼓勵孩子的一個很好的方式!我們今年用了下圖版本給聖誕老人寫信,孩子們都好認真地完成!(下圖中的naughty下面有括弧but I can explain真的很好笑)
  • 探尋聖誕老人故鄉 · 芬蘭聖誕老人村
    都系爸爸媽媽為左哄小朋友開心嘅一個謊言d禮物都系爸爸媽媽塞入去噶其實小朋友系聖誕節收穫嘅系爸爸媽媽對孩子嘅愛今日我想介紹嘅地方同聖誕老人有關就系聖誕老人村啦~聖誕老人村其實好似一個小型主題樂園系一組以聖誕老人為主題嘅特色木質建築群白雪覆蓋下嘅聖誕老人村好似童話入邊嘅仙境咁靜謐而安寧每年黎呢度嘅人都唔少噶大家都係為左一睹聖誕老人嘅風採
  • 香港聖誕老人有什麼聖誕願望,你一定想不到
    另外,港產聖誕老人還有一個「獨有優勢」——兼職做財神。香港剛經歷了125年來最熱的平安夜,溫度達到了攝氏24.7度,午間甚至到了27、28度。在這個南半球風格的聖誕裡,抹一把汗後又要忍不住偷抹一把淚的,要數香港的聖誕老人們了。
  • 想做獨屬於你的聖誕老人
    在我大二的時候,就親眼見過聖誕老人。那天夜裡,他沒有駕著馴鹿雪橇送禮物,而是很拉風的騎著一輛電動車。當我把這事說給男友時,他一個勁兒的點頭,還安慰我,只有善良的人才能看到聖誕老公公。我捧著他的臉,吧唧就親了一口。
  • 10部小確幸聖誕電影:聖誕老人也有翻車的時候
    他一到美國,就一頭扎進酒吧,他獨有的英倫魅力一下就吸引了一個美國辣妹的注意。沒過一會兒,又來了另外兩位辣妹,三人邀請單身漢回家過聖誕,正當四人準備做妙不可言的事時,最性感的第四個女孩也回家了,你猜會發生什麼?只能說單身漢的豔福還真不淺啊!
  • 聖誕將至,聖誕老人的由來~~~
    雖然沒有人真的見過神秘人的樣子,但是人們通常裝扮成頭戴紅色聖誕帽子,大大的白色鬍子,一身紅色棉衣,腳穿紅色靴子的樣子。因為總在聖誕節前夜出現派發禮物,所以習慣地稱他為"聖誕老人"。從前有一個老人,名叫尼古拉斯,他一生最愛幫助貧窮的人家。其中有一次他幫助三個貧窮的少後送他們三袋金子以逃過被賣的不幸。當尼古拉斯偷偷把其中一袋金子送給其中一名女子時,他把金子從其中一個窗戶扔進去,恰好掉進景在壁上的一長襪中。