最近幾個月,毒教材被曝光引發爭議,那些編寫度教材的人著實可惡。咱程式員也沒有手繪插畫能力,但咱可以藉助強大的深度學習模型將視頻轉動漫。所以今天的目標是讓任何具有python語言基本能力的程式員,實現短視頻轉動漫效果。 效果展示 一、思路流程 讀取視頻幀 將每一幀圖像轉為動漫幀 將轉換後的動漫幀轉為視 ...
最近幾個月,毒教材被曝光引發爭議,那些編寫度教材的人著實可惡。咱程式員也沒有手繪插畫能力,但咱可以藉助強大的深度學習模型將視頻轉動漫。所以今天的目標是讓任何具有python語言基本能力的程式員,實現短視頻轉動漫效果。
效果展示
一、思路流程
- 讀取視頻幀
- 將每一幀圖像轉為動漫幀
- 將轉換後的動漫幀轉為視頻
難點在於如何將圖像轉為動漫效果。這裡我們使用基於深度學習的動漫效果轉換模型,考慮到許多讀者對這塊不瞭解,因此我這邊準備好了源碼和模型,直接調用即可。不想看文章細節的可以直接拖到文章末尾,獲取源碼。
二、圖像轉動漫
為了讓大家不關心深度學習模型,已經為大家準備好了轉換後的onnx類型模型。接下來按順序介紹運行onnx模型流程。
安裝onnxruntime庫
pip install onnxruntime # 源碼及Python資料教程、電子書領取群 279199867
如果想要用GPU加速,可以安裝GPU版本的onnxruntime:
pip install onnxruntime-gpu
需要註意的是:
onnxruntime-gpu的版本跟CUDA有關聯,具體對應關係如下:
當然,如果用CPU運行,那就不需要考慮那麼多了。考慮到通用性,本文全部以CPU版本onnxruntime。
運行模型
先導入onnxruntime庫,創建InferenceSession對象,調用run函數。
如下所示
import onnxruntime as rt sess = rt.InferenceSession(MODEL_PATH) inp_name = sess.get_inputs()[0].name out = sess.run(None, {inp_name: inp_image})
具體到我們這裡的動漫效果,實現細節如下:
import cv2 import numpy as np import onnxruntime as rt # MODEL = "models/anime_1.onnx" MODEL = "models/anime_2.onnx" sess = rt.InferenceSession(MODEL) inp_name = sess.get_inputs()[0].name def infer(rgb): rgb = np.expand_dims(rgb, 0) rgb = rgb * 2.0 / 255.0 - 1 rgb = rgb.astype(np.float32) out = sess.run(None, {inp_name: rgb}) out = out[0][0] out = (out+1)/2*255 out = np.clip(out, 0, 255).astype(np.uint8) return out def preprocess(rgb): pad_w = 0 pad_h = 0 h,w,__ = rgb.shape N = 2**3 if h%N!=0: pad_h=(h//N+1)*N-h if w%2!=0: pad_w=(w//N+1)*N-w # print(pad_w, pad_h, w, h) rgb = np.pad(rgb, ((0,pad_h),(0, pad_w),(0,0)), "reflect") return rgb, pad_w, pad_h
其中, preprocess函數確保輸入圖像的寬高是8的整數倍。這裡主要是因為考慮到深度學習模型有下採樣,確保每次下採樣能被2整除。
單幀效果展示
三、視頻幀讀取與視頻幀寫入
這裡使用Opencv庫,提取視頻中每一幀並調用回調函數將視頻幀回傳。在將圖片轉視頻過程中,通過定義VideoWriter類型變數WRITE確保唯一性。具體實現代碼如下:
import cv2 from tqdm import tqdm WRITER = None def write_frame(frame, out_path, fps=30): global WRITER if WRITER is None: size = frame.shape[0:2][::-1] WRITER = cv2.VideoWriter( out_path, cv2.VideoWriter_fourcc(*'mp4v'), # 編碼器 fps, size) WRITER.write(frame) def extract_frames(video_path, callback): video = cv2.VideoCapture(video_path) num_frames = int(video.get(cv2.CAP_PROP_FRAME_COUNT)) for _ in tqdm(range(num_frames)): _, frame = video.read() if frame is not None: callback(frame) else: break
完整源碼獲取點擊 藍色字體 獲取喲~
給大家推薦一套爬蟲教程,涵蓋常見大部分案例,非常實用!
代碼總是學完就忘記?100個爬蟲實戰項目!讓你沉迷學習丨學以致用丨下一個Python大神就是你!