├── Bad Apple.py ├── README.md ├── convert.py └── data ├── 1.flv └── bgm.mp3 /Bad Apple.py: -------------------------------------------------------------------------------- 1 | # Author: 请喊我去编程 2 | # Bilibili: https://space.bilibili.com/73503664 3 | # GitHub: https://github.com/CallMeToProgram/Bad-Apple 4 | # Mail: 2395795924@qq.com 5 | 6 | # Created at 2019-06-17 7 | # Updated at 2020-03-03 8 | 9 | import pygame 10 | import time 11 | import curses 12 | from pathlib import Path 13 | import convert 14 | 15 | # video and bgm path 16 | VIDEO_PATH = "data/1.flv" 17 | BGM_PATH = "data/bgm.mp3" 18 | 19 | # frame rate of video 20 | FRAME_RATE = 1 / 30 21 | 22 | 23 | if Path("video_data.py").exists(): 24 | from video_data import video_data 25 | else: 26 | if not Path(VIDEO_PATH).exists(): 27 | print("视频不存在: ", VIDEO_PATH) 28 | video_data = convert.write(VIDEO_PATH) 29 | input("\n转换完成, 按任意键继续...") 30 | 31 | if not Path(BGM_PATH).exists(): 32 | print("音乐不存在: ", BGM_PATH) 33 | 34 | count = 0 35 | 36 | stdsrc = curses.initscr() 37 | curses.start_color() 38 | stdsrc.resize(30, 100) 39 | 40 | pygame.mixer.init() 41 | track = pygame.mixer.music.load(BGM_PATH) 42 | pygame.mixer.music.play() 43 | time.sleep(0.4) 44 | now = time.time() 45 | 46 | for frame_data in video_data: 47 | for i in range(len(frame_data)): 48 | stdsrc.addstr(i, 0, frame_data[i], curses.COLOR_WHITE) 49 | while time.time() - now < count * FRAME_RATE: 50 | time.sleep(count * FRAME_RATE - time.time() + now) 51 | stdsrc.refresh() 52 | count += 1 53 | 54 | curses.endwin() 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bad-Apple 2 | 用Python实现字符画 Bad Apple 3 | 4 | 5 | 运行Bad Apple.py即可 6 | -------------------------------------------------------------------------------- /convert.py: -------------------------------------------------------------------------------- 1 | # Author: 请喊我去编程 2 | # Bilibili: https://space.bilibili.com/73503664 3 | # GitHub: https://github.com/CallMeToProgram/Bad-Apple 4 | # Mail: 2395795924@qq.com 5 | 6 | # Created at 2019-06-17 7 | # Updated at 2019-12-20 8 | 9 | import matplotlib.pyplot as plt 10 | import cv2 11 | import pprint 12 | 13 | ascii_char = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. ") 14 | char_len = len(ascii_char) 15 | show_heigth = 30 16 | show_width = 90 17 | 18 | 19 | def convert(pic): 20 | pic_heigth, pic_width, _ = pic.shape 21 | gray = 0.2126 * pic[:, :, 2] + 0.7152 * pic[:, :, 1] + 0.0722 * pic[:, :, 0] 22 | res = [] 23 | for i in range(show_heigth): 24 | y = int(i * pic_heigth / show_heigth) 25 | text = "" 26 | for j in range(show_width): 27 | x = int(j * pic_width / show_width) 28 | text += ascii_char[int(gray[y][x] / 256 * char_len)] 29 | res.append(text) 30 | return res 31 | 32 | 33 | def write(VIDEO_PATH): 34 | print("转换视频中...") 35 | vc = cv2.VideoCapture(VIDEO_PATH) 36 | count = 0 37 | f, frame = vc.read() 38 | video_data = [] 39 | while f: 40 | count += 1 41 | print("\r转换进度: %d" % count, end='') 42 | text = convert(frame) 43 | video_data.append(text) 44 | f, frame = vc.read() 45 | 46 | with open("video_data.py", "w") as f: 47 | f.write("video_data = " + pprint.pformat(video_data)) 48 | 49 | return video_data 50 | 51 | 52 | if __name__ == '__main__': 53 | print(convert(plt.imread("1.jpg"))) 54 | -------------------------------------------------------------------------------- /data/1.flv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CallMeToProgram/Bad-Apple/caf1d819005034035617cc168992dd4cff0d870e/data/1.flv -------------------------------------------------------------------------------- /data/bgm.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CallMeToProgram/Bad-Apple/caf1d819005034035617cc168992dd4cff0d870e/data/bgm.mp3 --------------------------------------------------------------------------------