問題如下:
也就是在一張照片裡,已知有個長方形的物體,但是經過了透視投影,已經不再是規則的長方形,那麼如何提取這個圖形裡的內容呢?這是個很常見的場景,比如在博物館裡看到一幅很喜歡的畫,用手機找了下來,可是回家一看歪歪斜斜,腦補原畫內容又覺得不對,那麼就需要算法輔助來從原圖裡提取原來的內容了。不妨把應用的場景分為以下:右上:295.6, 118.4
右下:172.4, 311.3
左下:2.4, 202.4
把這四個坐標按如上順序放到一個叫corner的變量裡。如果我們打算把這幅圖案恢復到一個300x400的圖像裡,那麼按照對應的順序把下面四個坐標放到一個叫canvas的變量裡: 左上:0, 0右上:300, 0
右下:300, 400
左下:0, 400
假設原圖已經用OpenCV讀取到一個叫image的變量裡,那麼提取紙張圖案的代碼如下:1 M = cv2.getPerspectiveTransform(corners, canvas) 2 result = cv2.warpPerspective(image, M, (0, 0))把左圖剪裁出來,去掉紅點後試了試,結果如下: 當然,其實這一步用Photoshop就可以了。。
1 image = cv2.pyrMeanShiftFiltering(image, 25, 10)
因為主要目的是預處理降噪,windows size和color distance都不用太大,避免浪費計算時間還有過度降噪。降噪後可以看到桌面上的紋理都被抹去了,紙張邊緣附近干淨了很多。然而這還遠遠不夠,圖案本身,和圖像裡的其他物體都有很多明顯的邊緣,而且都是直線邊緣。
2) 紙張邊緣檢測
雖然降噪了,可是圖像裡還是有很多邊緣明顯的元素。怎麼盡量只保留紙張的邊緣呢,這時候可以考慮用分割算法,把圖像分為紙張部分和其他部分,這樣分割的mask邊緣就和紙張邊緣應該是差不多重合的。在這裡可以考慮用GrabCut,這樣對於簡單的情況,比如紙張或畫布和背景對比強烈的,直接把圖像邊緣的像素作為bounding box就可以實現自動分割。當自動分割不精確的情況下再引入手動輔助分割,具體到我這裡用的例子,背景和畫面接近,所以需要手動輔助: 結果如下: 可以看到,分割後的結果雖然能基本區分紙張形狀了,可是邊緣並不准確,另外鍵盤和部分桌面沒能區分開來。這時可以繼續用GrabCut+手動標注得到只有紙張的分割。或者為了用戶友好的話,盡量少引入手動輔助,那麼可以考慮先繼續到下一步檢測邊緣,再做後期處理。假設我們考慮後者,那麼我們得到的是如下的mask: 這個mask並不精確,所以不能直接用於邊緣檢測,但是它大致標出了圖片裡最明顯的邊緣位置所在,所以可以考慮下面的思路:保留降噪後位於mask邊緣附近的信息用於真正的邊緣檢測,而把其他部分都模糊處理,也就是說基於上面得到的mask做出下面的mask用於模糊處理: 基於這個mask得到的用於邊緣檢測的圖像如下: 用canny算子檢測出邊緣如下:正是要的結果。
接下來計算四條線的交點,方法點這裡。因為有4條線,會得到6個結果,因為在這種應用場景中,方形的物體在透視變換下不會出現凹角,所以直接捨棄離紙張中心最遠的兩個交點就得到了四個角的坐標,結果如下:
這樣就回到了一開始四角坐標已經得到的情況,直接進行透視變換就行了。
寫了這麼多,其實有一條至關重要的假設,甚至可以說是最關鍵的步驟之一我一直沒提,那就是Camera Calibration,如果有相機的情況下,meta data都知道,那麼需要先坐Camera Calibration才能知道紙張或者畫布的原始尺寸。我這裡試的例子當然是沒有的,也可以有,相應的算法OpenCV裡也有現成的,不過即便如此還是非常麻煩,所以我的所有流程都是默認原始尺寸已經獲得了。再說了,就算沒有,變換回方形之後使用者憑感覺進行簡單軸縮放都比Camera Calibration方便得多。。
--------------------------------------分割線 --------------------------------------
Ubuntu Linux下安裝OpenCV2.4.1所需包 http://www.linuxidc.com/Linux/2012-08/68184.htm
Ubuntu 12.04 安裝 OpenCV2.4.2 http://www.linuxidc.com/Linux/2012-09/70158.htm
CentOS下OpenCV無法讀取視頻文件 http://www.linuxidc.com/Linux/2011-07/39295.htm
Ubuntu 12.04下安裝OpenCV 2.4.5總結 http://www.linuxidc.com/Linux/2013-06/86704.htm
Ubuntu 10.04中安裝OpenCv2.1九步曲 http://www.linuxidc.com/Linux/2010-09/28678.htm
基於QT和OpenCV的人臉識別系統 http://www.linuxidc.com/Linux/2011-11/47806.htm
[翻譯]Ubuntu 14.04, 13.10 下安裝 OpenCV 2.4.9 http://www.linuxidc.com/Linux/2014-12/110045.htm
--------------------------------------分割線 --------------------------------------
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2015-01/111962p2.htm