ImageMagick 範例 --
視訊處理

索引
ImageMagick 範例 前言與索引
視訊轉 GIF,最佳化摘要
去除視訊畫面交錯
ImageMagick 並非特別適合處理數位視訊,但它常被用於此目的,特別是在 Linux 環境中。在這裡,我探討專門用於處理真實(和光線追蹤)視訊序列的技術和範例。

視訊轉 GIF,最佳化摘要

一位使用 IM 建立電影 GIF 的軟體開發人員 Benoit Rouleau,在與我討論時,給了我一段 飛機飛過 的 AVI 視訊,以幫助我們共同探索 IM 視訊轉換技術。然而,雖然 AVI 本身相當小,但未壓縮的視訊卻有 [IM 文字] 位元組的大小,並且包含 [IM 文字] 種顏色,分佈在 [IM 文字] 個畫面中。
然而,IM 將此視訊轉換為 GIF 動畫並沒有真正的問題。但請注意,您可能會遇到一些不受支援的「AVI 區塊」錯誤,可以使用「-quiet控制設定 來忽略這些錯誤。

  magick -quiet -delay 1 plane.avi plane.gif
[IM Output]
這使用了 ImageMagick 預設的 色彩量化和抖動 方法,產生了非常合理的視訊轉換結果。由於視訊一開始就使用很少的顏色,因此很少出現顏色問題。這並非總是如此,特別是因為 GIF 每個畫面的顏色限制為 256 色。然而,動畫檔案的大小為 [IM 文字] 位元組,雖然由於顏色減少和 GIF 像素資料壓縮,它只有原始大小的 1/5,但仍然相當大。此外,如果您進一步研究產生的動畫,您會發現圖像中的 [IM 文字] 個畫面中,有 [IM 文字] 個畫面添加了自己的獨立 本地色彩表。也就是說,GIF 動畫中的每個畫面都需要自己的顏色索引表。也就是說,雖然每個畫面的顏色都少於 256 色(由於 GIF 格式的限制),但整個動畫使用了總共 [IM 文字] 種顏色。不幸的是,GIF 格式不會壓縮顏色表,因此所有這些額外的顏色表可能會佔用多達:256 色 * 每色 3 位元組 * 106 個畫面;或 81,408 位元組的檔案空間。對於 1GB 的視訊來說並不多,但仍然是相當可觀的空間,特別是當我們進一步最佳化視訊時。除此之外,動畫的 GIF 畫面不會很好地進行最佳化。這不僅是因為背景在移動(由於相機向上移動),還因為 IM 使用了 誤差校正抖動(希爾伯特曲線抖動),它會產生一種偽隨機的顏色模式,在不同的畫面之間有所不同。後面的例子將使這種「抖動雜訊」更加明顯。

通用全域色彩表

在這裡,我為視訊的所有畫面 產生單一全域色彩表

  magick -quiet -delay 1 plane.avi  +remap   plane_cgc.gif
這自然會產生 [IM 文字] 個本地色彩表,以及 [IM 文字] 位元組的檔案大小。
[IM Output]
如您所見,產生的動畫沒有額外的局部調色板。相反,IM 根據動畫中的所有影格生成了單一全域調色板,其中包含 [IM 文字] 個「最佳」顏色。遺憾的是,這也導致像素數據無法像以前那樣良好地壓縮,因為需要更強的抖動處理。結果是動畫看起來略差,但大小與之前大致相同。對於這個顏色有限的特定影片,我甚至可以進一步減少使用的顏色數量,例如僅使用 64 種顏色,而不會產生太多問題,從而產生更小的動畫檔案大小。然而,這在很大程度上取決於所使用的影片序列,而且可能看起來不太好。您自己的影片可能會產生更好或更差的結果,尤其是在處理使用更多顏色和可能多個場景的影片時。

通用全域調色板

產生「更小」GIF 動畫的更好方法是僅提供通用的通用顏色範圍,而不是為動畫生成「最佳」全域調色板。使用一種無論原始影片中存在哪些顏色都能很好地運作的調色板。這樣做的另一個原因是,您可以延長影片時間,而不會對顏色選擇產生嚴重的負面影響,也無需為每個影格使用局部調色板。每個影格都抖動到相同的顏色映射,完全獨立於動畫中的其他影格。
在這裡,我使用了 「332」顏色映射,當不需要透明度時,它通常被認為是非常好的標準顏色映射。我經常在各種影片格式中看到這種顏色映射(或 219 色 「網頁安全」顏色映射)。

  magick -quiet -delay 1 plane.avi -remap colormap_332.png plane_ugc.gif
[IM Output]
此動畫具有 [IM 文字] 個局部調色板,因此動畫更小,大小為 [IM 文字] 位元組。然而,問題是您經常會在恆定顏色的區域看到明顯且惱人的「雜訊」。這種雜訊也存在於之前的所有影片動畫中。由於使用了更通用,因此分佈更廣的顏色映射,因此現在只能看到它。雜訊實際上是由於在重新生成圖像時減少的顏色集的抖動引起的。然而,這會產生一個從一幀到一幀變化的偽隨機顏色模式,從而導致圖像中出現背景雜訊。有關發生這種情況的原因的更多詳細信息,請參見 E 抖動的問題
我們可以關閉顏色抖動以消除「抖動雜訊」...

  magick -quiet -delay 1 plane.avi \
          +dither -remap colormap_332.png plane_ugc_nd.gif
它具有 [IM 文字] 個局部調色板,大小為 [IM 文字] 位元組。
[IM Output]
產生的動畫非常小,僅為原始動畫大小的 1/60,這通常是因為大面積的純色產生了極好的像素壓縮。但是,雖然它修復了抖動雜訊,並使檔案大小非常小,但您會得到顏色條帶,這通常被認為是非常糟糕的折衷方案。

有序抖動影片

真正的解決方案是使用不同的顏色抖動技術,該技術不會產生與上一幀不同的圖案。
例如,在這裡,我使用 使用色階海報化的有序抖動 來抖動相同的通用 「332」顏色映射

  magick -quiet -delay 1 plane.avi \
          -ordered-dither o8x8,8,8,4 +remap plane_od.gif
它具有 [IM 文字] 個局部調色板,大小為 [IM 文字] 位元組。
[IM Output]
上面還使用了「+remap」運算子,以確保所有圖像都使用完全相同的全域色彩表(有序抖動已將其減少到最多 256 種顏色)。 由於顏色數量已經最佳化,「+remap」運算子不會進行抖動或減少顏色。 生成的抖動圖案不是隨機的,並且從一幀到下一幀不會發生太大變化。 因此,動畫中已移除「抖動雜訊」,從而產生了從一幀到下一幀的固定顏色圖案。 該圖案也非常重複,可以實現更好的壓縮效果。 最後,由於色彩表是固定的,因此無論使用什麼影片,它都應該可以正常工作。

更高品質的有序抖動影片

然而,這個特定的影片僅使用一小部分顏色,主要是各種深淺的藍色,因此它實際上並沒有使用通用均勻色彩表提供的很多顏色。 事實上,最後的影片動畫只使用了 [IM 文字] 種顏色! 這個數字非常低,因此也很明顯。 但這也意味著此特定動畫可以受益於在有序抖動操作中使用大量的「顏色級別」,從而提高整體品質。 然而,首先我們需要確定動畫在達到 GIF 檔案格式和全域色彩表重新映射所施加的 256 色限制之前可以處理多少個顏色級別。 然而,棘手的部分是您必須在將動畫儲存為受限 GIF 格式之前確定這些。 以下是我使用的命令...

    magick -quiet plane.avi -ordered-dither o8x8,23 -append -format %k info:
[IM Text]
基本上,我增加和減少了要使用的顏色級別的數量,直到我得到一個恰好在所需的 256 色限制內的數字。
然後,我可以將發現的「顏色級別」選擇應用於飛機動畫。

  magick -quiet -delay 1 plane.avi \
          -ordered-dither o8x8,23 +remap plane_od2.gif
它具有 [IM 文字] 個局部色彩表,大小為 [IM 文字] 位元組,並且有 [IM 文字] 種顏色。
[IM Output]
如您所見,產生了一個非常高品質的有序抖動影片,它與我們之前生成的使用「最佳色彩表」的全域色彩表版本相當,但大小也縮小了 1/3,而「抖動雜訊」現在更難看到了。 當然,由於品質要高得多,因此它確實需要更大的檔案大小,因為它的壓縮率不如低品質版本。 另一方面,您現在可以透過使用的「顏色級別」數量來很好地控制品質與檔案大小之間的權衡。 請記住,這種技術是一種*特殊情況*,適用於不使用太多顏色的動畫。 通過添加更多幀來延長影片長度也會添加更多顏色,因此需要降低「顏色級別」品質控制。 這是迄今為止我見過的針對一般 GIF 動畫的最佳顏色最佳化方法。 它可以消除「抖動雜訊」,提供一定的品質控制,並保留使用其他 GIF 動畫最佳化方法的能力,例如 影格最佳化

壓縮(透明度)最佳化

由於此影片使用的是搖攝鏡頭,因此影片的背景會隨著影格而變化。 這意味著 GIF 動畫將無法很好地進行 影格最佳化
但是,我們仍然可以使用簡單的 透明度最佳化 來進一步減小 GIF 動畫的最終大小。

  magick plane_od2.gif  -layers OptimizeTransparency +remap plane_opt.gif
結果的大小為 [IM 文字] 位元組,並且包含 [IM 文字] 種顏色。
[IM Output]
也就是說,在圖像中添加了一種額外的顏色,即透明顏色索引,並且將任何不會改變當前顯示顏色的像素都設為透明。這反過來會在原始動畫中產生大段的透明區域,以及相似像素序列的重複,從而提高最終 GIF 圖像中的 LZW 壓縮率。不錯,動畫現在是直接轉換為 GIF 的一半大小,並且仍然保持相當高的品質。*如果您想對上述內容進行補充,討論進一步改進這些技術的方法,請與我聯繫,或到 IM 論壇留言。我很樂意聽取您的意見、技術和討論,或者查看您可能遇到的特定視頻/動畫問題。*其中一個討論是 為動畫 GIF 尋找「正確的量化級別」

Giflossy 壓縮 LZW 優化

一個名為 GifLossy 的新工具,它是原始 Gifsicle 程序的一個分支,它可以修改每一幀的顏色,以便讓 LZW 能夠更大程度地壓縮圖像。
例如,在這裡我將其應用於原始的 GIF 動畫,要求它將顏色減少到單個 256 色表格。

  gifsicle -O3 --lossy=80 --colors 256 plane.gif -o plane_giflossy.gif
其大小驚人地只有 [IM 文字] 位元組。雖然它的品質不如我們使用有序抖動所達到的那麼高,但它的大小不到後者的一半。
[IM Output]
受到上述結果的鼓舞,我決定在我們獲得的最佳有序抖動結果上使用 GifLossy,看看它是否能使其更小。

  gifsicle -O3 --lossy=80 plane_od2.gif -o plane_od2_giflossy.gif
我們確實獲得了更小的尺寸,只有 [IM 文字] 位元組。遺憾的是,我們基本上失去了之前努力實現的高品質有序抖動結果。真是令人失望。
[IM Output]


對視頻幀進行去交織

並非所有圖像都來自數位相機。從非 CCD 攝像機的數位視頻中提取圖像是非常常見的。這些圖像會進行交織以便在電視上直接顯示,導致每隔一行就是圖像的不同幀(交織)。對於靜止不動的兩個幀,交織通常不太明顯。也許只會產生輕微的圖像邊緣模糊。但是當涉及快速移動的物體時,所產生的交織圖像會非常不自然,因為兩個幀已經合併在一起。
來自德國的 Wolfgang Hugemann <Auto@Hugemann.de> 就遇到了這個問題,他發送給我一張他本人拍攝的 碰撞測試 的快照。但為了演示,我將使用從中裁剪出來的較小圖像。然而,這些技術也適用於全尺寸圖像。

    magick video_frame.png  -crop 100x100+200+470 +repage  interlaced.png
[IM Output]
Wolfgang Hugemann 對原始視頻幀使用了 TIFF 格式,我將其轉換為 PNG 以便在 IM 示例中使用。在完成處理之前,不要試圖對這些圖像使用 JPEG 格式,因為它會破壞此過程所需的低級品質。
如您所見,隔行掃描顯示了兩個獨立的畫面,因為它來自隔行掃描的 PAL 數位視訊序列(每秒約 50 個半畫面)。是的,汽車移動速度非常快,相機使用高速快門,產生了非常高品質的視訊影像。結果影像是由兩個交錯的半畫面組成,汽車的側後視鏡在半畫面之間 1/50 秒的時間間隔內移動了相當大的距離。
在這裡,我們只是將其中一個隔行掃描的半畫面(每隔一行)替換為白色。這是標準的去隔行掃描方法,稱為「BoB」濾波器。這是由 Wolfgang 為 IM 範例提供的。

  magick interlaced.png  -fx "floor(j/2)==j/2 ? u : 1"  deinterlace_1.png
[IM Output]
現在 FX 運算子 速度很慢,因此另一種方法是建立「條紋影像」。可以使用特殊的內建影像「pattern:Horizontal2」產生此類影像。
然後可以使用「Screen」合成方法將該影像與原始影像疊加,以疊加白線,或使用「Multiply」疊加黑線。例如...

  magick -size 100x100 pattern:Horizontal2 \
          interlaced.png -compose Multiply -composite  deinterlace_2.png
[IM Output]
否定圖案可用於選擇隔行掃描影像的另一半。或者,如果您將「Multiply」更改為「Screen」,則可以提取具有白色背景的畫面。
作為替代方案,我嘗試透過複製上一行來填補遺漏的畫面線。

    magick interlaced.png  -fx "u.p{i,j-j%2}"  deinterlace_3.png
[IM Output]
您也可以使用 像素化技術 來縮小和放大影像,以便將每隔一行加倍。

    magick interlaced.png -sample 100%x50% \
                           -sample 100%x200%  deinterlace_4.png
[IM Output]
透過稍微變化,您可以組合兩側的線條,以便在調整大小擴展時垂直平滑半畫面影像。

    magick interlaced.png -sample 100%x50% \
                           -resize 100%x200%  deinterlace_5.png
[IM Output]
結果是從隔行掃描視訊影像中提取了一個特別好的畫面。
如果您想從影像中提取另一個半畫面,您可以調整「sampling:offset」(從 IM v6.8.4-7 開始)

    magick interlaced.png -define sample:offset=75 \
            -sample 100%x50%  -resize 100%x200%    deinterlace_6.png
[IM Output]
在此版本的 IM 之前,您需要「-roll」影像一個像素,才能達到相同的效果。