HTC最新手機M8附加的新功能、最近很火紅的UFocus到底是怎麼做的?
從影像處理、電腦視覺演算法的角度,原理作法細節一次理解!(粗略的…)

圖左至右分別為 清晰影像、disparity map與模擬DOF結果
(圖片來自http://www.dofpro.com/tutorial1.htm)
1. 先拍兩張完全清楚的影像!
我猜如果HTC夠有錢,相機模組大可使用EDOF CMOS,確保整張影像的清析:目前UFocus的罩門是無法抵抗近物景深模糊,也就是一開始拍的影像模糊會造成stereo-matching錯誤。當然HTC M8目前也沒有讓模糊影像變清楚的方法
至於EDOF(NOKIA E7有使用)原理,基本上就是擴增景深,利用一個特殊的散射鏡片達到depth invariant point spread function,再套用已經校正好的point spread function作deconvolution,還原回全幅對焦的影像。
這個題目早在1990年哈伯天文望遠鏡凸垂的時候就被解決;現在由於生醫科技需要顯微技術,而又因為顯微鏡的淺景深造成物體模糊,所以這項技術仍在蓬勃發展,有網友強調模糊影像是無法救回顯然是錯誤的,隨便google deblur或deconvolution就可以找到讀不完的paper。
2. 進行stereo影像的rectification
![]()
http://en.wikipedia.org/wiki/Image_rectification
原始的雙影像可能是1的general case,這個三角形的幾何關係我們稱之為epipolar geometry,其中有許多有趣的特性不綴述。為了加速運算需要進行image rectification將兩影像warping至同一個與base line平行之平面如圖2。
這邊由於M8的影像已經對齊了(平行排列,並且解析度較低的副鏡頭經過一個Affine Transformation放大對齊),所以直接是步驟2,也就是兩影像位於同一個平面上。
3. stereo matching,也就是深度計算
上圖2的藍色水平線我們稱之為epipolar line,在左右圖epipolar line進行搜尋,如圖是尋找樹梢,一般來說是固定左圖特徵位置,在右圖作line search,尋找最相似的區塊;實作上由於組裝和校正誤差,可能要多搜尋3~5個pixel的高度。這部分牽涉到了photo-consistency、depth constrain等搜尋演算法強化準度與速度。
如果左右圖影像有下列特性則非常容易造成比對錯誤
- repeated pattern,畫面中有太多相似的物體,如大樓窗戶
- occlusion,物體間的互相遮擋使左右圖看到影像不同,當然左圖看到的東西無法在右圖被找到,自然的深度就錯誤。各位可以實驗把一個瓶子拿在眼前,試著單看左右眼的影像。
- blur,模糊的影像自然沒有高頻細節來描述區塊! 所以比對會變得更困難,但某種程度上是可用的(不要太糊)
- object edge,物體的邊緣容易錯誤,由於CMOS bayer pattern需要被demosaic的關係邊緣pixel的精準度是不高的!這可能也是HTC想把副鏡頭cost down的原因之一(反正都不準嘛~)
幸運的是,世界上有一群瘋子,每天都在點pixel想辦法讓這件事情變得更好!middlebury大學甚至還弄出了一個benchmark網站要整死世上所有研究生,甚至還有一個全自動的上傳與評價系統,讓大家在上面為了幾個pixel的準度天天爆肝(http://vision.middlebury.edu/stereo/eval/),有興趣的宅宅們可以在網站上review世界上最準確的演算法論文
http://vision.middlebury.edu/stereo/eval/
當左右影像搜尋到相同物體時,其在epipolar line的距離(左圖藍框至右圖藍框的距離,單位是pixel)我們稱之為disparity,其倒數就是depth深度,可被換算成真實物距,這可能也是M8對焦快速的其中一個原因。當這件事情很密集的作成全畫面的點對應時,下圖就出來拉~

dsparity map,越亮則是disparity越大,倒數則代表depth,表離我們鏡頭比較近
4. Depth of field Mask,選出要保留清楚的範圍
這也是M8作得不優的其中一個地方
我們從disparity map選擇一個值,保留這個值前後幾個disparity的pixel作為清楚的地方。如下圖我們決定僅讓第一個旗子清楚
HTC的演算法在depth精度不足之下,選擇到的範圍是很粗糙的,在軟體模糊的物體邊界反而可能出現清楚的pixel!!有可能常出現在畫面邊緣處!(由於兩影像看到的範圍不同)
或是該清楚的地方被變成模糊的,這個比較不容易察覺,最常見是髮絲部分
5. 製作blur的背景
這也是M8作得不優的第二個地方
DOF模擬,根據離焦平面的距離不同,point spread function的大小是也不同,基本上離合焦平面越近則越小反之越大,模糊程度要與合焦平面距離成正比,如下圖。HTC不知道為啥似乎在point spread function的大小控制上很不自然,模糊部分似乎都套用同一個或是差不多的size,並沒有遵循這個光學原則
各位可以嘗試斜拍多個點光源,觀察光暈是否有大小區別
![]()
中央的PSF表合焦平面,左右各表離合焦平面較遠的PSF
[EDIT] 後來聽說有做這部分!但是我感覺沒有很明顯,也可能是遠距離的depth幾乎一樣所以分別不大,還是得先把disparity太短的問題改善才是
6. blending,合成清楚和模糊影像
M8竟然用一個alpha blending疊加兩影像就想草草了事!
有點像這樣\[I(x)=0.5*A(x)+0.5*B(x)\]
實際上應是根據與焦平面距離調整比例,並且權重加總為1保證亮度不改變
\[I(x)=W_A*A(x)+W_B*B(x)\]
\[ W_A+W_B=1\]
各位可以嘗試斜拍一個連續平面,保證UFocus的效果會有斷層!
下圖借01網友照片一用(路邊的浣熊)。注意該景深應模糊的字中間部分竟然是清楚的!
由於兩個圖層的影像(清楚+模糊)只是使用半透明疊加,在清楚的影像中加上了外圈的模糊光暈,有誰見過這種不自然景深模糊?附上全圖的模糊效果供參考
較合理的作法應是利用poisson image editing的方法,在gradient domain進行原影像的reconstruction才會自然
HTC的作法顯然是上圖右二…
總結UFocus作法的缺點與改進
stereo matching真的很厲害! 但是我猜八成也是買人家IP的,不是magic lab或studio software作的,軟體後端相對粗糙很多。
以我嚴苛的標準,目前只有light field才能稱作是產品,M8的UFocus僅是加值服務而已
1. 物體邊緣不自然
解法1:增加副鏡頭解析度(喔拜託別用UltraPixel了拉!)、換好一點的stereo matching演算法、quantization精度提高
解法2:既然深度不準確,必須同時考慮物體edge優化邊緣,使用grabcut演算法同時考慮image gradient與depth做optimization(很重要所以變粗)
2. 模糊程度不自然
解法:point spread function須考慮與焦平面距離縮放(depth-aware blurring )
我嘴砲M8作不出來可能是工程師死腦筋想硬幹multi-layer blurring作bending。實作上可建立一個Integral Image,然後在計算blurring的時候根據不同的depth來對integral image取值作該點pixel的加權,記憶體就只要一份影像大小就夠了,取任一模糊程度pixel僅要3個加減法而已,很適合ASIC加速,不用depth精度這麼多張影像~~(可能是256個影像,當然我只是嘴砲沒下去寫程式XD)。總比\(2*10^6*3*256\)這麼多記憶體好…
3. 圖層疊加不自然
解法1:使用poisson image blending,嘗試去optimize一個gradient domain的poisson equation;或考慮快一點就是multi-band blending,無論是用FFT或wavelet解法
解法2:抄lytro,建立48層(我嘗試decode lytro的RAW檔LFP發現的)的focus layer(針對不同深度合焦的影像)做blending,depth斷層會很滑順,而不是僅用兩張影像疊圖,這才是最自然的解法,但是手機上做可能很吃力,並且也不知道會不會侵犯專利,但做成ASIC應該就加密了也不會被告~
4. 近物罩門
解法:用deconvolution解太近的模糊部分~
5. 建議新增有趣應用,他們竟然沒想到耶!!下一版作出來要給我獎金才對!XD
改變point spread function形狀進行模糊(如愛心、雪花),改變散景形狀,成本低效果美! 廣告應該要主打這個才有原創性才對! 後對焦太氾濫了!







相較於外國大廠與學術研究機構,台灣做 vision computing 特別是 multiple-view reconstruction 的人真的不多,中文資源很稀少,但這些都是打造明日 IT 的關鍵技術,希望能有更多這一類的好文拋磚引玉。
台灣公司普遍不重視核心技術,大多以系統廠思維導向,Multi-View Stereo與Computer Vision技術在台灣仍不受重視;國內展覽看到的東西多半是OpenCV兜出來的DEMO罷了,少見到有國外如德州儀器大廠等為ISP專設一顆ASIC做處理,國內廠沒有這個遠見和膽量。我也希望大公司能多發展這類新技術,這樣才好找工作XDD
HTC的做法像趕鴨子上架,演算法仍然不夠細緻,但也不難理解裡面工程師的辛勞。HTC Studio Software部門被解散重組數次不是沒原因的…
請問 M8 使用的 dual-cam rectification 方式為何呢?
組裝上已經對齊camera center與 base line平行
基本上已經達成rectified image的定義了,僅在兩顆鏡頭解析不同下
需將副鏡頭影像乘上一個3×3的affine transformation matrix,做一些scale和translation align的校正
不過這也只是我的猜測罷了,供您參考
之前使用過 OpenCV 做 stereo rectification , 但是效果有實不理想, 所以想請教有沒有其它比較有效的方式?
感謝.
最近比較懶,等有空再寫tutorial
已經寄信給你了,以前的作業報告..
多謝你的說明。想知道的是這些改善的方式,是否可以透過韌體達成? M8 的硬體已不會變動,若要提昇相機的成像功能,只能力用韌體更新的方式更換演算法了。
Firmware能做的只有調整參數! ISP等級的演算法不是firmware做的,處理的都是pipeline成千上萬的pixel耶
如果是DSP或許可以做一些修改,但是幅度不大,不太可能做出我提的改進,因為DSP的fucntion多是包好的
學術上多半是FPGA先行做一個初步硬體,再考慮成本開成ASIC
我提的做法如果不是給手機CPU算(慢!)
那只好再開一顆ASIC加速,你可以等M100看看HTC會不會做?XD
最後一個建議改一下現在軟體應該可以輕鬆實現~
請問原po的意思是
m8的副鏡頭可能是用
1.EDOF cmos sensor搭配去做stereo matching嗎?
還是
2.用普通的cmos sensor?
M8目前是普通CMOS當副鏡頭
請問原Po圖層疊加lytro (針對不同深度合焦的影像)要怎麼去實現?
或者是僅用兩張影像,如何疊加效果會比較好!
多張影像的方法文章中有提到了,基本上就是針對距離作blending,可以想像已經錄下所有對焦行程的影像再行合成,類似LG的magic對焦
兩張的重點就是邊緣要準確!
1. 怎麼知道副鏡頭是普通鏡頭?
2. 兩顆鏡頭的距離那麼近, 距離遠一點, disparity 恐怕就不易區分了
1. 有些事情不能說
2. 這部分是有由來的,根據EVO 3D的悲劇,兩顆拉開距離的鏡頭容易在手持被遮擋影響使用。這邊他們下了很大功夫校正,結論是有些事情不能說XD。
或者應該問, 您怎麼知道它不是 EDOF 鏡頭?
有些事情不能說
瞭解, 那就 stereo camera 來說, distance 這麼近, 三四公尺遠的物體, 恐怕就不易區分, 對嗎?
為了維持單手操作上的方便,鏡頭配置並不同ideal case,必須要有取捨! 不然當年EVO 3D為啥沒做出來? (其實是
高層沒想到…)你的說法不正確,請參考narrow view stereo Camera
或是large focal length calibration
Sorry! 不太懂您的意思… 主鏡頭與副鏡頭的距離如果只有 1cm, 那麼, 四五公尺以外的物體之視差, 大概只有 1, 2 pixels
(我沒有規格, 無法精算), 十公尺以外的物體, 視差恐怕都是 1 pixel 以內, 無法辨識深度差異…
應該是這樣吧?
對,要怎麼拉開投影距離呢?拉開又會有什麼副作用 XDD
“你的說法不正確,請參考narrow view stereo Camera
或是large focal length calibration”
謝謝, 我 check 一下
看規格, HTC M8 rear camera, focal length 是 28mm (eff), 中規中矩
可惜 secondary camera 沒提供
副像機這部分牽涉到一些算法核心,我不能提供細節
你有興趣可以拆機研究鏡頭特性,一些逆向工程應該不難推出原理
同時,你不可能拿到兩張影像的source,這邊要保護專利,連HTC恐怕都沒有
API提供的僅會有算好的depth
OK, thanks a lot!
一般來說, 拉長焦距可以讓 disparity 容易解析一點, 只是像差會變嚴重點, 我再推敲一下…
是貴公司的new project? 我也是113校友,其實你要不要直接去找他們問比較快,也在竹科阿….
FOV 似乎也有幫助…
這不是我們的 project, 但我以前曾經做過幾次類似計劃, 也被砍過幾次計劃
老闆看到雙鏡頭, 通常都不會太高興, 很容易有放棄的念頭
如果能瞭解更好的解法, 也不枉費過去的歲月
哈,我完全理解你們project被砍的感受XD
在心有不甘的情況下當然會對HTC的做法感興趣
甚至期望拿來當下次提project的籌碼! (人家HTC都這麼做了之類…)
在Google camera上剛推出的Lens Blur mode 似乎比m8的效果好,
http://googleresearch.blogspot.sg/2014/04/lens-blur-in-new-google-camera-app.html
而且硬體不需要雙鏡頭 (軟體需android 4.4),
這點想請教adahbingee怎麼看?
本來雙鏡就不是必要! 用錄的再根據加速度計擷取適當距離的frame也是一個解法,同樣可以獲得stereo image,只要小心處理畫面邊緣不同視角的內容就可以做得不錯(最簡單就是crop),早些的手機平台論文幾乎都是這麼做的
甚至由於擷取的是影片,有遠超過兩張以上的照片,只要控制兩兩間的距離不要太近(narrow view),MVS的精度和完整度不是stereo可比擬的,詳見Furukawa的PMVS paper;速度上計算一個3D點僅有3個自由度,使用conjugate gradient僅最多需要3個iteration就可以收斂,非常適合高度平行化的多核手機平台
但如果雙鏡加上ASIC即時產生深度,即可做到如kinect fusion等級的即時重建,這時硬體上的優勢就出來了! 前者是精算,後者是掃描! 進入的資料量又是另一個級距差了!
我們可以等看看他們什麼時候要開ASIC…而google早已有Project Tango在實做硬體掃描了,部門主管 Johnny Lee之前就任職於微軟Kinect部門
台灣廠商走得慢,還有很大一步要追!
再者,後端的軟體也很重要,HTC在做這塊的人沒有3D相關領域知識,可以算是外行,幾乎都是影像處理和UI背景的工程師,有再好的深度圖也無法產生自然的結果
順帶一提,Furukawa現在任職於Google,不過之前注意到是偏向Maps的場景重建(重建羅馬計畫)和博物館導覽(Image Based Rendering類的),HTC給這種薪水要怎打世界最強?XD
天啊我超嘴砲XDD,實際上這件事情真的很難,非常非常非常難(
看看自己努力兩年的論文也是垃圾一篇);我們要相信台灣之光!你好,我是名三维动画制作者。从M8双镜头发布以来就一直关注着。 UFocus 诞生时就猜到其实原理跟三维软件渲染景深通道合成差不多。我看完了文章又看完了评论,留意到你说“你不可能拿到兩張影像的source”,是指不可能拿到depth map(景深贴图)么?其实我一直在苦于寻找能够从m8中提取景深贴图的方式,这样在photoshop nuke之类的软件中,人工对景深贴图和原图进行匹配,得到更逼真的景深而不依靠htc one m8本身的程序虚化。可是我一直不知道如何得到这张景深贴图(图片),种种迹象表明景深信息也存在于那唯一的一张jpg里面,不知道有没有什么方法能够得到那张景深?
取得depth map應該是可以的參考HTC dev
https://www.htcdev.com/devcenter/opensense-sdk/htc-dual-lens-api
我提到不能取得source是指經rectified的影像.這部分必須要保護IP公司的演算法核心
orz 谢谢,可惜我并不是一名开发者……对程序开发这一块儿,不是很了解。其实我也跑去htc的开发者网页找了一圈,这个sdk也下下来了……可是不太会用。看来只有等第三方或者htc官方来提供方法了……还是谢谢你
有沒有 narrow view stereo Camera, large focal length calibration 的 paper 可以推薦的?
應該不難找耶!
1
2
3
Thank you very much!
“是貴公司的new project? 我也是113校友,其實你要不要直接去找他們問比較快,也在竹科阿….”
您是指 HTC 還是 A 開頭的公司?
應該是A
在下面有可能取得兩張影像的source嗎?
http://forum.xda-developers.com/showthread.php?t=2760705
請問是要我幫您讀英文嗎?XD
請教一下, 目前這樣的技術可以做到怎樣的偵測距離, 以及距離解析度?
想像物體如果無限遠,投影在兩影像上幾乎是同一點,此時就無法判斷深度了。具體公式還要推敲一下。
網路上看到, main lens 是 OV4688 focal length 3.82mm, secondary lens 是 OV2722
因為 OV2722 pixel size 只有 1.4um, OV4688 pixel size 是 2um
感覺似乎 seconday lens 挑相似的 eff focal length (不用 tele lens),
再把兩邊 scaling 成一樣, e.g. 1920×1080, 就可以算深度了
以 1.4um 為例,
dp = 1.4um, Z = 4000mm, f = 3.82mm, b = 20mm
dZ = Z^2*dp/(f*b)
深度解析度是 29cm, 感覺夠用了呀.
我有弄錯什麼嗎?
感覺閣下比較專業阿! 不敢班門弄斧,說實在還真的沒細推過
sorry久沒接觸 stereo matching ,敏銳度不佳XD,可能要先sync一下符號
\[\begin{equation}\frac{\left|x_1- x_2\right|}{f}=\frac{b}{Z}\end{equation}\]
假設兩鏡已經位於同一 baseline (rectified),同一種 sensor 和 lens,根據相似三角型有上式關係, \(f\) 為兩鏡的 focal length , \(x_1,x_2\) 代表一個深度為 \(Z\) 的3D點在同一系統的影像座標,其 disparity 為 \(\left|x_1-x_2\right|\) , \(b\) 則是兩個光軸的距離,將 disparity 簡化為 \(d\)
\[\begin{equation}\frac{d}{f}=\frac{b}{Z}\end{equation}\]
以 1920 pixel 寬的影像 \(d\) 最大 1920*0.0014 = 2.688mm ,20*3.82/2.688=28.4mm
下圖表 \(d\) 橫軸與可量測 \(Z\) 縱軸之關係,縱軸為log axis。

pixel 寬 0.0014mm , baseline 距離 \(b\) 20mm , \(f\) 3.82mm
後面就是計算在某一個固定深度 \(Z\) 下,物體要在一個平面移動多少才能改變 1 pixel 移動,幾合關係可以明確手畫定義出來,但是數學忘光了
所以沒辦法驗證下去…sorry
題外話是開發遇到的問題也不代表產品結果…(只是非常不負責任的閒聊罷了…
請教為何需要兩張影像作blending?
直接依照depth map對原圖每個pixel作不同程度的blur
然後使用者選取的區域不要做blur
應該就有一張有景深的照片了
不太清楚為何要做兩圖疊加?
謝謝~
我覺得你的方法PQ比較好,但by pixel做不同程度的low pass,不用的理由有可能是手機運算不夠快,使用者可能沒辦法隨點隨看結果,考慮到使用經驗的妥協算法(但可以用來preview阿!
所以幫忙想一些加速法…
如果RAM夠大可以建立幾個不同程度 low pass image 做內插來近似,超過11 taps可以用 FFT 跑 convolution 比較快
(當然要深度精度這麼多個是不可能的. Eg. 10張 low pass image)
演算法是根據結果猜測,他們的影像 artifacts 看起來比較接近 alpha blending 結果,所以我整個思路都被帶走了XD,應該還可以改進