如何直接有效的解決問題是一門藝術。我們是做產(chǎn)品、做系統(tǒng)、做服務的,不是玩技術的,需要做的是在最短的時間內(nèi)以最有效的方式來解決工作中面對的難題。就在剛才,用了半小時不到時間,俺用一種極其簡單、直接、有效、霸道的方法解決了照片的反轉負沖特效問題。這種解決問題的思路值得總結推廣。
反轉負沖(反轉片)是一種攝影拍攝技術,它通過拍攝后反轉沖洗,得到色彩鮮艷的照片,非常養(yǎng)眼,F(xiàn)在都是數(shù)碼相機了,可以通過圖像處理算法來模擬反轉片的效果,比如說,“光影魔術手”就提供了5種反轉片特效:(1)素淡人像;(2)淡雅色彩;(3)真實色彩;(4)艷麗色彩;(5)濃郁色彩。且看(5)濃郁色彩的效果:
左邊是處理前的圖像,右邊是處理后的圖像,可以看到,處理后的圖像顏色格外飽滿。我目前開發(fā)的一款圖像處理軟件,一個難題就是處理后的照片色彩會變暗,這個反轉負沖特效的效果正是我所需要的。
且看“光影魔術手”怎樣描繪“反轉片”功能——
“模擬反轉片的效果,是《光影魔術手》最重要的功能之一。經(jīng)處理后照片反差更鮮明,色彩更亮麗。算法經(jīng)多次改良后,暗部細節(jié)得到最大程度的保留,高光部分無溢出,紅色還原十分準確,色彩過渡自然艷麗,絕無色斑!提供多種模式供用戶選擇,其中人像模式對亞洲人的膚色進行了優(yōu)化,不會出現(xiàn)膚色偏黃現(xiàn)象。獨有的暗部增補算法不僅增強了暗部, 同時令高光部分的表現(xiàn)更出色,絕對沒有霧感引入。精心設計,專業(yè)效果!強烈推薦所有用戶使用! ”
下面且看俺怎么在半小時內(nèi)將這個光影魔術手引以為豪的功能給集成到俺自己的軟件中來。
第一步,先查資料。以關鍵字“反轉片”+“算法”在google搜索,搜到的都是說“光影魔術手”這效果多NB多NB的文章,沒參考意義。
第二步,在金山詞霸網(wǎng)上輸入“反轉片”,查出來英文單詞是 “reversal film”,然后在google scholar中搜索 “reversal film algorithm”,沒介紹的。在 google 中搜索“reversal film algorithm”,沒有一篇文章講了實質(zhì)性內(nèi)容的。進 google code search 搜索 “reversal film”,沒一個有實質(zhì)性內(nèi)容的。進 cnki 搜索 “reversal film”和“反轉片”,沒一個有實質(zhì)性內(nèi)容的。這下完蛋了,沒參考的,眼看要個屁了。
第三步,反轉片這個效果很重要,一定有很多人用 photoshop 處理過。搜“反轉片”,專門找介紹怎么用 photoshop 進行反轉負沖處理的文章。找到幾篇講如何手動進行反轉負沖特效處理的文章,比如這一篇:http://www.windsn.com/article.asp?id=478。這篇文章中的效果是很NB的。通過閱讀這篇文章發(fā)現(xiàn),“反轉片”僅僅是點操作即可,它與像素的鄰域無關,與圖像的統(tǒng)計信息無關。
第四步,天空一聲巨響,頭腦一片閃亮。通過第三步,可以推測,反轉負沖實際上只是一個 RGB 空間到 RGB 空間的映射而已。只需要對于RGB空間的任意一個顏色,計算出它所對應的顏色,做一個替換即可。
第五步,如何尋找這個映射呢?利用歸約解決問題。
Udi Manber 的《算法引論-一種創(chuàng)造性的方法》第10章《歸約》的引言部分講了這樣一個故事——
有人問一個數(shù)學家和她的丈夫如下問題:假設你在地下室,想燒開水怎么辦?數(shù)學家說,她會上到廚房并在那里燒水。她的丈夫回答類似。那人繼續(xù)問:假設你在廚房,想燒開水怎么辦?她丈夫回答說:“這很容易的,將水壺灌滿然后點燃煤氣!倍鴶(shù)學家回答:“我的答案更簡單。到地下室去,在那里我已經(jīng)知道如何解決這個問題了!
就讓我們回到“地下室”去解決這個問題。前面說過,光影魔術手可以實現(xiàn)反轉片的效果。因此,建立一張圖片,讓這張圖片上包含所有的RGB顏色值,然后用光影魔術手去處理這張圖片,得到的效果圖另存下來,這就得到了一個RGB空間到RGB空間的映射。通常,RGB的每一個Channel是1個Byte,那么將全部的RGB顏色值放到一張圖片上去,這張圖片就太大了,需要256×256×256個像素。為了減少處理量,對RGB空間進行采樣,只選擇Channel值為偶數(shù)的色彩,這樣,就把RGB空間壓縮到 128×128×128大小了,也就是一張1024×2048的圖片即可。下面是生成算法:
ImageRgb24 img = new ImageRgb24(1024, 2048);
for (int x = 0; x < 128; x++)
{
for (int y = 0; y < 128; y++)
{
for (int z = 0; z < 128; z++)
{
int index = x * 128 * 128 + y * 128 + z;
img[index] = new Rgb24(x * 2, y * 2, z * 2);
}
}
}
將上面的圖片存為 bmp 格式:
用 光影魔術手 的5種反轉片特效分別進行處理,另存為5個 bmp 文件。每一個bmp文件,代表1種反轉片特效,假設某個特效的 bmp 的圖儲加載在一個名為 img 的 ImageRgb24 中,則 img[color.Red / 2 * 128 * 128 + color.Green / 2 * 128 + color.Blue/2] 就是色彩 color 反轉片處理后的色彩了。下面是使用“濃郁色彩”bmp圖片映射后的效果圖,是不是和光影魔術手處理結果很像呢?
通過對光影魔術手的進一步分析,發(fā)現(xiàn)它的反轉片特效并不完全是點操作,比如說,截取一張圖片的一部分,處理后相同位置的像素和全張圖片處理后相同位置的像素并不一樣,而是有比較小的差異?赡芩鶕(jù)色彩的概率分布進行了進一步的處理。不過無所謂了,前面這些已經(jīng)夠用了。
想起了讀研究生時的一個故事。老師布置了閱讀題目,讓寫一份讀書報告。我將那個主題的文章查了幾十篇,然后進行資料分類,寫出了一篇很漂亮的讀書報告。很幸運的被老師選為3份最優(yōu)秀的讀書報告,上講臺去講。我這份報告寫得很好,但是報告里寫的內(nèi)容我是完全不明白,結果講的一塌糊涂。不一定非要懂才能寫得好一份報告,你只需要善于歸納總結即可。
到目前為止,反轉片的原理俺依然是毫無頭緒,但問題已經(jīng)解決了——我成功將這一特效用寥寥幾行代碼實現(xiàn),集成在我的程序中!解決問題是一門藝術。