摘要:讓我們來用Python定制出心儀的“本草綱目女孩”,敲出魔性的代碼舞蹈,520,準備好心儀女孩的舞蹈視訊,把這份别出心裁的禮物給TA
本文分享自華為雲社群《【雲駐共創】華為雲AI之用Python定制我的《本草綱目女孩》》,作者:愚公搬代碼。
前言
近日,《本草綱目》毽子操的視訊刷屏網絡。公司裡更是多了很多劉畊宏女孩,在520到來之際特意奉獻這篇文章給大家。如果有心儀的女孩這篇文章可以幫助你哦。
歌詞:擡腿!拍腿!,側邊的肥肉咔咔掉,人魚線馬甲線我都要!劉畊宏的男孩女孩看過來。
讓我們來用Python定制出心儀的“本草綱目女孩”,敲出魔性的代碼舞蹈,520,準備好心儀女孩的舞蹈視訊,把這份别出心裁的禮物給TA❤️。
一、華為雲ModelArts-Notebook介紹
1.華為雲ModelArts-Notebook
ModelArts內建了基于開源的Jupyter Notebook和JupyterLab,可為您提供線上的互動式開發調試工具。您無需關注安裝配置,在ModelArts管理控制台直接使用Notebook,編寫和調測模型訓練代碼,然後基于該代碼進行模型的訓練。
其中,ModelArts還提供了華為自研的分布式訓練加速架構MoXing,您可以在Notebook中使用MoXing編寫訓練腳本,讓您代碼編寫更加高效、代碼更加簡潔。
1.1 Jupyter Notebook是什麼
Jupyter Notebook是一個可以在浏覽器中使用的互動式的計算應用程式,該應用程式的所有可見的内容,以筆記本文檔表示,包括計算的輸入和輸出、解釋文本、數學、圖像和對象的富媒體等表示。是以,Jupyter Notebook可以實作将代碼、文字完美結合起來,非常适合從事機器學習、資料分析等資料科學工作的人員。
Jupyter Notebook相關文檔:https://docs.jupyter.org/en/latest/
1.2 JupyterLab是什麼
JupyterLab是一個互動式的開發環境,是Jupyter Notebook的下一代産品,可以使用它編寫Notebook、操作終端、編輯MarkDown文本、打開互動模式、檢視csv檔案及圖檔等功能。
JupyterLab相關文檔:https://jupyterlab.readthedocs.io/en/stable/
1.3 什麼是Moxing
MoXing是華為雲ModelArts團隊自研的分布式訓練加速架構,它建構于開源的深度學習引擎TensorFlow、MXNet、PyTorch、Keras之上。相對于TensorFlow和MXNet原生API而言,MoXing API讓模型代碼的編寫更加簡單,允許使用者隻需要關心資料輸入(input_fn)和模型建構(model_fn)的代碼,即可實作任意模型在多GPU和分布式下的高性能運作,降低了TensorFlow和MXNet的使用門檻。另外,MoXing-TensorFlow還将支援自動超參選擇和自動模型結構搜尋,使用者無需關心超參和模型結構,做到模型全自動學習。
Moxing相關文檔:https://github.com/huaweicloud/ModelArts-Lab/tree/master/docs/moxing_api_doc
2.Python-Opencv
Python由荷蘭數學和計算機科學研究學會的吉多·範羅蘇姆于1990年代初設計,作為一門叫做ABC語言的替代品。Python提供了高效的進階資料結構,還能簡單有效地面向對象程式設計。Python文法和動态類型,以及解釋型語言的本質,使它成為多數平台上寫腳本和快速開發應用的程式設計語言,随着版本的不斷更新和語言新功能的添加,逐漸被用于獨立的、大型項目的開發。
Python解釋器易于擴充,可以使用C語言或C++(或者其他可以通過C調用的語言)擴充新的功能和資料類型。Python也可用于可定制化軟體中的擴充程式語言。Python豐富的标準庫,提供了适用于各個主要系統平台的源碼或機器碼。
OpenCV用C++語言編寫,它具有C++,Python,Java和MATLAB接口,并支援Windows,Linux,Android和Mac OS,OpenCV主要傾向于實時視覺應用,并在可用時利用MMX和SSE指令,如今也提供對于C#、Ch、Ruby,GO的支援。
opencv-python的github網址:https://pypi.org/project/opencv-python/
OpenCV官網:https://opencv.org/
二、本地案例實作Python定制我的《本草綱目女孩》
1.案例實作流程
衆所周知,視訊是由一幀幀圖像構成,Opencv處理視訊圖像資訊的原理就是将視訊轉為一幀幀圖像,處理完圖像後再轉換為視訊。
用Python實作案例流程如下:
2.案例環境部署
2.1 本機環境
- vs2022
- anaconda(已經包括opencv和PIL)
- python
2.2 安裝對應的anaconda包
anaconda這是一個非常常用的python包內建管理工具,其中預安裝了很多python庫,使得我們不需要去手動安裝各種的第三方庫,我們知道自己取手動安裝的過程中,很容易就會遇到一些報錯,解決起來也非常的麻煩。
anaconda官網:https://www.anaconda.com/products/distribution#Downloads
下載下傳完軟體包一路點選安裝就行了,安裝成功後會出現如下界面。
檢視是否安裝成功指令:
conda --version
2.3 安裝opencv-python
進入anaconda控制台輸入如下指令:
pip install opencv-python
3.案例實作代碼
本案例的實作過程主要分為以下幾步:
1. 導入資料
2. 導入庫函數
3. 将視訊轉化為圖像幀
4. 對圖檔幀進行ASCII碼的轉換
5. 将轉換好的圖檔幀合成視訊
3.1 導入資料
視訊下載下傳位址:https://cnnorth4-modelhub-datasets-obsfs-sfnua.obs.cn-north-4.myhuaweicloud.com/content/35d24c0e-f337-442b-935f-ef8123062d3e/QzNm9F/dataset/test_demo0510.mp4
3.2 導入庫函數
#導入Python庫
import cv2
from PIL import Image,ImageFont,ImageDraw
import os
from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize
3.3 将視訊轉化為圖像幀
#将視訊轉換為圖檔存入目标檔案夾
def video_to_pic(vp):
number = 0
# 判斷載入的視訊是否可以打開
if vp.isOpened():
#r:布爾型 (True 或者False),代表有沒有讀取到圖檔,frame:表示截取到的一幀的圖檔的資料,是個三維數組
r,frame = vp.read()
#判斷檔案夾是否存在,不存在的話則建立檔案夾
if not os.path.exists('cache_pic'):
os.mkdir('cache_pic')
os.chdir('cache_pic')
else:
r = False
#周遊視訊,并将每一幀圖檔寫入檔案夾
while r:
number += 1
cv2.imwrite(str(number)+'.jpg',frame)
r,frame = vp.read()
print('\n由視訊一共生成了{}張圖檔!'.format(number))
# 修改目前工作目錄至主目錄
os.chdir("..")
return number
3.4 對圖檔幀進行ASCII碼的轉換
#将圖檔進行批量化處理
def star_to_char(number, save_pic_path):
#判斷檔案夾是否存在,不存在的話則建立檔案夾
if not os.path.exists('cache_char'):
os.mkdir('cache_char')
# 生成目标圖檔檔案的路徑清單
img_path_list = [save_pic_path + r'/{}.jpg'.format(i) for i in range(1, number + 1)]
task = 0
for image_path in img_path_list:
# 擷取圖檔的分辨率
img_width, img_height = Image.open(image_path).size
task += 1
#處理圖檔,并顯示處理程序
img_to_char(image_path, img_width, img_height, task)
print('{}/{} is processed.'.format(task, number))
print('=======================')
print('All pictures were processed!')
print('=======================')
return 0
# 将圖檔轉換為灰階圖像後進行ascii_char中的ASCII值輸出
# 函數輸入像素RGBA值,輸出對應的字元碼。其原理是将字元均勻地分布在整個灰階範圍内,像素灰階值落在哪個區間就對應哪個字元碼。
def get_char(r, g, b, alpha=256):
#ascii_char就是字元清單,用來将不同灰階的像素進行不同字元體替換的參照。
ascii_char = list("#RMNHQODBWGPZ*@$C&98?32I1>!:-;. ")
#alpha在為0的時候便是完全透明的圖檔,是以傳回空
if alpha == 0:
return ''
length = len(ascii_char)
#轉為灰階圖
#RGBA是代表Red(紅色)、Green(綠色)、Blue(藍色)和Alpha的色彩空間,Alpha通道一般用作不透明度參數
#如果一個像素的alpha通道數值為0%,那它就是完全透明的,而數值為100%則意味着一個完全不透明的像素
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
# unit = (256.0 + 1) / len(ascii_char)
unit = 256 / len(ascii_char)
return ascii_char[int(gray / unit)]
def img_to_char(image_path, raw_width, raw_height, task):
width = int(raw_width / 6)
height = int(raw_height / 15)
# 以RGB模式打開
im = Image.open(image_path).convert('RGB')
im = im.resize((width, height), Image.NEAREST)
txt = ''
color = []
#周遊圖檔的每個像素
for i in range(height):
for j in range(width):
pixel = im.getpixel((j, i))
# 将顔色加入進行索引
color.append((pixel[0], pixel[1], pixel[2]))
if len(pixel) == 4:
txt += get_char(pixel[0], pixel[1], pixel[2], pixel[3])
else:
txt += get_char(pixel[0], pixel[1], pixel[2])
txt += '\n'
color.append((255, 255, 255))
im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255))
dr = ImageDraw.Draw(im_txt)
font = ImageFont.load_default().font
x, y = 0, 0
font_w, font_h = font.getsize(txt[1])
font_h *= 1.37 # 調整字型大小
for i in range(len(txt)):
if (txt[i] == '\n'):
x += font_h
y = -font_w
dr.text((y, x), txt[i], fill=color[i])
y += font_w
#存儲處理後的圖檔至檔案夾
os.chdir('cache_char')
im_txt.save(str(task) + '.jpg')
#直接進入新建立的檔案夾将生成的圖檔直接存入檔案夾中
os.chdir("..")
return 0
3.5 将轉換好的圖檔幀合成視訊
# 進度條顯示
def process_bar(percent, start_str='', end_str='', total_length=0):
bar = ''.join("■ " * int(percent * total_length)) + ''
bar = '\r' + start_str + bar.ljust(total_length) + ' {:0>4.1f}%|'.format(percent * 100) + end_str
print(bar, end='', flush=True)
#圖檔幀合成視訊
def jpg_to_video(char_image_path, FPS):
# 設定視訊編碼器,這裡使用MP42編碼器
video_fourcc = VideoWriter_fourcc(*"MP42")
# 生成目标字元圖檔檔案的路徑清單
char_img_path_list = [char_image_path + r'/{}.jpg'.format(i) for i in range(1, number + 1)]
# 擷取圖檔的分辨率
char_img_test = Image.open(char_img_path_list[1]).size
if not os.path.exists('video'):
os.mkdir('video')
video_writter = VideoWriter('video/output.avi', video_fourcc, FPS, char_img_test)
sum = len(char_img_path_list)
count = 0
for image_path in char_img_path_list:
img = cv2.imread(image_path)
video_writter.write(img)
end_str = '100%'
count = count + 1
process_bar(count / sum, start_str='', end_str=end_str, total_length=15)
video_writter.release()
print('\n')
print('=======================')
print('The video is finished!')
print('=======================')
3.6 主函數
if __name__ == "__main__":
#初始視訊路徑
video_path = 'test_demo0510.mp4'
#原始視訊轉為圖檔的圖檔儲存路徑
save_pic_path = 'cache_pic'
#圖檔經處理後的圖檔儲存路徑
save_charpic_path = 'cache_char'
# 讀取視訊
vp = cv2.VideoCapture(video_path)
# 将視訊轉換為圖檔 并進行計數,傳回總共生成了多少張圖檔
number = video_to_pic(vp)
# 計算視訊幀數
FPS = vp.get(cv2.CAP_PROP_FPS)
# 将圖像進行字元串處理後
star_to_char(number, save_pic_path)
vp.release()
# 将圖檔合成為視訊
jpg_to_video(save_charpic_path, FPS)
3.7 運作結果
運作後一共生成了382張圖檔,和視訊檔案,儲存在如下檔案夾下。
4.案例播放代碼
import cv2
from IPython.display import clear_output, Image, display
def show_video(video_path, show_text):
video = cv2.VideoCapture(video_path)
while True:
try:
clear_output(wait=True)
# 讀取視訊
ret, frame = video.read()
if not ret:
break
height, width, _ = frame.shape
cv2.putText(frame, show_text, (0, 100), cv2.FONT_HERSHEY_TRIPLEX, 3.65, (255, 0, 0), 2)
frame = cv2.resize(frame, (int(width / 2), int(height / 2)))
_, ret = cv2.imencode('.jpg', frame)
display(Image(data=ret))
except KeyboardInterrupt:
video.release()
#視訊循環播放
i=1
while i>0:
show_video('video/output.avi',str(i))
i=i+1
三、華為雲AI實作Python定制我的《本草綱目女孩》
1.基礎配置
"本草綱目"健身操字元串視訊操作執行個體的案例頁面如下:https://developer.huaweicloud.com/develop/aigallery/Notebook/detail?id=c81526e5-cc88-497f-8a21-41a5632e014e
點選Run in ModelArts,進入JupyterLab頁面。
配置目前運作環境,切換規格,并選擇免費的就好了。
2.導入資料
選擇下方代碼,點選運作。
運作完成後如下:
3.安裝相關依賴
選擇下方代碼,點選運作安裝opencv包
pip install opencv_python
4.導入庫函數
#導入Python庫
import cv2
from PIL import Image,ImageFont,ImageDraw
import os
from cv2 import VideoWriter, VideoWriter_fourcc, imread, resize
5.将視訊轉化為圖像幀
#将視訊轉換為圖檔存入目标檔案夾
def video_to_pic(vp):
number = 0
# 判斷載入的視訊是否可以打開
if vp.isOpened():
#r:布爾型 (True 或者False),代表有沒有讀取到圖檔,frame:表示截取到的一幀的圖檔的資料,是個三維數組
r,frame = vp.read()
#判斷檔案夾是否存在,不存在的話則建立檔案夾
if not os.path.exists('cache_pic'):
os.mkdir('cache_pic')
os.chdir('cache_pic')
else:
r = False
#周遊視訊,并将每一幀圖檔寫入檔案夾
while r:
number += 1
cv2.imwrite(str(number)+'.jpg',frame)
r,frame = vp.read()
print('\n由視訊一共生成了{}張圖檔!'.format(number))
# 修改目前工作目錄至主目錄
os.chdir("..")
return number
6.對圖檔幀進行ASCII碼的轉換
#将圖檔進行批量化處理
def star_to_char(number, save_pic_path):
#判斷檔案夾是否存在,不存在的話則建立檔案夾
if not os.path.exists('cache_char'):
os.mkdir('cache_char')
# 生成目标圖檔檔案的路徑清單
img_path_list = [save_pic_path + r'/{}.jpg'.format(i) for i in range(1, number + 1)]
task = 0
for image_path in img_path_list:
# 擷取圖檔的分辨率
img_width, img_height = Image.open(image_path).size
task += 1
#處理圖檔,并顯示處理程序
img_to_char(image_path, img_width, img_height, task)
print('{}/{} is processed.'.format(task, number))
print('=======================')
print('All pictures were processed!')
print('=======================')
return 0
# 将圖檔轉換為灰階圖像後進行ascii_char中的ASCII值輸出
# 函數輸入像素RGBA值,輸出對應的字元碼。其原理是将字元均勻地分布在整個灰階範圍内,像素灰階值落在哪個區間就對應哪個字元碼。
def get_char(r, g, b, alpha=256):
#ascii_char就是字元清單,用來将不同灰階的像素進行不同字元體替換的參照。
ascii_char = list("#RMNHQODBWGPZ*@$C&98?32I1>!:-;. ")
#alpha在為0的時候便是完全透明的圖檔,是以傳回空
if alpha == 0:
return ''
length = len(ascii_char)
#轉為灰階圖
#RGBA是代表Red(紅色)、Green(綠色)、Blue(藍色)和Alpha的色彩空間,Alpha通道一般用作不透明度參數
#如果一個像素的alpha通道數值為0%,那它就是完全透明的,而數值為100%則意味着一個完全不透明的像素
gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
# unit = (256.0 + 1) / len(ascii_char)
unit = 256 / len(ascii_char)
return ascii_char[int(gray / unit)]
def img_to_char(image_path, raw_width, raw_height, task):
width = int(raw_width / 6)
height = int(raw_height / 15)
# 以RGB模式打開
im = Image.open(image_path).convert('RGB')
im = im.resize((width, height), Image.NEAREST)
txt = ''
color = []
#周遊圖檔的每個像素
for i in range(height):
for j in range(width):
pixel = im.getpixel((j, i))
# 将顔色加入進行索引
color.append((pixel[0], pixel[1], pixel[2]))
if len(pixel) == 4:
txt += get_char(pixel[0], pixel[1], pixel[2], pixel[3])
else:
txt += get_char(pixel[0], pixel[1], pixel[2])
txt += '\n'
color.append((255, 255, 255))
im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255))
dr = ImageDraw.Draw(im_txt)
font = ImageFont.load_default().font
x, y = 0, 0
font_w, font_h = font.getsize(txt[1])
font_h *= 1.37 # 調整字型大小
for i in range(len(txt)):
if (txt[i] == '\n'):
x += font_h
y = -font_w
dr.text((y, x), txt[i], fill=color[i])
y += font_w
#存儲處理後的圖檔至檔案夾
os.chdir('cache_char')
im_txt.save(str(task) + '.jpg')
#直接進入新建立的檔案夾将生成的圖檔直接存入檔案夾中
os.chdir("..")
return 0
7.将轉換好的圖檔幀合成視訊
# 進度條顯示
def process_bar(percent, start_str='', end_str='', total_length=0):
bar = ''.join("■ " * int(percent * total_length)) + ''
bar = '\r' + start_str + bar.ljust(total_length) + ' {:0>4.1f}%|'.format(percent * 100) + end_str
print(bar, end='', flush=True)
#圖檔幀合成視訊
def jpg_to_video(char_image_path, FPS):
# 設定視訊編碼器,這裡使用MP42編碼器
video_fourcc = VideoWriter_fourcc(*"MP42")
# 生成目标字元圖檔檔案的路徑清單
char_img_path_list = [char_image_path + r'/{}.jpg'.format(i) for i in range(1, number + 1)]
# 擷取圖檔的分辨率
char_img_test = Image.open(char_img_path_list[1]).size
if not os.path.exists('video'):
os.mkdir('video')
video_writter = VideoWriter('video/output.avi', video_fourcc, FPS, char_img_test)
sum = len(char_img_path_list)
count = 0
for image_path in char_img_path_list:
img = cv2.imread(image_path)
video_writter.write(img)
end_str = '100%'
count = count + 1
process_bar(count / sum, start_str='', end_str=end_str, total_length=15)
video_writter.release()
print('\n')
print('=======================')
print('The video is finished!')
print('=======================')
8.運作主函數
if __name__ == "__main__":
#初始視訊路徑
video_path = 'test_demo0510.mp4'
#原始視訊轉為圖檔的圖檔儲存路徑
save_pic_path = 'cache_pic'
#圖檔經處理後的圖檔儲存路徑
save_charpic_path = 'cache_char'
# 讀取視訊
vp = cv2.VideoCapture(video_path)
# 将視訊轉換為圖檔 并進行計數,傳回總共生成了多少張圖檔
number = video_to_pic(vp)
# 計算視訊幀數
FPS = vp.get(cv2.CAP_PROP_FPS)
# 将圖像進行字元串處理後
star_to_char(number, save_pic_path)
vp.release()
# 将圖檔合成為視訊
jpg_to_video(save_charpic_path, FPS)
等待主函數執行完成,後會生成如下三個檔案夾:
9.播放視訊
總結
本文主要介紹了本地開發和華為雲ModelArts開發兩種形式,從開發流程中大家也明白那種形式開發更簡單。
ModelArts是面向開發者的一站式AI開發平台,為機器學習與深度學習提供海量資料預處理及半自動化标注、大規模分布式Training、自動化模型生成,及端-邊-雲模型按需部署能力,幫助使用者快速建立和部署模型,管理全周期AI工作流。