2013年9月26日 星期四

background removal algogo !

關於這點是研究不完的,能用的演算法之多,符合怎樣的場景使用哪種等,我想這邊不該是講這些的地方,應該留給研究生去研究。
那麼主要講的是基本的圖形演算法的幾個東西 dilation erosion .
我用的演算法非常簡單,基本上就是設定個threshold ,讓顏色能夠透過threshold去作擴張。並且隨著距離作linear decay。
首先透過手在圖片上畫過的路徑取點,作分群演算法取出最大群組的顏色量,以那幾點當作基準點去作Dilation
Dilation
http://www.cs.princeton.edu/~pshilane/class/mosaic/images/dilation.png
不囉說直接看圖大概就知道Dilation在幹嘛,基本上我全用十字的參考去作dilate
http://ostermiller.org/dilate_and_erode.html
這網站對於Dilation有詳盡的implement可以參考。
但是對於程式判斷出來的區塊,用這麼簡易的threshold去作判別出來的區塊是非常殘破的,這時候才是Dilation and Erosion發揮的地方。
首先對自己判斷出來的區塊作fixed times Dilation,之後再對已存在的區塊作the same times Erosion
最後出現的區塊就會非常完整,Dilation and Erosion那步驟吃掉了破碎的像素
整個spirit就如同上述所敘的,很容易吧。。
。。實際上運作起來會死人的
首先假設一張很普通的圖,say 800x600好了,那實際上就有480000個像素,所需要的bitmask就要有480000個,不要太囂張用bitwise那還得在寫一些macro去實作,用最小的uint8好了,也會有480000bytes,那也要將近0.5mb的記憶體,這已經是很小張的圖片以及最保守的bitmask了。
再來就是計算點位的問題,假設你第一步的Dilation不要太多,兩百pixel就夠了,200pixel在800x600的圖來看只吃掉了1/4個距離,也就是說每一步你只能擴張1/4左右的圖片大小,所需要掃描的次數為800x600x200次...恩,我本來跑在simulator覺得沒什麼,還是一樣快,真正跑在ipad3才發現,跑完一次要五六秒。。這還只是average。。
直接講我目前版本的三個步驟final的作法好了
對於那些點存進兩個set container,輪流作reset,將第一次dilate的點存進另一個container,這樣不斷的來回作你想要dilate的次數,這樣可以避免每次都要掃600x800次,但這部份的速率感覺上並沒有比600x800實作良好的continue快許多,畢竟物件也是有效率的問題。
最後的dilation我取20好了,也就是作800x600x20次,速度還是在0.2秒內完成。
最慘的是erosion,最近才發現erosion做了兩秒多,並且這部份似乎好像沒有簡化的方法,直到目前我才想到一個好方法!就是在上述的public dilation中,取出最後一次dilation的點存進container,而直接用那些點去作dilate就夠了,直到這部份的完成,目前整個作一次消背景的動作average time可以壓在一秒左右,並且跑出的效果還ok

如此複雜背景的圖片,多花點步驟還是可以弄出不錯的成果。


我目前覺得值得做的further
1. 回復上一步
2. 手動畫筆清除
3. 手動畫筆復原
4. 自動手動切換
5. 全部重作
6. threshold的調整
7. dilate width的調整
甚至能想到的further應該都有辦法作,目前就先如此了。

沒有留言:

張貼留言