2017年12月30日 星期六

ImageMagick mask : 批次遮罩疊圖 (例如局部著色)

遮罩疊圖的各階段圖片 先前曾經 在 gimp 裡面採用遮罩機制 幫相片只保留主角的顏色。 遮罩疊圖不僅限用於著色。 凡是需要 「把一張圖的一部分疊到另一張底圖之上」 的動作都適用。 如果有很多張圖要用相同的方式處理, 改用 ImageMagick 指令會比用 gimp 快。 最麻煩的部分是: 每張圖的遮罩很難自動產生。 不過現在 AI 那麼厲害, 很快地就會出現各種類似 街道圖片 semantic segmentation 語義分割 的類神經網路, 到時候這篇所介紹的技巧就會很有用了: 我們要解說如何用 ImageMagick 命令列把一張原圖及它的語義分割成果圖轉換成局部著色的圖。 我已更新 範例圖檔, 裡面包含九張原圖 (orig/*) 跟九張語義分割成果圖 (result/*) 所以你不需要架設 docker 等等, 只要有安裝 ImageMagick 就可以跟著實作。

遮罩疊圖的流程/步驟 完整的 script 在 hilight.sh; 流程如右圖。 除了 「用深度學習產生語義分割成果圖」 之外, 只有三個步驟。 假設原圖叫做 orig.jpg、 語義分割成果圖叫做 semseg.jpg 。

第一步: 產生黑白版 (嚴格來講應該叫做灰階版): convert orig.jpg -colorspace Gray gray.jpg

做第二步之前, 先做一點查詢跟小實驗。 根據 ENet 的原始碼, semseg.png 裡面應該只有 19 種顏色才對。 用 ImageMagick 的 histogram 統計功能 確認一下: convert semseg.png -format %c histogram:info:- 如果出現超過 19 種顏色, 那有可能是 AI 的外包裝輸出程式有 bug (自首 orz)。 再來測試 ImageMagick 的 「選色著色」 功能: convert -opaque 'rgb(220,20,60)' semseg.png test.png 這會把 semseg.png 裡面的所有 rgb(220,20,60) 顏色的部分都改塗上白色, 存成 test.png。 如果想要塗上綠色而不是白色, 可以在 -opaque 之前加上 -fill 'rgb(0,255,0)'

所以完整的第二句長這樣: convert semseg.png -fill white -opaque 'rgb(220,20,60)' -fill black +opaque white mask.png。 意思是: 把代表 「人」 的紅色塗成白色, 再把 「除了白色之外的其他所有地方」 都塗成黑色 (+opaque white) , 這就是我們需要的遮罩。 或是把 +opaque white 改成 +transparent white 也可以, 也就是 「除了白色之外的其他所有地方都塗成透明」

第三句則是: convert -composite gray.jpg orig.jpg mask.png hilight.jpg 意思是: 以 gray.jpg 為底圖, 把 orig.jpg 截一小塊下來 (以 mask.png 決定截取範圍), 疊上去產生 hilight.jpg 就得到我們要的成果! 關於遮罩更進階的功能, 詳見 手冊

呵呵, 這篇根本是 ImageMagick 教學文~~ 那就順便說明一下前一篇的 九圖合併 是怎麼做的。 一開始是用 montage ?.jpg semseg-result.jpg 一個指令就搞定, 很方便。 但是後來發現這個指令無法指定合併圖的大小, 感覺不太實用。 於是改成手工合併:

for i in 1 2 3 ; do convert -resize x400 $i.jpg ../montage/$i.jpg ; done
for i in 4 5 6 ; do convert -resize x359 $i.jpg ../montage/$i.jpg ; done
for i in 7 8 9 ; do convert -resize x400 $i.jpg ../montage/$i.jpg ; done
cd ../montage
convert [123].jpg -background white -splice 20x0+0+0 -gravity Center +append -gravity SouthEast -splice 20x0+0+0 R1.jpg
convert [456].jpg -background white -splice 20x0+0+0 -gravity Center +append -gravity SouthEast -splice 20x0+0+0 R2.jpg
convert [789].jpg -background white -splice 20x0+0+0 -gravity Center +append -gravity SouthEast -splice 20x0+0+0 R3.jpg
convert R[123].jpg -background white -splice 0x20+0+0 -gravity Center -append -gravity SouthEast -splice 0x20+0+0 final.jpg

前面三個 for 迴圈以三張圖為一組, 每一組調成相同的高度。 高度的數字是用工人智慧約略估算、 嘗試錯誤, 最終要讓每一組的 「三張寬度加總」 約略相同。 再來三句 +append 分別把每一組橫向合併, 前後及中間穿插空白。 最後一句 -append 把三長橫條圖上下合併, 前後及中間穿插空白。 這是從 這裡 學來的。

我愛 ImageMagick!

沒有留言:

張貼留言