Python繪制1000響大地紅鞭炮動(dòng)態(tài)效果
新年新氣象,今天就用代碼來(lái)制作一個(gè) 動(dòng)態(tài)鞭炮 ,效果如下所示。
動(dòng)態(tài)鞭炮的基本原理是:將一個(gè)錄制好的鞭炮視頻以字符畫(huà)的形式復(fù)現(xiàn),基本步驟是幀采樣 → 逐幀轉(zhuǎn)換為字符畫(huà) → 字符畫(huà)合成視頻。下面開(kāi)始吧!略略略~~~(本作品沒(méi)有聲音,想要聲音的自己的嘴巴自己發(fā)聲······你懂得
1、視頻幀采樣
函數(shù)如下所示,主要功能是將視頻的圖像流逐幀保存到特定的緩存文件夾中(若該文件夾不存在會(huì)自動(dòng)創(chuàng)建)。函數(shù)輸入vp是openCV視頻句柄,輸出number是轉(zhuǎn)換的圖片數(shù)。
def video2Pic(vp): number = 0 if vp.isOpened(): r,frame = vp.read() if not os.path.exists('cachePic'): os.mkdir('cachePic') os.chdir('cachePic') else: r = False while r: number += 1 cv2.imwrite(str(number)+'.jpg',frame) r,frame = vp.read() os.chdir("..") return number
2、將圖片轉(zhuǎn)為字符畫(huà)
2.1 創(chuàng)建像素-字符索引
函數(shù)輸入像素RGBA值,輸出對(duì)應(yīng)的字符碼。其原理是將字符均勻地分布在整個(gè)灰度范圍內(nèi),像素灰度值落在哪個(gè)區(qū)間就對(duì)應(yīng)哪個(gè)字符碼。字符碼可以參考 ASCII碼
ASCII 碼使用指定的7 位或8 位二進(jìn)制數(shù)組合來(lái)表示128 或256 種可能的字符。標(biāo)準(zhǔn)ASCII 碼也叫基礎(chǔ)ASCII碼,使用7 位二進(jìn)制數(shù)(剩下的1位二進(jìn)制為0)來(lái)表示所有的大寫(xiě)和小寫(xiě)字母,數(shù)字0 到9、標(biāo)點(diǎn)符號(hào),以及在美式英語(yǔ)中使用的特殊控制字符。其中:0~31及127(共33個(gè))是控制字符或通信專(zhuān)用字符(其余為可顯示字符),如控制符:LF(換行)、CR(回車(chē))、FF(換頁(yè))、DEL(刪除)、BS(退格)、BEL(響鈴)等;通信專(zhuān)用字符:SOH(文頭)、EOT(文尾)、ACK(確認(rèn))等;ASCII值為8、9、10 和13 分別轉(zhuǎn)換為退格、制表、換行和回車(chē)字符。它們并沒(méi)有特定的圖形顯示,但會(huì)依不同的應(yīng)用程序,而對(duì)文本顯示有不同的影響。
RGBA是代表Red(紅色)、Green(綠色)、Blue(藍(lán)色)和Alpha的色彩空間,Alpha通道一般用作不透明度參數(shù)。如果一個(gè)像素的alpha通道數(shù)值為0%,那它就是完全透明的,而數(shù)值為100%則意味著一個(gè)完全不透明的像素(傳統(tǒng)的數(shù)字圖像)。gray=0.2126 * r + 0.7152 * g + 0.0722 * b是RGB轉(zhuǎn)為灰度值的經(jīng)驗(yàn)公式,人眼對(duì)綠色更敏感。
def color2Char(r,g,b,alpha = 256): imgChar= list("#RMNHQODBWGPZ*@$C&98?32I1>!:-;. ") if alpha: gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) unit = 256 / len(imgChar) return imgChar[int(gray / unit)] else: return ''
2.2 將圖片逐像素轉(zhuǎn)換為字符
img = Image.open(imagePath).convert('RGB').resize((imgWidth, imgHeight),Image.NEAREST) for i in range(imgHeight): for j in range(imgWidth): pixel = img.getpixel((j, i)) color.append((pixel[0],pixel[1],pixel[2])) txt = txt + color2Char(pixel[0], pixel[1], pixel[2], pixel[3]) if len(pixel) == 4 else \ txt + color2Char(pixel[0], pixel[1], pixel[2]) txt += '\n' color.append((255,255,255))
3、將字符圖像合成視頻
def img2Video(vp, number, savePath): videoFourcc = VideoWriter_fourcc(*"MP42") # 設(shè)置視頻編碼器 asciiImgPathList = ['cacheChar' + r'/{}.jpg'.format(i) for i in range(1, number + 1)] asciiImgTemp = Image.open(asciiImgPathList[1]).size videoWritter= VideoWriter(savePath, videoFourcc, vp.get(cv2.CAP_PROP_FPS), asciiImgTemp) for imagePath in asciiImgPathList: videoWritter.write(cv2.imread(imagePath)) videoWritter.release()
4、完整代碼
import cv2 from PIL import Image,ImageFont,ImageDraw import os from cv2 import VideoWriter, VideoWriter_fourcc ''' * @breif: 將像素顏色轉(zhuǎn)換為ASCII字符 * @param[in]: 像素RGBA值 * @retval: 字符 ''' def color2Char(r,g,b,alpha = 256): imgChar = list("#RMNHQODBWGPZ*@$C&98?32I1>!:-;. ") if alpha: gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b) unit = 256 / len(imgChar) return imgChar[int(gray / unit)] else: return '' ''' * @breif: 將視頻逐幀轉(zhuǎn)換為圖片 * @param[in]: vp -> openCV視頻句柄 * @retval: number -> 轉(zhuǎn)換的圖片數(shù) ''' def video2Pic(vp): number = 0 if vp.isOpened(): r,frame = vp.read() if not os.path.exists('cachePic'): os.mkdir('cachePic') os.chdir('cachePic') else: r = False while r: number += 1 cv2.imwrite(str(number)+'.jpg',frame) r,frame = vp.read() os.chdir("..") return number ''' * @breif: 將圖片逐像素轉(zhuǎn)換為ASCII字符 * @param[in]: imagePath -> 圖片路徑 * @param[in]: index -> 圖片索引 * @retval: None ''' def img2Char(imagePath, index): # 初始化 txt, color, font = '', [], ImageFont.load_default().font imgWidth, imgHeight = Image.open(imagePath).size asciiImg = Image.new("RGB",(imgWidth, imgHeight), (255,255,255)) drawPtr = ImageDraw.Draw(asciiImg) imgWidth, imgHeight = int(imgWidth / 6), int(imgHeight / 15) # 對(duì)圖像幀逐像素轉(zhuǎn)化為ASCII字符并記錄RGB值 img = Image.open(imagePath).convert('RGB').resize((imgWidth, imgHeight),Image.NEAREST) for i in range(imgHeight): for j in range(imgWidth): pixel = img.getpixel((j, i)) color.append((pixel[0],pixel[1],pixel[2])) txt = txt + color2Char(pixel[0], pixel[1], pixel[2], pixel[3]) if len(pixel) == 4 else \ txt + color2Char(pixel[0], pixel[1], pixel[2]) txt += '\n' color.append((255,255,255)) # 繪制ASCII字符畫(huà)并保存 x, y = 0,0 fontW, fontH = font.getsize(txt[1]) fontH *= 1.37 for i in range(len(txt)): if(txt[i]=='\n'): x += fontH y = -fontW drawPtr.text((y,x), txt[i], fill=color[i]) y += fontW os.chdir('cacheChar') asciiImg.save(str(index)+'.jpg') os.chdir("..") ''' * @breif: 將視頻轉(zhuǎn)換為ASCII圖像集 * @param[in]: number -> 幀數(shù) * @retval: None ''' def video2Char(number): if not os.path.exists('cacheChar'): os.mkdir('cacheChar') img_path_list = ['cachePic' + r'/{}.jpg'.format(i) for i in range(1, number + 1)] task = 0 for imagePath in img_path_list: task += 1 img2Char(imagePath, task) ''' * @breif: 將圖像合成視頻 * @param[in]: vp -> openCV視頻句柄 * @param[in]: number -> 幀數(shù) * @param[in]: savePath -> 視頻保存路徑 * @retval: None ''' def img2Video(vp, number, savePath): videoFourcc = VideoWriter_fourcc(*"MP42") # 設(shè)置視頻編碼器 asciiImgPathList = ['cacheChar' + r'/{}.jpg'.format(i) for i in range(1, number + 1)] asciiImgTemp = Image.open(asciiImgPathList[1]).size videoWritter= VideoWriter(savePath, videoFourcc, vp.get(cv2.CAP_PROP_FPS), asciiImgTemp) for imagePath in asciiImgPathList: videoWritter.write(cv2.imread(imagePath)) videoWritter.release() if __name__ == '__main__': videoPath = 'test.mp4' savePath = 'new.avi' vp = cv2.VideoCapture(videoPath) number = video2Pic(vp) video2Char(number) img2Video(vp, number, savePath) vp.release()
好啦,這就是今天的內(nèi)容,如果你那里還不能放鞭炮,那就來(lái)試試這個(gè)吧?。。?!
到此這篇關(guān)于Python繪制1000響大地紅鞭炮動(dòng)態(tài)效果的文章就介紹到這了,更多相關(guān)Python鞭炮內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python 開(kāi)發(fā)工具PyCharm安裝教程圖文詳解(新手必看)
PyCharm是一種Python IDE,帶有一整套可以幫助用戶在使用Python語(yǔ)言開(kāi)發(fā)時(shí)提高其效率的工具,比如調(diào)試、語(yǔ)法高亮、Project管理、代碼跳轉(zhuǎn)、智能提示、自動(dòng)完成、單元測(cè)試、版本控制。今天通過(guò)本文給大家分享PyCharm安裝教程,一起看看吧2020-02-02Python實(shí)現(xiàn)單例模式的四種方式詳解
單例模式可以保證一個(gè)類(lèi)僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。本文為大家介紹了Python實(shí)現(xiàn)單例模式的四種方式,需要的可以參考一下2022-05-05python爬蟲(chóng)學(xué)習(xí)筆記之Beautifulsoup模塊用法詳解
這篇文章主要介紹了python爬蟲(chóng)學(xué)習(xí)筆記之Beautifulsoup模塊用法,結(jié)合實(shí)例形式詳細(xì)分析了python爬蟲(chóng)Beautifulsoup模塊基本功能、原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04Python實(shí)現(xiàn)Sqlite將字段當(dāng)做索引進(jìn)行查詢(xún)的方法
這篇文章主要介紹了Python實(shí)現(xiàn)Sqlite將字段當(dāng)做索引進(jìn)行查詢(xún)的方法,涉及Python針對(duì)sqlite數(shù)據(jù)庫(kù)索引操作的相關(guān)技巧,需要的朋友可以參考下2016-07-07Keras自動(dòng)下載的數(shù)據(jù)集/模型存放位置介紹
這篇文章主要介紹了Keras自動(dòng)下載的數(shù)據(jù)集/模型存放位置介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06IDA Pro 6.0使用Qt框架實(shí)現(xiàn)了跨平臺(tái)的UI界面
通過(guò)本文帶領(lǐng)大家學(xué)習(xí)如何使用PySide使用IDAPython為 IDA Pro 創(chuàng)建 UI 界面,對(duì)IDA Pro 6.0使用Qt 框架實(shí)現(xiàn)了跨平臺(tái)的UI相關(guān)知識(shí)感興趣的朋友一起看看吧2021-07-07Django中celery執(zhí)行任務(wù)結(jié)果的保存方法
今天小編就為大家分享一篇Django中celery執(zhí)行任務(wù)結(jié)果的保存方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07Python 結(jié)構(gòu)化字符串中提取數(shù)據(jù)詳情
這篇文章主要介紹了Python 結(jié)構(gòu)化字符串中提取數(shù)據(jù)詳情,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08