31、 霍夫變換

2021-02-13 人工智慧與機器視覺

       霍夫變換是一種用於在圖像中查找直線、圓或其他簡單形狀的方法。最初的霍夫變換是直線變換,這是一種在二值圖像中搜索直線的方法。該變換可以進一步推廣到圓以及橢圓等情況。

  霍夫直線變換的基本理論是,二值圖像中的任何點都可能是某條直線的一部分。如果通過斜率a和截距b對直線進行參數化,則原始圖像中的一個點將轉換為(a,b)平面中與通過該點的所有線相對應的點的軌跡。如果將輸入圖像中的每個非零像素轉換為輸出圖像中的這樣一組點並對所有這些貢獻求和,那麼出現在輸入(即(x,y)平面)圖像中的直線將顯示為在輸出(即(a,b)平面)圖像中的局部最大值。(a,b)平面通常稱為累加器平面。

截距截取形式實際上並不是代表所有通過點的線的最佳方式(即,由於線的密度隨斜率的不同而存在很大差異,並且可能的斜率從–∞到+∞)。這就是為什麼數值計算中使用的變換圖像的實際參數化有些不同的原因。通常將每條線表示為極坐標(ρ,θ)中的一個點,隱含的線是穿過指定點但垂直於從原點到該點的半徑的線。OpenCV的Hough變換算法返回(ρ,θ)平面中的局部最大值。

OpenCV支持三種不同的霍夫直線變換:標準霍夫變換SHT,多尺度霍夫變換MHT和漸進概率霍夫變換PPHT。PPHT是此算法的一種變體,之所以稱其為「概率」,是因為它只累加了一部分,而不是累加了累加器平面中的每個可能點。因為如果無論如何峰值都足夠高,那麼僅其中一小部分就足以找到它。這種結果是大大減少了計算時間。

標準和多尺度Hough變換都在函數HoughLines()中實現,區別在於使用或不使用最後兩個可選參數。

voidcv::HoughLines(

cv::InputArrayimage,

cv::OutputArraylines,

doublerho,

doubletheta,

intthreshold,

doublesrn = 0,

doublestn = 0

);

第一個參數是輸入圖像,它必須是8位圖像,但是輸入被視為二值信息(即所有非零像素都被視為等效)。第二個參數是找到的行將被存儲的位置,這是一個N×1兩通道浮點型數組(列數N將是返回的行數),對於每個找到的行包含rho(ρ)和theta(θ)值。參數rho和theta設置直線所需的解析度(即累加器平面的解析度)。rho的單位是像素,theta的單位是弧度。閾值是累加器平面中的值。該參數表明必須要返回的線的點數。

標準的Hough變換不使用參數srn和stn。它們用於多尺度霍夫變換(MHT)。對MHT,這兩個參數表明應針對這些線的參數計算出更高的解析度。MHT首先根據rho和theta參數給定的精度計算直線的位置,然後繼續分別以srn和stn的因子來細化這些結果,即rho的最終解析度是rho除以srn,並且theta的最終解析度為theta除以stn。

voidcv::HoughLinesP(

cv::InputArrayimage,

cv::OutputArraylines,

doublerho,

doubletheta,

intthreshold,

doubleminLineLength = 0,

doublemaxLineGap = 0

);

HoughLinesP()函數與HoughLines()非常相似,但有兩個重要區別。第一個是lines參數將是一個四通道數組,找到的是線段兩個端點的位置(x0,y0)和(x1,y1)。第二個區別是對於PPHT,minLineLength和maxLineGap參數設置將返回線段的最小長度,以及算法不將其連接到單個較長線段中所需的共線段之間的分隔。

霍夫圓變換與霍夫直線變換大致相似。但它必須用具有三個維度的累加器,一個用於x,一個用於y(圓心的位置),另一個用於圓半徑r。這意味著更高的內存需求和更慢的速度。在OpenCV中,通過使用一種稱為Hough梯度的方法避免了此問題。霍夫梯度的原理如下:首先,圖像進行邊緣檢測;接下來,對於邊緣圖像中的每個非零點,都要考慮局部梯度。使用該梯度,沿該斜率指示從-a處增加每個點。指定的最小到指定的最大距離在累加器中。同時,記錄這些非零像素中的每個像素在邊緣圖像中的位置。然後從該(二維)累加器中既高於某個給定閾值又大於其所有直接鄰域的那些點中選擇候選中心。這些候選中心按照其累加器值的降序排序,因此具有最多支持像素的中心會首先出現。接下來,對於每個中心,均考慮所有非零像素。這些像素根據它們與中心的距離排序。從最小的距離到最大的半徑,選擇一個最好由非零像素支持的半徑。如果中心有來自邊緣圖像中非零像素的足夠支持,並且距任何先前選擇的中心有足夠的距離,則保留中心。

這種實現方式使算法可以運行得更快,並且它有助於解決三維累加器稀疏的問題,否則將導致大量噪聲並使結果不穩定。但是有一些問題需要注意。首先,使用Sobel導數來計算局部梯度(以及隨之而來的假設可以認為它等同於局部切線)並不是一個數值穩定的命題。「大多數時候」可能是正確的,但是這會在輸出中產生一些噪聲。其次,針對每個候選中心考慮邊緣圖像中的整個非零像素集,因此,如果累加器閾值太低,該算法將花費很長時間運行。第三,由於每個中心僅選擇一個圓,因此,如果存在同心圓,則將僅獲得其中一個。

霍夫圓變換函數HoughCircles()具有與直線變換相似的參數。

voidcv::HoughCircles(

cv::InputArrayimage,

cv::OutputArraycircles,

intmethod,

doubledp,

doubleminDist,

doubleparam1 = 100,

doubleparam2 = 100,

intminRadius = 0,

intmaxRadius = 0

);

輸入圖像還是8位圖像。HoughCircles()和HoughLines()之間的一個重要區別是後者需要二值圖像。HoughCircles()函數內部自動調用Sobel(),因此可以提供更通用的灰度圖像。

結果數組將是矩陣數組或向量,具體取決於傳遞給HoughCircles()的內容。如果使用矩陣,它將是類型為F32C3的一維數組;這三個通道將用於編碼圓的位置及其半徑。如果使用向量,則其類型必須為vector <Vec3f>。方法參數必須始終設置HOUGH_GRADIENT。

參數dp是所用累加器圖像的解析度。此參數使我們可以創建解析度比輸入圖像低的累加器。因為沒有理由期望圖像中存在的圓自然落入與框的寬度或高度相同數量中。如果dp設置為1,則解析度將相同;否則,解析度將變為1。如果將其設置為較大的數字,則累加器解析度將減小該因子(在這種情況下為一半)。dp的值不能小於1。

參數minDist是兩個圓之間必須存在的最小距離,以便將它們視為不同的圓。

對於設置為HOUGH_GRADIENT的方法,接下來的兩個參數param1和param2分別是邊沿Canny閾值和累加器閾值。Canny邊緣檢測器本身實際上採用了兩個不同的閾值。當內部調用Canny()時,第一個(較高)閾值設置為參數param1的值傳遞到HoughCircles()中,並且第二個(較低的)閾值正好設置為該值的一半。參數param2是用於對累加器進行閾值處理的參數,它與Hough Lines()的閾值參數完全相似。

最後兩個參數是可以找到的圓的最小和最大半徑。這意味著這些是累加器為其表示的圓的半徑。例1顯示了一個使用HoughCircles()的示例程序。

例1:使用霍夫圓變換在圖像中查找直線和圓

#include<opencv2/opencv.hpp>#include<iostream>#include<math.h>usingnamespace cv;usingnamespace std;int main(intargc, char** argv){    Mat src;    Mat thrImg;    src = imread("E:/hough.bmp", 0);    imshow("src", src);    threshold(src, thrImg, 100, 255, 1);    vector<Vec2f> lines;    HoughLines(thrImg, lines, 1.1, CV_PI/180, 200);    for (size_t i = 0; i < lines.size(); i++)    {         float rho = lines[i][0], theta = lines[i][1];         Point pt1, pt2;         double a = cos(theta), b = sin(theta);         double x0 = a*rho, y0 = b*rho;         pt1.x = cvRound(x0 + 2000 * (-b));         pt1.y = cvRound(y0 + 2000 * (a));         pt2.x = cvRound(x0 - 2000 * (-b));         pt2.y = cvRound(y0 - 2000 * (a));         line(src, pt1, pt2, Scalar(0,0,255), 2);    }    vector<Vec3f> circles;    HoughCircles(src, circles, cv::HOUGH_GRADIENT,2,100,80,100,30,60 );    for (size_t i = 0; i < circles.size(); ++i)    {circle(src,Point(cvRound(circles[i][0]),cvRound(circles[i][1])),cvRound(circles[i][2]),Scalar(0, 0, 255),3);    }    imshow("Hough", src);    waitKey(0);    return 0;}

值得反思的是,無論採用什麼技巧,都沒有繞過要求以三個自由度(x,y和r)來描述圓的要求。結果與之前的尋找直線相比,需要更多的內存和計算時間。考慮到這一點,最好在情況允許的範圍內緊緊地限制半徑參數,以控制計算時間。霍拉變換在1981年由Ballard擴展到任意形狀。

農曆2020年的最後一天,祝大家春節快樂。

相關焦點

  • 霍夫變換原理剖析
    變換後的空間成為霍夫空間。即:笛卡爾坐標系中一條直線,對應霍夫空間的一個點。 到這裡問題似乎解決了,已經完成了霍夫變換的求解,但是如果像下圖這種情況呢?其實本質上就是: 找出其中數值較大的一些點,通常可以給定一個閾值,Threshold一下。
  • [OpenCV]經典霍夫變換原理
    本文主要講述的是霍夫變換的一些內容,並加入一些在生活中的應用,希望能對讀者對於霍夫變換的內容有所了解。首先我先說的是,霍夫變換是一個特徵提取技術。其可用於隔離圖像中特定形狀的特徵的技術,應用在圖像分析、計算機視覺和數字圖像處理領域。
  • 概率霍夫變換
    cv2.line(orgb,(x1,y1),(x2,y2),(255,0,0),5)plt.subplot(121)plt.imshow(oShow)plt.axis('off')plt.subplot(122)plt.imshow(orgb)plt.axis('off')(-0.5, 459.5, 459.5, -0.5)算法:概率霍夫變換是霍夫變換算法的優化
  • 霍夫變換是怎麼發明的
    發明霍夫變換在20世紀60年代後期,我與我的同事Richard O. Duda和其他人一起為Shakey開發了一個視覺系統,這是一個由SRI International的人工智慧中心創建的移動智慧機器人。 Shakey生活在一個室內世界,房間裡有幾乎像楔子和立方體一樣的幾何實體。
  • opencv教程-霍夫變換、圖像分割
    1:模板匹配opencv裡的模板匹配就不說了,也就是從當前圖像提取模板圖像匹配還好,換一個不同圖片的模板就不行了,而且對縮放的模板匹配效果也很差,就說下基本流程如下:圖像灰度化→cv2.matchTemplate→cv2.minMaxLoc2:霍夫變換
  • 咕咕霍夫麵包
    今天我要給親們介紹一種很有趣的點心,它叫咕咕霍夫。
  • 咕咕霍夫
    在德國和法國的阿爾薩斯地區,聖誕節一定少不了咕咕霍夫。說它是蛋糕也好,麵包也不錯。
  • 咕咕霍夫蛋糕
    咕咕霍夫(Kougelhopf)是法國Alsace地區的名產,但傳說也是德國南部和奧地利的傳統特產,他國家如瑞士,波蘭,匈牙利都有自己的傳統咕咕霍夫
  • 咕咕霍夫麵包製作
    今天我要給親們介紹一種很有趣的點心,它叫咕咕霍夫。
  • 咕咕霍夫,是麵包還是蛋糕?
    但你們有沒有想過咕咕霍夫其實是一蛋糕口感的麵包呢?傳統的咕咕霍夫模具傳統的咕咕霍夫模具大部分都是用陶瓷做的在法國很多家庭都會私藏一個漂亮的陶瓷的咕咕霍夫模具雖然每年可能只用那麼一回但是意義甚大哦!現在的咕咕霍夫模具大多都是金屬和矽膠做的比如著名的西班牙品牌某葵有一款金牌產品—薩瓦林模具跟咕咕霍夫很像呢~但是別弄混了咕咕霍夫更窄更深
  • 教你做神秘的咕咕霍夫!
    今天我要給親們介紹一種很有趣的點心,它叫咕咕霍夫。首先,它的原文和中文名字都非常豐富多彩:kugelhopf、kugelhupf、suglhopf、suglhupf、 咕咕霍夫、古格霍夫、穀穀霍夫,無論哪個都是指這種形狀特別,濃鬱得像蛋糕, 含有很多果乾的中空麵包~
  • Kougelhopf裸露的「咕咕霍夫蛋糕配方」
    咕咕霍夫(Kougelhopf)是法國Alsace地區的名產,但傳說也是德國南部和奧地利的傳統特產,他國家如瑞士,波蘭,匈牙利都有自己的傳統咕咕霍夫
  • 濃鬱得像蛋糕,俏皮又可愛的咕咕霍夫麵包.
    今天我要給親們介紹一種很有趣的點心,它叫咕咕霍夫。
  • 【消息】遼寧舉辦「柴門霍夫年」紀念活動
    7月23日遼寧省工商聯國際經濟文化俱樂部在瀋陽舉辦「柴門霍夫年」紀念活動以紀念7月26日世界語《第一書》發表130周年和「柴門霍夫年」。遼寧電視臺娜姐朗誦工作室深情朗誦了柴門霍夫的詩歌作品;遼寧省女畫家東方雅鳳繪畫了柴門霍夫的畫像;著名書法家揮毫書寫了毛澤東主席1939年在延安為世界語展覽會的題詞:「我還是這一句話:如果以世界語為形式,而載之以真正國際主義之道,真正革命之道,那麼世界語是可以學的,是應該學的」;參加活動的世界語者和世界語愛好者以詩、詞、對聯、書法等形式來紀念「柴門霍夫年」。
  • 視頻配方-聖誕節超簡單的咕咕霍夫|家庭烘焙小竅門
    咕咕霍夫就這樣誕生了,在阿爾薩斯語中「Kugelhopf」意思就是頭巾。這種說法讓咕咕霍夫在聖誕節更加顯得有意義。傳說波蘭國王,也就是路易十五的嶽父,Stanislas Leczynski在洛林地區的呂內維爾(Lunéville)設立了宮殿,他覺得當地的糕點咕咕霍夫有點太幹了,宮廷糕點師為了討他歡心便將咕咕霍夫浸泡在朗姆酒糖漿中。
  • 世界麵包咕咕霍夫,是麵包還是蛋糕?一個不得不拔草的模具!
    但你們有沒有想過咕咕霍夫其實是一蛋糕口感的麵包呢?傳統的咕咕霍夫模具 傳統的咕咕霍夫模具大部分都是用陶瓷做的在法國很多家庭都會私藏一個漂亮的陶瓷的咕咕霍夫模具雖然每年可能只用那麼一回現在的咕咕霍夫模具大多都是金屬和矽膠做的(其他模具也是~)比如著名的西班牙品牌某葵有一款金牌產品—薩瓦林模具跟咕咕霍夫很像呢~但是別弄混了咕咕霍夫更窄更深
  • 霍夫肯血系探密
    霍夫肯就使用這些鴿子與凡登布希作出的母鴿交配,育出了「獨眼號」。「獨眼號」(足環號:B56-6353631灰色雄鴿):具統計它贏得冠軍30次以上。「獨眼號」的直子與五十年代安特衛普聯盟冠軍凡萊林克羅克的鴿系交配後,育出了最有價值的灰三線「滴班德」B64-6151613灰色雄鴿,灰三線「滴班德」再交配凡龍作出的母鴿,就形成了後期的霍夫肯系,又被鴿友們戲稱為「黑豬」的緣由。
  • 聖誕節要來了,先學起來,視頻配方-聖誕節超簡單的咕咕霍夫
    平日的歐式早餐中也常能夠品嘗到甜口的咕咕霍夫,而鹹口咕咕霍夫則常被作為前菜開胃品。甜口的常以浸泡過朗姆酒或櫻桃白蘭地的葡萄乾和扁桃仁作為輔料,鹹口的則常配以豬肉丁和核桃。咕咕霍夫就這樣誕生了,在阿爾薩斯語中「Kugelhopf」意思就是頭巾。這種說法讓咕咕霍夫在聖誕節更加顯得有意義。
  • 神秘之作丨朗姆果乾咕咕霍夫
    有一種麵包,口感像蛋糕,光名字就足以讓人搞暈,kugelhopf,kugelhupf,gugelhopf,gugelhupf,suglhopf,咕咕霍夫
  • 柴門霍夫發明了世界語,至今少有人知,英語卻成了事實上的世界語
    公元1887年,歷史上的今天,柴門霍夫博士發明了世界語。這位出生于波蘭,祖籍為猶太人,從小就很有語言的天賦的博士,全名為:拉扎魯·路德維克·柴門霍夫,因當時波蘭被俄國沙皇統治,固取了此名。在柴門霍夫童年時,在他的印象裡,沒有所謂的人,當地居民只有俄羅斯人、波蘭人、日爾曼人和猶太人這四種人。每種人都說著自己的語言,每種人之間的關係也不好,即使沒有敵意,見面也無法溝通。