天天看點

解決問題的藝術:半小時程式設計實作照片的反轉負沖特效

如何直接有效的解決問題是一門藝術。我們是做産品、做系統、做服務的,不是玩技術的,需要做的是在最短的時間内以最有效的方式來解決工作中面對的難題。就在剛才,用了半小時不到時間,俺用一種極其簡單、直接、有效、霸道的方法解決了照片的反轉負沖特效問題。這種解決問題的思路值得總結推廣。

反轉負沖(反轉片)是一種攝影拍攝技術,它通過拍攝後反轉沖洗,得到色彩鮮豔的照片,非常養眼。現在都是數位相機了,可以通過圖像處理算法來模拟反轉片的效果,比如說,“光影魔術手”就提供了5種反轉片特效:(1)素淡人像;(2)淡雅色彩;(3)真實色彩;(4)豔麗色彩;(5)濃郁色彩。且看(5)濃郁色彩的效果:

<a href="http://images.cnblogs.com/cnblogs_com/xiaotie/WindowsLiveWriter/dca752c11278_14DF7/image_2_2.jpg"></a>

左邊是處理前的圖像,右邊是處理後的圖像,可以看到,處理後的圖像顔色格外飽滿。我目前開發的一款圖像處理軟體,一個難題就是處理後的照片色彩會變暗,這個反轉負沖特效的效果正是我所需要的。

且看“光影魔術手”怎樣描繪“反轉片”功能——

“模拟反轉片的效果,是《光影魔術手》最重要的功能之一。經處理後照片反差更鮮明,色彩更亮麗。算法經多次改良後,暗部細節得到最大程度的保留,高光部分無溢出,紅色還原十分準确,色彩過渡自然豔麗,絕無色斑!提供多種模式供使用者選擇,其中人像模式對亞洲人的膚色進行了優化,不會出現膚色偏黃現象。獨有的暗部增補算法不僅增強了暗部, 同時令高光部分的表現更出色,絕對沒有霧感引入。精心設計,專業效果!強烈推薦所有使用者使用! ”

下面且看俺怎麼在半小時内将這個光影魔術手引以為豪的功能給內建到俺自己的軟體中來。

第一步,先查資料。以關鍵字“反轉片”+“算法”在google搜尋,搜到的都是說“光影魔術手”這效果多NB多NB的文章,沒參考意義。

第二步,在金山詞霸網上輸入“反轉片”,查出來英文單詞是 “reversal film”,然後在google scholar中搜尋 “reversal film algorithm”,沒介紹的。在 google 中搜尋“reversal film algorithm”,沒有一篇文章講了實質性内容的。進 google code search 搜尋 “reversal film”,沒一個有實質性内容的。進 cnki 搜尋 “reversal film”和“反轉片”,沒一個有實質性内容的。這下完蛋了,沒參考的,眼看要個屁了。

第四步,天空一聲巨響,頭腦一片閃亮。通過第三步,可以推測,反轉負沖實際上隻是一個 RGB 空間到 RGB 空間的映射而已。隻需要對于RGB空間的任意一個顔色,計算出它所對應的顔色,做一個替換即可。

第五步,如何尋找這個映射呢?利用歸約解決問題。

Udi Manber 的《算法引論-一種創造性的方法》第10章《歸約》的引言部分講了這樣一個故事——

有人問一個數學家和她的丈夫如下問題:假設你在地下室,想燒開水怎麼辦?數學家說,她會上到廚房并在那裡燒水。她的丈夫回答類似。那人繼續問:假設你在廚房,想燒開水怎麼辦?她丈夫回答說:“這很容易的,将水壺灌滿然後點燃瓦斯。”而數學家回答:“我的答案更簡單。到地下室去,在那裡我已經知道如何解決這個問題了。”

就讓我們回到“地下室”去解決這個問題。前面說過,光影魔術手可以實作反轉片的效果。是以,建立一張圖檔,讓這張圖檔上包含所有的RGB顔色值,然後用光影魔術手去處理這張圖檔,得到的效果圖另存下來,這就得到了一個RGB空間到RGB空間的映射。通常,RGB的每一個Channel是1個Byte,那麼将全部的RGB顔色值放到一張圖檔上去,這張圖檔就太大了,需要256×256×256個像素。為了減少處理量,對RGB空間進行采樣,隻選擇Channel值為偶數的色彩,這樣,就把RGB空間壓縮到 128×128×128大小了,也就是一張1024×2048的圖檔即可。下面是生成算法:

ImageRgb24 img = new ImageRgb24(1024, 2048);  for (int x = 0; x &lt; 128; x++)  {      for (int y = 0; y &lt; 128; y++)      {          for (int z = 0; z &lt; 128; z++)          {              int index = x * 128 * 128 + y * 128 + z;              img[index] = new Rgb24(x * 2, y * 2, z * 2);          }      }  }

将上面的圖檔存為 bmp 格式:

<a href="http://images.cnblogs.com/cnblogs_com/xiaotie/WindowsLiveWriter/dca752c11278_14DF7/image_6_2.jpg"></a>

用 光影魔術手 的5種反轉片特效分别進行處理,另存為5個 bmp 檔案。每一個bmp檔案,代表1種反轉片特效,假設某個特效的 bmp 的圖儲加載在一個名為 img 的 ImageRgb24 中,則 img[color.Red / 2 * 128 * 128 + color.Green / 2 * 128 + color.Blue/2] 就是色彩 color 反轉片處理後的色彩了。下面是使用“濃郁色彩”bmp圖檔映射後的效果圖,是不是和光影魔術手處理結果很像呢?

<a href="http://images.cnblogs.com/cnblogs_com/xiaotie/WindowsLiveWriter/dca752c11278_14DF7/image_4_4.jpg"></a>

通過對光影魔術手的進一步分析,發現它的反轉片特效并不完全是點操作,比如說,截取一張圖檔的一部分,處理後相同位置的像素和全張圖檔處理後相同位置的像素并不一樣,而是有比較小的差異。可能它根據色彩的機率分布進行了進一步的處理。不過無所謂了,前面這些已經夠用了。

想起了讀研究所學生時的一個故事。老師布置了閱讀題目,讓寫一份讀書報告。我将那個主題的文章查了幾十篇,然後進行資料分類,寫出了一篇很漂亮的讀書報告。很幸運的被老師選為3份最優秀的讀書報告,上講台去講。我這份報告寫得很好,但是報告裡寫的内容我是完全不明白,結果講的一塌糊塗。不一定非要懂才能寫得好一份報告,你隻需要善于歸納總結即可。

到目前為止,反轉片的原理俺依然是毫無頭緒,但問題已經解決了——我成功将這一特效用寥寥幾行代碼實作,內建在我的程式中!解決問題是一門藝術。

==== 完 ====

本文轉自xiaotie部落格園部落格,原文連結http://www.cnblogs.com/xiaotie/archive/2010/11/30/1891644.html如需轉載請自行聯系原作者

xiaotie 集異璧實驗室(GEBLAB)

繼續閱讀