有錢能夠隨心所欲
的經典gif,因此我心血來潮想作一個本身的東北黑中介
版的隨心所欲
gif。原本我想找一個沒有文字的gif,而後找一個軟件添加文字,而後合成gif的。結果在網上搜索了一下,沒有找到合適的原版gif,只找到了一個有文字的gif。到是有軟件能夠手動添加文字合成gif的,可是若是要首先把原來的文字去除,而後再一點點添加,手動要作大量的工做,非常麻煩。我再嘗試了半個小時還沒弄好就放棄了(可是我想應該有比較簡便的方法,只是我懶得再本身去找了)。最後我想既然做爲一個程序員,能不能經過代碼去實現這個功能呢?固然能夠啦。我最熟悉的是python,天然優先考慮上python了。以前接觸過PIL這個庫,我記得它有給圖片添加文字的功能,並且最近不是纔剛剛看了moviepy這個庫,它能夠很容易合成gif,把這兩個結合到一塊兒不就很容易實現我想要的目標了嗎?一不作二不休,開搞!若是你的電腦已經安裝了ffmpeg的話,那麼將gif分割成單幀的序列圖片是很是容易的,運行下面的命令:python
ffmpeg -i 隨心所欲.gif %d.jpg
就能夠將隨心所欲.gif
分割成1.jpg,2.jpg,...。固然你也能夠直接使用python的PIL庫來處理gif,使用以下的代碼便可:程序員
from PIL import Image,ImageSequence gif = Image.open("隨心所欲.gif") for i,frame in enumerate(ImageSequence.Iterator(gif),1): frame.save("%d.jpg" % i)
或者你也可使用以前介紹過的moviepy庫(具體能夠參考我以前的一篇博客),若是你對opencv比較熟悉的話,天然也可使用opencv來處理。這裏就不詳細說了。
獲得gif的幀序列圖像以後,簡單來講一下後面處理的思路。由於原來的gif有些幀是有文字的,咱們要想添加本身的文字,就必需要把原來的文字去除掉,而後換成本身的。因此後面基本的思路就是:shell
具體實現代碼以下:函數
# -*- coding:utf-8 -*- import matplotlib.pyplot as plt from PIL import Image,ImageDraw,ImageFont from scipy.misc import imread,imsave,imresize import numpy as np import os from glob import glob from moviepy.editor import ImageSequenceClip # 消除文字的圖片序號 modify_img_index = list(range(11,14))+list(range(27,37)) + list(range(44,61)) + list(range(62,81)) \ + list(range(82,94)) + list(range(97,106)) + list(range(112,132)) + list(range(146,168)) text_info = [('好啊',(120,140))]*(14-11) + \ [('就算你今天找人來抗議',(40,140))]*(37-27) + \ [('就算你的理由再完美',(50,140))] *(61-44) + \ [('我想不退錢就不退錢',(50,140))] *(81-62) + \ [('畢竟我是東北黑中介',(50,140))] *(94-82) + \ [('東北黑中介了不得啊',(50,140))] *(106-97) + \ [('sorry,東北黑中介真的能夠隨心所欲',(5,140))]*(132-112) + \ [('之後讓他每天鬧',(60,140))]*(158-146) + \ [('每天鬧',(110,140))]*(169-158) index_to_text = dict(zip(modify_img_index,text_info)) # 保存圖片文件夾 save_dir = "output" if not os.path.exists(save_dir): os.mkdir(save_dir) new_color = np.array([50,50,50]) # 消除文字以後的顏色 fontsize = 18 fontcolor = (0,255,255) fps = 10 resize_scale = 1.5 # 新圖的寬和高是原來的多少倍 # 消除文字的x,y邊界座標 y_begin = 10 y_end = 280 x_begin = 140 x_end = 160 # 所有文件列表(無序) img_names = glob("*.jpg") #print(img_names) def modify(): # 遍歷每個圖像 for img_name in img_names: img = imread(img_name) h,w = img.shape[0],img.shape[1] #plt.imshow(img) img_new = np.copy(img) index = int(img_name.split(".")[0]) # 若是圖片有文字,須要修改 if index in modify_img_index: # 消除文字 img_new[x_begin:x_end,y_begin:y_end] = new_color text,pos = index_to_text[index] img_new = drawtext(Image.fromarray(img_new),text,pos,fontsize,fontcolor) #保存新的圖片 # imsave(os.path.join(save_dir,img_name),img_new) if resize_scale != 1: # resize img_new = img_new.resize((int(w*resize_scale),int(h*resize_scale))) img_new.save(os.path.join(save_dir,img_name)) print("Modify and save %s!" % img_name) else: # 沒有文字,不須要修改,直接保存原來的圖片 if resize_scale != 1: img = imresize(img,resize_scale) imsave(os.path.join(save_dir,img_name),img) print("Save %s!" % img_name) def drawtext(img,text,pos,fontsize,fontcolor): ''' draw text for img @param img:image to draw text @param text:text to draw @param pos:where to draw the text((x,y)) @param fontsize: font size @param fontcolor: font color ''' font = ImageFont.truetype("simsun.ttc",fontsize) draw = ImageDraw.Draw(img) draw.text(pos,text,fontcolor,font = font) # plt.imshow(img) # plt.show() return img def test_drawtext(): img_name = "4.jpg" img = Image.open(img_name) #text = "好啊" text = "東北黑中介了不得啊" pos = (40,140) fontsize = 20 fontcolor = (0,255,255) drawtext(img,text,pos,fontsize,fontcolor) # 利用圖像序列生成gif def generate_gif(img_names,save_path,fps = 10): # img_names:list of image names clip = ImageSequenceClip(img_names,fps = fps) clip.write_gif(save_path) print("Write %s successfully!" % save_path) # 主函數 def main(): modify() save_gif_path = os.path.join(save_dir,"東北黑中介.gif") img_names = sorted(glob(os.path.join(save_dir,"*.jpg")),key = lambda x: int(x.split(".")[0].split("/")[1])) generate_gif(img_names,save_gif_path,fps) #test_drawtext() if __name__ == '__main__': main()
上面的代碼思路其實仍是比較清楚的。主要麻煩的地方就在於,咱們無法自動確認哪些幀出現了文字,因此在這裏我採用手動觀察圖像(有167張圖)的方式,肯定了出現文字的幀序列區間;而後對於這些幀序列區間,其文字替換成我本身的文字。還有一個問題就是,我要消除文字,就要知道文字的位置,其實這個能夠歸結爲一個目標檢測的問題,或者說是一個OCR問題(OCR的第一步,定位文字),可是OCR作起來仍是很麻煩的,這裏暫時不說,後面有空我會專門討論OCR問題。這裏比較好的地方在於,全部的文字出現的高度位置幾乎是同樣的,只是寬度方向的位置不同(有的字多,有的字少),這裏我仍是採用手動觀察標註的辦法,能夠藉助於matplotlib顯示圖像,用鼠標點擊圖像的某一點,它會顯示該點的(x,y)座標和像素值,這樣咱們就能夠手動肯定要消除的文字的位置,以及消除文字要填充的顏色了。按照這個思路,咱們能夠獲得一些消除原來文字,添加新文字以後的圖像以下圖2所示:
code