<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
之前經常在網上看到那種由一個個字元構成的視訊,非常炫酷。一直不懂是怎麼做的,這兩天研究了一下,發現並不難。
先來看一個最終效果(如果模糊的話,點選下方連結看高清版):
https://pan.baidu.com/s/1DvedXlDZ4dgHKLogdULogg 提取碼:1234
簡單來說,要將一個彩色的視訊變成字元畫出來的黑白視訊,用下面幾步就能搞定:
完整的程式碼我放在文章末尾了,直接執行python3 video2char.py即可。程式會要求你輸入視訊的本地路徑和轉變後的清晰度(0最模糊,1最清晰。當然越清晰,轉變越慢)。
執行程式碼的話需要用到tqdm、opencv_python、moviepy等幾個庫,首先得pip3 install確保它們都有了。
這裡面最關鍵的步驟就是如何將一幀彩色影象轉變為黑白的字元影象,如下圖所示:
從青蛙公主視訊抽幀出來的
用字元畫出來的
而轉變的原理其實很簡單。首先因為一個字元畫在影象裡會佔據很大一個畫素塊,所以必須先對彩色影象進行壓縮,連續的一個畫素塊可以合併,這個壓縮過程就是opencv的resize操作。
然後將壓縮後的畫素點轉變為黑白畫素點,並轉變為對應的字元。字元的話我這裡採用的是下面的字串,從黑到白,經過我的實踐這一組是效果最好的:
"#8XOHLTI)i=+;:,. "
接著就需要將轉變後的字元畫到新的畫布上去,需要注意的點是排布得均勻緊湊了,畫布四周最好不要有太多多餘的空白。
最後把所有的字元影象合併成視訊就行了,但是合併後是沒有聲音的,需要用moviepy庫把原視訊的聲音匯入過來。
import os import re import shutil from tqdm import trange, tqdm import cv2 from PIL import Image, ImageFont, ImageDraw from moviepy.editor import VideoFileClip class V2Char: font_path = "Arial.ttf" ascii_char = "#8XOHLTI)i=+;:,. " def __init__(self, video_path, clarity): self.video_path = video_path self.clarity = clarity def video2str(self): def convert(img): if img.shape[0] > self.text_size[1] or img.shape[1] > self.text_size[0]: img = cv2.resize(img, self.text_size, interpolation=cv2.INTER_NEAREST) ascii_frame = "" for i in range(img.shape[0]): for j in range(img.shape[1]): ascii_frame += self.ascii_char[ int(img[i, j] / 256 * len(self.ascii_char)) ] return ascii_frame print("正在將原視訊轉為字元...") self.char_video = [] cap = cv2.VideoCapture(self.video_path) self.fps = cap.get(cv2.CAP_PROP_FPS) self.nframe = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) self.raw_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) self.raw_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) font_size = int(25 - 20 * max(min(float(self.clarity), 1), 0)) self.font = ImageFont.truetype(self.font_path, font_size) self.char_width, self.char_height = max( [self.font.getsize(c) for c in self.ascii_char] ) self.text_size = ( int(self.raw_width / self.char_width), int(self.raw_height / self.char_height), ) for _ in trange(self.nframe): raw_frame = cv2.cvtColor(cap.read()[1], cv2.COLOR_BGR2GRAY) frame = convert(raw_frame) self.char_video.append(frame) cap.release() def str2fig(self): print("正在生成字元影象...") col, row = self.text_size catalog = self.video_path.split(".")[0] if not os.path.exists(catalog): os.makedirs(catalog) blank_width = int((self.raw_width - self.text_size[0] * self.char_width) / 2) blank_height = int((self.raw_height - self.text_size[1] * self.char_height) / 2) for p_id in trange(len(self.char_video)): strs = [self.char_video[p_id][i * col : (i + 1) * col] for i in range(row)] im = Image.new("RGB", (self.raw_width, self.raw_height), (255, 255, 255)) dr = ImageDraw.Draw(im) for i, str in enumerate(strs): for j in range(len(str)): dr.text( ( blank_width + j * self.char_width, blank_height + i * self.char_height, ), str[j], font=self.font, fill="#000000", ) im.save(catalog + r"/pic_{}.jpg".format(p_id)) def jpg2video(self): print("正在將字元影象合成字元視訊...") catalog = self.video_path.split(".")[0] images = os.listdir(catalog) images.sort(key=lambda x: int(re.findall(r"d+", x)[0])) im = Image.open(catalog + "/" + images[0]) fourcc = cv2.VideoWriter_fourcc("m", "p", "4", "v") savedname = catalog.split("/")[-1] vw = cv2.VideoWriter(savedname + "_tmp.mp4", fourcc, self.fps, im.size) for image in tqdm(images): frame = cv2.imread(catalog + "/" + image) vw.write(frame) vw.release() shutil.rmtree(catalog) def merge_audio(self): print("正在將音訊合成到字元視訊中...") raw_video = VideoFileClip(self.video_path) char_video = VideoFileClip(self.video_path.split(".")[0] + "_tmp.mp4") audio = raw_video.audio video = char_video.set_audio(audio) video.write_videofile( self.video_path.split(".")[0] + f"_{self.clarity}.mp4", codec="libx264", audio_codec="aac", ) os.remove(self.video_path.split(".")[0] + "_tmp.mp4") def gen_video(self): self.video2str() self.str2fig() self.jpg2video() self.merge_audio() if __name__ == "__main__": video_path = input("輸入視訊檔路徑:n") clarity = input("輸入清晰度(0~1, 直接回車使用預設值0):n") or 0 v2char = V2Char(video_path, clarity) v2char.gen_video()
以上就是用Python字元畫出了一個谷愛凌的詳細內容,更多關於Python字元畫的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45