HTC M8 UFocus 原理

HTC最新手機M8附加的新功能、最近很火紅的UFocus到底是怎麼做的?

從影像處理、電腦視覺演算法的角度,原理作法細節一次理解!(粗略的…)

depth

圖左至右分別為 清晰影像、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世界上最準確的演算法論文

middle

http://vision.middlebury.edu/stereo/eval/

當左右影像搜尋到相同物體時,其在epipolar line的距離(左圖藍框至右圖藍框的距離,單位是pixel)我們稱之為disparity,其倒數就是depth深度,可被換算成真實物距,這可能也是M8對焦快速的其中一個原因。當這件事情很密集的作成全畫面的點對應時,下圖就出來拉~

chessDM

dsparity map,越亮則是disparity越大,倒數則代表depth,表離我們鏡頭比較近

4. Depth of field Mask,選出要保留清楚的範圍

這也是M8作得不優的其中一個地方

我們從disparity map選擇一個值,保留這個值前後幾個disparity的pixel作為清楚的地方。如下圖我們決定僅讓第一個旗子清楚

chessDMMask

 

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網友照片一用(路邊的浣熊)。注意該景深應模糊的字中間部分竟然是清楚的!

aaa

由於兩個圖層的影像(清楚+模糊)只是使用半透明疊加,在清楚的影像中加上了外圈的模糊光暈,有誰見過這種不自然景深模糊?附上全圖的模糊效果供參考

aab

較合理的作法應是利用poisson image editing的方法,在gradient domain進行原影像的reconstruction才會自然

poisson

上圖來源

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

apture

改變point spread function形狀進行模糊(如愛心、雪花),改變散景形狀,成本低效果美! 廣告應該要主打這個才有原創性才對! 後對焦太氾濫了!

網址1、網址2

在〈HTC M8 UFocus 原理〉中有 47 則留言

  1. 相較於外國大廠與學術研究機構,台灣做 vision computing 特別是 multiple-view reconstruction 的人真的不多,中文資源很稀少,但這些都是打造明日 IT 的關鍵技術,希望能有更多這一類的好文拋磚引玉。

    1. 台灣公司普遍不重視核心技術,大多以系統廠思維導向,Multi-View Stereo與Computer Vision技術在台灣仍不受重視;國內展覽看到的東西多半是OpenCV兜出來的DEMO罷了,少見到有國外如德州儀器大廠等為ISP專設一顆ASIC做處理,國內廠沒有這個遠見和膽量。我也希望大公司能多發展這類新技術,這樣才好找工作XDD

      HTC的做法像趕鴨子上架,演算法仍然不夠細緻,但也不難理解裡面工程師的辛勞。HTC Studio Software部門被解散重組數次不是沒原因的…

        1. 組裝上已經對齊camera center與 base line平行
          基本上已經達成rectified image的定義了,僅在兩顆鏡頭解析不同下
          需將副鏡頭影像乘上一個3×3的affine transformation matrix,做一些scale和translation align的校正

          不過這也只是我的猜測罷了,供您參考

          1. 之前使用過 OpenCV 做 stereo rectification , 但是效果有實不理想, 所以想請教有沒有其它比較有效的方式?

            感謝.

          2. 最近比較懶,等有空再寫tutorial
            已經寄信給你了,以前的作業報告..

  2. 多謝你的說明。想知道的是這些改善的方式,是否可以透過韌體達成? M8 的硬體已不會變動,若要提昇相機的成像功能,只能力用韌體更新的方式更換演算法了。

    1. Firmware能做的只有調整參數! ISP等級的演算法不是firmware做的,處理的都是pipeline成千上萬的pixel耶

      如果是DSP或許可以做一些修改,但是幅度不大,不太可能做出我提的改進,因為DSP的fucntion多是包好的

      學術上多半是FPGA先行做一個初步硬體,再考慮成本開成ASIC

      我提的做法如果不是給手機CPU算(慢!)
      那只好再開一顆ASIC加速,你可以等M100看看HTC會不會做?XD
      最後一個建議改一下現在軟體應該可以輕鬆實現~

  3. 請問原po的意思是

    m8的副鏡頭可能是用
    1.EDOF cmos sensor搭配去做stereo matching嗎?
    還是
    2.用普通的cmos sensor?

  4. 請問原Po圖層疊加lytro (針對不同深度合焦的影像)要怎麼去實現?
    或者是僅用兩張影像,如何疊加效果會比較好!

    1. 多張影像的方法文章中有提到了,基本上就是針對距離作blending,可以想像已經錄下所有對焦行程的影像再行合成,類似LG的magic對焦

      兩張的重點就是邊緣要準確!

    1. 1. 有些事情不能說
      2. 這部分是有由來的,根據EVO 3D的悲劇,兩顆拉開距離的鏡頭容易在手持被遮擋影響使用。這邊他們下了很大功夫校正,結論是有些事情不能說XD。

    1. 為了維持單手操作上的方便,鏡頭配置並不同ideal case,必須要有取捨! 不然當年EVO 3D為啥沒做出來? (其實是高層沒想到…)

  5. Sorry! 不太懂您的意思… 主鏡頭與副鏡頭的距離如果只有 1cm, 那麼, 四五公尺以外的物體之視差, 大概只有 1, 2 pixels
    (我沒有規格, 無法精算), 十公尺以外的物體, 視差恐怕都是 1 pixel 以內, 無法辨識深度差異…

    應該是這樣吧?

    1. 副像機這部分牽涉到一些算法核心,我不能提供細節
      你有興趣可以拆機研究鏡頭特性,一些逆向工程應該不難推出原理
      同時,你不可能拿到兩張影像的source,這邊要保護專利,連HTC恐怕都沒有
      API提供的僅會有算好的depth

  6. FOV 似乎也有幫助…

    這不是我們的 project, 但我以前曾經做過幾次類似計劃, 也被砍過幾次計劃
    老闆看到雙鏡頭, 通常都不會太高興, 很容易有放棄的念頭
    如果能瞭解更好的解法, 也不枉費過去的歲月

    1. 哈,我完全理解你們project被砍的感受XD
      在心有不甘的情況下當然會對HTC的做法感興趣
      甚至期望拿來當下次提project的籌碼! (人家HTC都這麼做了之類…)

    1. 本來雙鏡就不是必要! 用錄的再根據加速度計擷取適當距離的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,實際上這件事情真的很難,非常非常非常難(看看自己努力兩年的論文也是垃圾一篇);我們要相信台灣之光!

  7. 你好,我是名三维动画制作者。从M8双镜头发布以来就一直关注着。 UFocus 诞生时就猜到其实原理跟三维软件渲染景深通道合成差不多。我看完了文章又看完了评论,留意到你说“你不可能拿到兩張影像的source”,是指不可能拿到depth map(景深贴图)么?其实我一直在苦于寻找能够从m8中提取景深贴图的方式,这样在photoshop nuke之类的软件中,人工对景深贴图和原图进行匹配,得到更逼真的景深而不依靠htc one m8本身的程序虚化。可是我一直不知道如何得到这张景深贴图(图片),种种迹象表明景深信息也存在于那唯一的一张jpg里面,不知道有没有什么方法能够得到那张景深?

      1. orz 谢谢,可惜我并不是一名开发者……对程序开发这一块儿,不是很了解。其实我也跑去htc的开发者网页找了一圈,这个sdk也下下来了……可是不太会用。看来只有等第三方或者htc官方来提供方法了……还是谢谢你

  8. “是貴公司的new project? 我也是113校友,其實你要不要直接去找他們問比較快,也在竹科阿….”

    您是指 HTC 還是 A 開頭的公司?

    1. 想像物體如果無限遠,投影在兩影像上幾乎是同一點,此時就無法判斷深度了。具體公式還要推敲一下。

  9. 網路上看到, 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, 感覺夠用了呀.
    我有弄錯什麼嗎?

    1. 感覺閣下比較專業阿! 不敢班門弄斧,說實在還真的沒細推過

      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

      題外話是開發遇到的問題也不代表產品結果…(只是非常不負責任的閒聊罷了…

  10. 請教為何需要兩張影像作blending?
    直接依照depth map對原圖每個pixel作不同程度的blur
    然後使用者選取的區域不要做blur
    應該就有一張有景深的照片了
    不太清楚為何要做兩圖疊加?
    謝謝~

    1. 我覺得你的方法PQ比較好,但by pixel做不同程度的low pass,不用的理由有可能是手機運算不夠快,使用者可能沒辦法隨點隨看結果,考慮到使用經驗的妥協算法(但可以用來preview阿!

      所以幫忙想一些加速法…
      如果RAM夠大可以建立幾個不同程度 low pass image 做內插來近似,超過11 taps可以用 FFT 跑 convolution 比較快
      (當然要深度精度這麼多個是不可能的. Eg. 10張 low pass image)

      演算法是根據結果猜測,他們的影像 artifacts 看起來比較接近 alpha blending 結果,所以我整個思路都被帶走了XD,應該還可以改進

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *