陌生的城市捐晶,陌生的宿舍菲语。我坐在陌生的床上,碼著字惑灵。就在幾天前山上,我還優(yōu)哉游哉地在熟悉的地方思考著邊緣檢測(cè)的真諦,誰(shuí)曾想英支,一個(gè)電話佩憾,就讓我開(kāi)始體驗(yàn)思念的傷。此時(shí)干花,外頭雷聲隆隆妄帘,雨聲瀝瀝。無(wú)事可做池凄,只得對(duì)著熟悉的電腦重新思索著我前些日子思考的問(wèn)題抡驼。
邊緣檢測(cè),聽(tīng)上去那么地簡(jiǎn)單肿仑。但真要重頭開(kāi)始寫(xiě)致盟,卻又沒(méi)那么簡(jiǎn)單。我的工作尤慰,經(jīng)常需要在較為單一的背景中尋找矩形物體馏锡。例如,尋找身份證啦割择,尋找紙幣啦眷篇,以及各種各樣的銀行卡之類的。它們的背景荔泳,不能說(shuō)復(fù)雜蕉饼;他們的邊緣虐杯,都可以認(rèn)為是直的。但工作幾年下來(lái)昧港,似乎最近才有勇氣說(shuō)擎椰,這類問(wèn)題我已經(jīng)胸有成竹了。因而把一些想法記錄下來(lái)创肥,以便日后搜尋达舒,也希望能與讀者分享。
1. Less is More
或許我們總覺(jué)得叹侄,圖像的分辨率越高越好巩搏。我們的民用相機(jī)有很長(zhǎng)一段時(shí)間都在比拼像素?cái)?shù)。這是不科學(xué)的趾代。但我今天并不是要科普選擇相機(jī)還要看什么指標(biāo)贯底。而是想說(shuō),圖像分辨率太高對(duì)圖像處理的影響撒强。其影響就是——
- 慢
- 太清晰了
分辨率高會(huì)使算法變慢禽捆,這一定很好理解,因此我就不解釋了飘哨。關(guān)鍵問(wèn)題是胚想,太清晰了也是錯(cuò)么?是的芽隆。因?yàn)檫^(guò)分清晰會(huì)使紋理太多而影響我們的算法浊服。還記得以前看過(guò)幾張“怪圖”,我?guī)е坨R看它時(shí)摆马,就覺(jué)得上面是一些雜亂無(wú)章的線條臼闻。但脫了眼鏡一看鸿吆,反而清楚了囤采。做圖像處理也是一樣,當(dāng)細(xì)節(jié)太多時(shí)惩淳,我們會(huì)掉進(jìn)細(xì)節(jié)里出不來(lái)蕉毯;但是如果我們讓圖像變模糊、變兴祭纭:即代虾,使用金字塔下采樣算法pyrDown
或者先對(duì)圖像模糊一下,然后再使用imresize
來(lái)縮小——在小尺度下激蹲,一些特征反而變得明顯了棉磨。
因此,如果要搜索高分辨率的圖像的前景邊緣学辱,我一般會(huì)按實(shí)際情況乘瓤,把圖片先下采樣幾次再說(shuō)环形。
2. 三個(gè)臭皮匠
在小尺度的圖像下,我會(huì)想辦法粗略地尋找前景衙傀。一般地抬吟,我會(huì)希望用Canny
算子將前景的邊緣找出來(lái),之后统抬,最外面的邊緣所包圍的區(qū)域便是前景了火本。再然后,我會(huì)用minAreaRect
來(lái)把前景的最小外接矩形給找出來(lái)聪建。如果前景本身就是一個(gè)矩形钙畔,那么到這一步,粗略的邊緣也就找到了金麸。但問(wèn)題來(lái)了刃鳄,我一定要保證前景的外邊緣是閉合的。有一點(diǎn)點(diǎn)不閉合都不行……那我怎么最大程度地讓它閉合呢钱骂?
之前叔锐,我總有些思維定勢(shì)似的,拿到一個(gè)彩圖就想著怎么先把它弄成灰度圖见秽。再對(duì)灰度圖作Canny
變換愉烙。我勞心勞力地去研究用怎么的灰度化的方式更好,但往往都是顧此失彼——當(dāng)對(duì)某些情況調(diào)好了解取,對(duì)另外一些情況步责,又不好了……有一天,我突然開(kāi)竅了禀苦,為何一定只對(duì)一張灰度圖作Canny
呢蔓肯,我可以對(duì)R/G/B通道分別做Canny
呀!然后再把分別Canny
的結(jié)果用bitwise_or
合起來(lái)不就完了嗎振乏?結(jié)果蔗包,效果接近完美!
3. 整體觀
小尺度雖好慧邮,但也只能粗略地找到邊緣调限。如果需要精確定位,還是得回到高分辨的圖中误澳。但如果邊緣周圍的紋理比較復(fù)雜的話耻矮,邊緣還是挺難找。我們可以先考慮忆谓,如果邊緣周圍背景就是黑色裆装,前景就是白色時(shí)如何搜索這條直線——這很簡(jiǎn)單,我們隔幾個(gè)點(diǎn)搜索一下黑色背景和白色前景之間的交界點(diǎn)的位置,然后再對(duì)這些交界點(diǎn)作一個(gè)擬合即可哨免。
那如果背景是黑色勾扭,而前景的紋理比較復(fù)雜呢?那我們可以使用一個(gè)叫Deriche核的東西來(lái)檢測(cè)交界點(diǎn)的位置铁瞒。(相當(dāng)于先模糊妙色,再用[1 0 -1]這樣的核來(lái)卷積。)使用這樣的方法慧耍,交界點(diǎn)可以找得比較準(zhǔn)確身辨,最后再用某種直線擬合的方法,比如Huber芍碧,來(lái)擬合直線即可煌珊。
那么,如果背景和前景都比較復(fù)雜呢泌豆?甚至定庵,我們需要找的是拼接的邊緣呢(邊緣兩邊都是前景,都有紋理)踪危?那就可以整體地去求解這條直線的位置了蔬浙。自己定義一個(gè)能量函數(shù)或者損失函數(shù),并猜測(cè)出這條直線方程的若干可能性贞远。計(jì)算這若干條直線方程的能量畴博,選擇得到最大的能量那條直線即可。
至于能量函數(shù)的具體定義方法蓝仲,請(qǐng)?jiān)试S我賣個(gè)關(guān)子吧~關(guān)鍵是想睡覺(jué)了……Zzz……
注:本文中所有標(biāo)記為這樣的function
俱病,都是OpenCV中的函數(shù)。