計算機視覺 OpenCV Android | 基本特征檢測之 霍夫直線檢測 詳析

霍夫直線檢測的作用——計算得到輸入圖像(一般是二值化的邊緣檢測結果圖像)中包含的所有直線的數(shù)目與位置

  • 在取得圖像邊緣的基礎上灾馒,
    對一些特定的幾何形狀邊緣巩搏,如直線敞咧、圓匹表,通過圖像霍夫變換把圖像從平面坐標空間變換到霍夫坐標空間孽江,
    就可以通過求取霍夫空間局部極大值方法(其實就是霍夫空間中的曲線交集點),
    得到極坐標空間對應參數(shù)方程直線的兩個參數(shù)(r讶坯,θ)
    從而計算得到邊緣圖像中所有直線(基于平面坐標)的數(shù)目與位置岗屏。

假設有一條直線如下圖:


(紅色部分是計算過程辆琅,遞等到右下角的結果漱办,待會兒要用)

笛卡兒平面坐標系統(tǒng)中的斜率參數(shù)與截距參數(shù)為(k,b)婉烟;

若變換到極坐標空間則變成求取另外兩個參數(shù)(r娩井,θ)r 和 θ之間的關系可以表示為:
(公式的來源運算過程見上圖)



對于每個平面空間的像素點坐標(x似袁,y)洞辣,
隨著角度θ的取值不同,都會得到r值昙衅,
(%+++%要點.B)而對于任意一條直線來說扬霜,在極坐標空間它的(r,θ)都是固定不變的而涉,
則對于邊緣圖像每個平面空間坐標點可繪制極坐標的曲線如圖所示:

  • 上圖中著瓶,

    左側是一個平面空間的像素點
    基于公式r = x * cosθ + y * sinθ啼县,
    通過給定不同的θ值蟹但,得到唯一對應r值,
    無數(shù)個(r谭羔,θ)數(shù)對構成的一道極坐標曲線华糖;

    右側是三個平面空間的像素點
    基于公式r = x * cosθ + y * sinθ瘟裸,
    通過給定不同的θ值客叉,得到唯一對應r值,
    無數(shù)個(r话告,θ)數(shù)對構成的三道極坐標曲線兼搏;

  • 無論截圖的左側還是右側,都是所謂 霍夫空間的一部分沙郭,所謂霍夫空間佛呻,如下圖:
    圖片參考于此博文

霍夫空間 概念詳析

霍夫空間就是一個基于(r所坯,θ)兩個參數(shù)坐標軸的數(shù)據空間缤谎,
數(shù)量級規(guī)模是可以是一個邊緣圖像像素點數(shù)量斧吐;

并且這個空間包括了這樣的一系列曲線 :
一個邊緣圖像所有(all & each,假設為 N 個)像素點(x,y)续捂,
基于公式r = x * cosθ + y * sinθ斥季,
通過給定不同的θ值茫陆,得到唯一對應r值苫昌,
無數(shù)個(r哩至,θ)數(shù)對構成對應上 N個 像素點N 道 極坐標曲線(霍夫空間的曲線)惕耕;


霍夫直線檢測 的 知識要點
  • (要點.A)
    輸入的邊緣圖像中的每一個像素點一 一 對 應一條霍夫空間(or 極坐標參數(shù))曲線纺裁;

  • (要點.B)
    而對于邊緣圖像中的 任意一條直線來說,在極坐標空間它的(r,θ)都是固定不變的欺缘,


  • (由上可得 要點.C)
    霍夫空間中的一個交集點(若干曲線的交點(r栋豫,θ))
    就是一條直線(點的參數(shù)(r,θ)可變換成直線)谚殊;
  • 而重疊在這個交集點上的霍夫(極坐標)曲線集笼才,
    其實就是該交集點代表的(存在邊緣圖像中 的 對應的)直線 所包含的(像素)點集

  • (要點.D)
    交集點累積的曲線络凿;
    對應(平面坐標系的邊緣圖像上的)直線所包含的像素點集就越骡送;
    也即對應直線長度

霍夫直線檢測 從二值化.邊緣檢測.結果圖像到檢測繪制出直線 的大概步驟

以上引用框中的內容是個人的梳理總結絮记,下面繼續(xù)讀書筆記的內容摔踱。

  • 由在平面空間同屬于一條直線的像素點繪制出來的曲線必然會相交于一點(上方截圖的b)右側所示的曲線),
  • 而這個點正是存在邊緣對象中的對應的直線極坐標空間中的參數(shù)方程的參數(shù)怨愤,
    這樣就在極坐標空間找到了直線的參數(shù)方程派敷,
    反變換回到平面坐標空間就可以求得直線的兩個參數(shù)(k,b)撰洗,
    得到直線位置篮愉,
    而它們在極坐標的交點就是直線在霍夫空間的表達
    直線越差导,其在霍夫空間這個點的累積值就越试躏,相對的灰度值也就越(亮)

OpenCV關于霍夫直線變換提供了兩個相關API函數(shù)设褐,
一個是在霍夫空間求取直線兩個極坐標的參數(shù)颠蕴,
需要開發(fā)者自己轉換到平面坐標空間計算直線;
另外一個則會直接返回平面空間直線/線段的兩個點坐標信息助析。

返回極坐標參數(shù)的API函數(shù)如下:

  • HoughLines(Mat image, Mat lines, double rho, double theta, int threshold)
    image:表示輸入圖像犀被,8位單通道圖像,一般為二值圖像外冀。
    lines:表示輸出的每個直線的極坐標參數(shù)方程的兩個參數(shù)寡键。
    rho:表示極坐標空間r值每次的步長,一般設置為1雪隧。
    theta:表示角度θ西轩,每次移動即可。
    threshold:表示霍夫空間中該點的累積數(shù)膀跌,
    該累積數(shù)越大遭商,則得到的直線可能就越長,
    取值范圍通常為30~50捅伤,單位是像素,
    假設為30的話巫玻,則表示大于30個像素長度的線段才會被檢測到丛忆。
  • threshold解釋中所述的累積數(shù)可以看做我們數(shù)據處理中的投票機制祠汇,
    票數(shù)大于threshold交集點
    (即累積的曲線數(shù)大于threshold交集點),
    才認定是有效直線熄诡,
    才能被函數(shù)檢測到提取出來用于返回/變換繪制成直線可很;

使用該API實現(xiàn)直線檢測:

private void houghLinesDemo(Mat src, Mat dst) {
  Mat edges = new Mat();
  Imgproc.Canny(src, edges, 50, 150, 3, true);
  Mat lines = new Mat();
  Imgproc.HoughLines(edges, lines, 1,Math.PI/180.0, 200);
  Mat out = Mat.zeros(src.size(), src.type());
  float[] data = new float[2];
  for(int i=0; i<lines.rows(); i++) { 
      lines.get(i, 0, data);
      float rho = data[0], theta = data[1];
      double a = Math.cos(theta), b = Math.sin(theta);
      double x0 = a*rho, y0 = b*rho;

      Point pt1 = new Point();
      Point pt2 = new Point();
      pt1.x = Math.round(x0 + 100*(-b));//!!!!!!!!!!!!!!!!!
      pt1.y = Math.round(y0 + 100*(a));
      pt2.x = Math.round(x0 - 100*(-b));
      pt2.y = Math.round(y0 - 100*(a));

      Imgproc.line(out, pt1, pt2, new Scalar(0,0,255), 3, Imgproc.LINE_AA, 0);
  }
  out.copyTo(dst);
  out.release();
  edges.release();
}

關于pt1.x = Math.round(x0 + 100*(-b));這一行代碼,

以上的這個API函數(shù)需要對得到的每對極坐標參數(shù)(r,θ)計算笛厦,
使其變換平面空間x0 = r * cosθ ; y0 = r * sinθ)纳鼎,
接著通過對x0y0添加偏移量并進行計算,得到直線的兩個點裳凸;
然后繪制直線贱鄙。

另外一個API函數(shù)則比較簡單,
省去了開發(fā)者自己把極坐標變換為直線坐標的過程姨谷,
直接返回每個線段/直線對應的兩個點坐標逗宁,
其API函數(shù)與參數(shù)的解釋具體如下:

  • HoughLinesP(Mat image, Mat lines, double rho, double theta, int threshold, double minLineLength, double maxLineGap)
    image:表示輸入圖像,8位單通道圖像梦湘,一般為二值圖像疙剑。
    lines表示輸出的每個直線最終要繪制用兩個 平面坐標系參數(shù)
    rho:表示極坐標空間r值每次的步長践叠,一般設置為1言缤。
    theta:表示角度θ,每次移動1°即可禁灼。
    threshold:表示極坐標中該點的累積數(shù)管挟,該累積數(shù)越大,則得到的直線可能就越長弄捕,取值范圍通常為30~50僻孝,單位是像素,假設取值為30守谓,則表示大于30個像素長度的線段才會被檢測到穿铆。
    minLineLength:表示可以檢測的最小線段長度,根據實際需要進行設置斋荞。
    maxLineGap:表示線段之間的最大間隔像素荞雏,假設5表示小于5個像素的兩個相鄰線段可以連接起來。

使用該API實現(xiàn)圖像直線檢測:

private void houghLinePDemo(Mat src, Mat dst) {
  Mat edges = new Mat();
  Imgproc.Canny(src, edges, 50, 150, 3, true);
  Mat lines = new Mat();
  Imgproc.HoughLinesP(edges, lines, 1, Math.PI/180.0, 100, 50, 10);
  Mat out = Mat.zeros(src.size(), src.type());
  for(int i=0; i<lines.rows(); i++) {
      int[] oneline = new int[4];
      lines.get(i, 0, oneline);
      Imgproc.line(out, new Point(oneline[0], oneline[1]),
          new Point(oneline[2], oneline[3]),
          new Scalar(0, 0, 255), 2, 8, 0);
  }
  out.copyTo(dst);
  // 釋放內存
  out.release();
  edges.release();
}
  • 這里需要注意的是,
    圖像二值化邊緣檢測算法輸出結果質量很大程度上影響 霍夫直線變換結果凤优,
    同時在使用HoughLinesP的時候悦陋,最后兩個參數(shù)設置也會影響霍夫直線檢測的結果。







參考材料
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末筑辨,一起剝皮案震驚了整個濱河市俺驶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棍辕,老刑警劉巖暮现,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異楚昭,居然都是意外死亡栖袋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門哪替,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栋荸,“玉大人,你說我怎么就攤上這事凭舶∩慰椋” “怎么了?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵帅霜,是天一觀的道長匆背。 經常有香客問我,道長身冀,這世上最難降的妖魔是什么钝尸? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮搂根,結果婚禮上珍促,老公的妹妹穿的比我還像新娘。我一直安慰自己剩愧,他們只是感情好猪叙,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著仁卷,像睡著了一般穴翩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上锦积,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天芒帕,我揣著相機與錄音,去河邊找鬼丰介。 笑死背蟆,一個胖子當著我的面吹牛鉴分,可吹牛的內容都是我干的。 我是一名探鬼主播淆储,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼冠场,長吁一口氣:“原來是場噩夢啊……” “哼家浇!你這毒婦竟也來了本砰?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤钢悲,失蹤者是張志新(化名)和其女友劉穎点额,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莺琳,經...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡还棱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了惭等。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片珍手。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖辞做,靈堂內的尸體忽然破棺而出琳要,到底是詐尸還是另有隱情,我是刑警寧澤秤茅,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布稚补,位于F島的核電站,受9級特大地震影響框喳,放射性物質發(fā)生泄漏课幕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一五垮、第九天 我趴在偏房一處隱蔽的房頂上張望乍惊。 院中可真熱鬧,春花似錦放仗、人聲如沸润绎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凡橱。三九已至,卻和暖如春亭姥,著一層夾襖步出監(jiān)牢的瞬間稼钩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工达罗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坝撑,地道東北人静秆。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像巡李,于是被迫代替她去往敵國和親抚笔。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內容