奇月 發(fā)自 凹非寺量子位 | 公眾號(hào) QbitAI

奇月 發(fā)自 凹非寺量子位 | 公眾號(hào) QbitAI

老二次元/科技宅倒背如流的Bad Apple動(dòng)畫(huà),網(wǎng)友Nolen Royalty用Vim文本編輯器復(fù)現(xiàn)出來(lái)了!

而且僅耗時(shí)8小時(shí)、用了6500個(gè)正則表達(dá)式!

先來(lái)一起瞅瞅效果:

https://mp.weixin.qq.com/s/UaCpTGN6YAiIclorF4QhlA

可以看到,動(dòng)畫(huà)基本還原了人物的所有動(dòng)作,整體視頻也很流暢,畫(huà)風(fēng)很有經(jīng)典像素風(fēng)游戲的味道。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

繼終端、游戲引擎、ASCII碼各種 Bad Apple 整活之后,Vim 編輯器也出息了一回!

難怪有網(wǎng)友說(shuō),這就是我們喜歡 Bad Apple 的原因,它總是能帶給我們更多驚喜。

打開(kāi)網(wǎng)易新聞 查看精彩圖片
打開(kāi)網(wǎng)易新聞 查看精彩圖片

PS:如果你還不知道Bad Apple,它是來(lái)自《東方Project》中的一個(gè)音樂(lè)MV,已經(jīng)成為動(dòng)畫(huà)界和科技界的一個(gè)梗。不僅有各種二創(chuàng)視頻,大家還會(huì)在各種硬件和軟件上復(fù)現(xiàn)它,可以說(shuō)“有屏幕的地方就有Bad Apple”。

怎么做到的

網(wǎng)友 Nolen Royalty 還熱心分享了用 Vim 制作Bad Apple的過(guò)程,主要分為以下4步:

打開(kāi)網(wǎng)易新聞 查看精彩圖片

1.提取畫(huà)面幀轉(zhuǎn)換成數(shù)組

第一步非常簡(jiǎn)單,使用 GitHub 用戶(hù) Felixoofed 的庫(kù)就可以獲取 Bad Apple 每一幀的數(shù)據(jù)。

這個(gè)倉(cāng)庫(kù)里面包含了原始的視頻以及一個(gè) ffmpeg 命令,可以將視頻轉(zhuǎn)換為約 6500 張 PNG 圖片,每張代表一幀。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

然后 Nolen 編寫(xiě)了一小段 Python 代碼,將每個(gè) PNG 文件轉(zhuǎn)換為 0 和 1 的二維數(shù)組(其中 1 代表黑色像素)。

視頻最初是 480x360 分辨率,在測(cè)量了終端后 Nolen 將其縮小到 120x90。

from PIL import Image

import numpy as np

def process_image(path, target_width=120, target_height=90):

img = Image.open(path)

img = img.resize((target_width, target_height), Image.Resampling.LANCZOS)

if img.mode != "L":

img = img.convert("L")

pixels = np.array(img)

binary_pixels = (pixels < 10).astype(int) # 1 for dark, 0 for light return binary_pixels

def text_preview(binary_pixels):

chars = {0: ".", 1: "#"}

return "\n".join("".join(chars[px] for px in row) for row in binary_pixels)

2.用Vim的高亮匹配功能繪制任意矩形

那么如何在 Vim 中繪制圖形呢?

假設(shè)你在文本中創(chuàng)建了一個(gè)主要由 A 組成的網(wǎng)格,并在其中嵌入一個(gè)由 B 組成的繪圖,這樣如果你搜索 B,就會(huì)看到一個(gè)小的棍狀人物圖形:

打開(kāi)網(wǎng)易新聞 查看精彩圖片

使用這個(gè)方法就可以畫(huà)圖了,但是還存在2個(gè)問(wèn)題:

a.藍(lán)色高亮(Vim 默認(rèn))看起來(lái)不太清晰。

Vim 允許用戶(hù)自行配置高亮功能,調(diào)用 hi Search cterm=NONE ctermfg=grey ctermbg=grey ,就可以讓它用相同的顏色高亮匹配字符的前景和背景,這樣就能得到漂亮的方塊:

打開(kāi)網(wǎng)易新聞 查看精彩圖片

b.第二個(gè)問(wèn)題是,如何將矩形變?yōu)檎叫蜗袼亍?/p>

Nolen 最終找到了Square 字體,這是一個(gè)正方形的字體,它最初是為了讓用戶(hù)在終端中玩 roguelike 游戲而設(shè)計(jì)的,在 Vim 中使用它可以繪制一個(gè)非常漂亮的網(wǎng)格:

打開(kāi)網(wǎng)易新聞 查看精彩圖片

接下來(lái)就是分析每幀畫(huà)面的信息,生成一個(gè)針對(duì)主要圖形的正則表達(dá)式優(yōu)化文件。

然后作者發(fā)現(xiàn),用Vim 自帶的搜索功能就可以生成連續(xù)的矩形。

/\%l /\%>l /\%

\%23l Matches in a specific line.

\%<23l Matches above a specific line (lower line number).

\%>23l Matches below a specific line (higher line number).

\%.l Matches at the cursor line.

\%<.l Matches above the cursor line.

\%>.l Matches below the cursor line.

Vim 搜索可以匹配特定的行號(hào)(和列號(hào)),你可以將多個(gè)這樣的搜索組合在一起。

例如, \%>5c\%<15c\%>4l\%<9l 可以匹配第 5 列和第 15 列之間以及第 4 行和第 9 行之間的矩形區(qū)域。

而且,這種匹配模式還可以和其他 Vim 搜索進(jìn)行 OR 操作,比如將上面的式子和 - \%>5c\%<15c\%>4l\%<9l\|\%>12c\%<25c\%>10l\%<15l 進(jìn)行OR操作,就可以繪制出之前的矩形以及位于列 12 和 25 以及行 10 和 15 之間的新矩形。

這樣,使用單個(gè)搜索式就可以輕松地在屏幕上繪制許多矩形。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

3.將動(dòng)畫(huà)幀的圖形轉(zhuǎn)換成矩形

接下來(lái),就得把圖像的網(wǎng)格(90x120,約 10000 個(gè)像素)拆成一個(gè)個(gè)矩形。

Nolen 首先嘗試找出所有不一樣的矩形并生成長(zhǎng)搜索字符串、或者把網(wǎng)格拆成最少可填滿(mǎn)的矩形,但兩種嘗試均以失敗告終。

最終他想出了一個(gè)很簡(jiǎn)單的算法,它是這樣工作的:先在圖像的第一行里,把所有連續(xù)的“1”的部分找出來(lái)。找完第一行,再看第二行,找出和第二行找到的部分有重疊的地方。

要是把這個(gè)重疊部分和第一行合起來(lái)形成的矩形的面積,比單獨(dú)這兩行形成的矩形的面積都大的話(huà),就把它們合并成一個(gè)矩形。然后就一直持續(xù)下去,盡量把新找到的部分合并到之前的矩形里

這個(gè)算法通常情況下表現(xiàn)得不錯(cuò)。但當(dāng)搜索字符串超過(guò)10000個(gè)字符,就會(huì)嚴(yán)重拉低每秒的幀數(shù)。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

Nolen 于是又寫(xiě)了兩個(gè)解決方案(從左到右構(gòu)建矩形的算法版本和僅查看各個(gè)行的簡(jiǎn)單 RLE),然后通過(guò)三種算法運(yùn)行每個(gè)幀并選擇最短搜索模式,這個(gè)組合算法最終效果不錯(cuò)。

# Number of times each approach was picked

original approach (top to bottom merging) - 1110

left to right merging - 2239

single-row RLE - 3300

4.設(shè)置好Vim宏就可以在編輯器中播放動(dòng)畫(huà)了

分解好了圖形,最后的一個(gè)問(wèn)題就是:如何在 Vim 中播放視頻。具體步驟如下:

1.Vim 設(shè)置:頂部中心窗口播放視頻,是一個(gè)包含 90 行每行 120 個(gè)空格的文件,左右兩側(cè)是用于圖像居中的空緩沖區(qū),底部窗口是約 6500 個(gè)搜索模式列表。

2.使用 Vim 宏播放視頻:Vim 宏可以記錄一系列擊鍵操作,方便重播。宏命令為“”ay$:let @/=@a^M+”,具體來(lái)說(shuō),就是對(duì)寄存器 a 操作,拉動(dòng)到行尾,將寄存器/的內(nèi)容設(shè)置為寄存器 a 的內(nèi)容,執(zhí)行命令,然后移動(dòng)到下一行開(kāi)頭。這樣設(shè)置宏可以讓光標(biāo)回歸到正確位置,反復(fù)迭代即可實(shí)現(xiàn)重播。

3.優(yōu)化:最有趣的優(yōu)化操作是“l(fā)et @/=@a”,相比“/^Ra^M”操作,它避免了過(guò)長(zhǎng)的查詢(xún)操作導(dǎo)致搜索窗口閃爍嚴(yán)重和幀率降低的問(wèn)題。

4.運(yùn)行宏:可以運(yùn)行“1500@q”(假設(shè)宏記錄在寄存器 q 中)播放宏 1500 次,快速運(yùn)行 1500 幀。

打開(kāi)網(wǎng)易新聞 查看精彩圖片

這樣一來(lái),就終于能得到開(kāi)頭的 Bad Apple 視頻啦!

,時(shí)長(zhǎng)00:42

作者還表示,由于是在一天內(nèi)完成的項(xiàng)目,還有很多可以完善的細(xì)節(jié),比如可以創(chuàng)建結(jié)構(gòu)良好的文件來(lái)使用傳統(tǒng)正則表達(dá)式而非 Vim 的行/列搜索功能,以及幀率的穩(wěn)定性方面還可以繼續(xù)加強(qiáng)。

萬(wàn)物皆可BadApple

除了用 Vim 編輯器,網(wǎng)友們?cè)?Bad Apple 整活上一直都腦洞大開(kāi),可以說(shuō)只有你想不到,沒(méi)有網(wǎng)友做不到的。(doge)

比如有人用馬里奧游戲復(fù)現(xiàn):

打開(kāi)網(wǎng)易新聞 查看精彩圖片

還有在電腦終端中敲幾個(gè)命令就能運(yùn)行的:

打開(kāi)網(wǎng)易新聞 查看精彩圖片

甚至包括一些奇奇怪怪的硬件,包括快被淘汰的老式電視機(jī)電磁顯示屏、甚至做實(shí)驗(yàn)用的示波器都可以:

打開(kāi)網(wǎng)易新聞 查看精彩圖片

打開(kāi)網(wǎng)易新聞 查看精彩圖片

打開(kāi)網(wǎng)易新聞 查看精彩圖片

打開(kāi)網(wǎng)易新聞 查看精彩圖片

看來(lái),人類(lèi)對(duì)Bad Apple的開(kāi)發(fā)可能還不到10%啊,期待以后能看到更多的整活視頻(搓手手)

[1]https://news.ycombinator.com/item?id=42674116
[2]https://eieio.games/blog/bad-apple-with-regex-in-vim/