列表生成式版圖片拼接——知乎是喵多還是汪多系列
在回答這個問題的時候——用狗的照片當頭像是否比用貓的照片當頭像的人多?為什麼? - 知乎,為了突破5M的圖片上傳限制,我寫了個圖片拼接的腳本,方便將所有結果拼接成小於5M的圖片上傳,圖片路徑是vision文件夾下的相應名字的文件。
將這段腳本放上來是因為整個腳本都是用列表生成式寫的,寫完之後有點蒙蔽,不知道這種方式到底是讓程序可讀性增強了還是減弱了○| ̄|_
代碼見文末代碼清單,簡單介紹下列表生成式。
- 各種生成式匯總
需要注意的是set生成式是大括弧,而生成器是用小括弧,dict生成式中需要用冒號。
[i for i in l]# list comprehension[i for i in l if i > 0] #list comprehension if {k: v for k,v in d}# dict comprehension(i for i in l)# generator comprehension{i for i in l}# set comprehension
- 可讀性建議
- 將生成式的功能作為其賦值的變數的變數名。
- 如果有過長的表達式,應該提取出來,避免超過單句長度限制。
- 並避免嵌套生成器。
- 小tips
- 如果是用pycharm,可以按下CTRL+J體驗一下列表生成式的模板,可自動識別當前可迭代對象,請用pycharm的務必要試一試,幸福感爆炸,見下圖。
- 生成器的作用是為了替代python中的函數式工具(偽)——map、filter,可見生成式+if表達式是比較完美的替代了這兩個函數,這也解釋了為什麼生成式中的if表達式不支持else。
- 圖片處理部分用的是opencv的cv2,圖像處理本質上是矩陣的處理,所以不僅是圖像處理,cv2裡面有幾個函數搭配numpy食用的效果也蠻不錯的,比如cv2.bitwise_not系列、cv2.absdiff等。numpy中除了腳本中用到的np.column_stack和np.row_stack,還有np.flatten、np.concatenate等操作也常常能出奇制勝。
- 代碼清單
#coding:utf-8import cv2import numpy as npimport osPATH = vision\{}\def get_animals_ranged_list(animal, maxlength = -1): u"""從animal路徑中獲取maxlenght個圖片並用cv2讀取, 給每張圖片標上ID,並刪選出size錯誤的圖像。""" img_in_path = [x[:-3] for x in os.listdir(PATH.format(animal))][:maxlength] print img numbers, len(img_in_path) cats_list = [(cv2.imread(PATH.format(animal) + x + jpg),x) for x in img_in_path] text_parameter = (cv2.FONT_HERSHEY_TRIPLEX, 0.5, (255, 255, 255), 1, False) put_id = [cv2.putText(x,name , (10, 100), *text_parameter) for x, name in cats_list] return [x for x,name in cats_list if x.shape == (200, 200, 3)] def img_list_to_two_dimesion_for_merge(list_, step = 10): u"""將圖片數組切分成一個二維數組,並將最後一行用空白圖片填滿 最後調用cv2合併圖片""" step_range = range(len(list_))[::step] ranged_list = [list_[x:x+step] for x in step_range] blank = np.ones((200, 200, 3), dtype=np.uint8) * 255 if len(ranged_list[-1]) < step: _ = ranged_list[-1] ranged_list[-1] = _ + [blank]*(step - len(ranged_list[-1])) column_stack = [np.column_stack(x) for x in ranged_list] return np.row_stack(column_stack)def split_img(img, step = 5000): u"""長圖片切段,每個圖片大小小於5M,滿足知乎上傳標準""" length, width, dims = img.shape return [img[x:x + step] for x in range(length)[::step]]def img_line(animal=cat): u"""主函數,生成可上傳知乎答案的長圖片""" img_cats = get_animals_ranged_list(animal) range_cat = img_list_to_two_dimesion_for_merge(img_cats) splited_img = split_img(range_cat) [cv2.imwrite("vision\"+animal+str(i)+.jpg,x) for i,x in enumerate(splited_img)]def desktop(animal): u"""主函數,生成總的圖片用作桌面""" img_cats = get_animals_ranged_list(animal,maxlength = 200) range_cat = img_list_to_two_dimesion_for_merge(img_cats, step=20) cv2.imwrite("vision\all.jpg", range_cat)if __name__ == __main__: # desktop(all) img_line(cat) # img_line(dog)
系列文章緣由:
用狗的照片當頭像是否比用貓的照片當頭像的人多?為什麼? - 知乎系列一:
Google Cloud Platform CLOUD VISION API--知乎是喵多還是汪多
我的知乎專欄:
python雜七雜八的使用經驗 - 知乎專欄推薦閱讀:
※用Python爬取某網站的圖片到本地時遇到了問題,請問如何解決?
※python 爬蟲 圖片抓取問題,有的網站中的圖片不能抓取?
※千里挑一的我乎妹子大V排行榜(數據初探1)
※Python中那些神一樣的代碼
※Python3.6正式版要來了,你期待哪些新特性?