【matlab图像处理笔记4】【图像变换】(三)图像的霍夫变换
文章目錄
- 推薦閱讀
- 前言
- 霍夫變換概述
- 霍夫變換直線檢測原理
- 從笛卡爾坐標系到霍夫空間
- 兩點一線的霍夫空間形式
- 尋找共線的點
- 直角坐標系存在的問題
- 極坐標參數空間下的霍夫變換
- matlab霍夫變換直線檢測示例
- 檢測步驟
- 示例以及代碼
- 原圖
- 邊緣檢測
- 對二值圖像霍夫變換
- 尋找霍夫空間中的交點
- 在笛卡爾坐標系繪制線段
- 關于houghlines的補充說明
- 完整代碼
推薦閱讀
本系列其他文章
參考教程/推薦文章
前言
本篇將介紹圖像變換中的霍夫變換,該文章不會對霍夫變換做太過于詳細的推導,將更注重于霍夫變換的理解與應用。
本篇文章主要介紹霍夫變換直線檢測。
霍夫變換概述
霍夫變換是一種在圖像中尋找直線、圓形以及其他簡單形狀的方法,廣義上的霍夫變換可以找到你想要的任何你可以描述的特征。
霍夫變換采用類似于投票的方式來獲取當前圖像內的形狀集合,該變換由Paul Hough(霍夫)于1962年首次提出。最初的霍夫變換只能用于檢測直線,經過發展后,霍夫變換不僅能夠識別直線,還能識別其他簡單的圖形結構,常見的有圓、橢圓等。實際上,只要是能夠用一個參數方程表示的對象,都適合用霍夫變換來檢測。
霍夫變換直線檢測原理
從笛卡爾坐標系到霍夫空間
直線變為點
在笛卡爾坐標系中,存在一條直線y=k0x+b0y=k_0x+b_0y=k0?x+b0?
將y=k0x+b0y=k_0x+b_0y=k0?x+b0?寫為關于(k,b)(k,b)(k,b)的函數:
b0=?k0x+yb_0 = -k_0x+y b0?=?k0?x+y
變換后的空間稱為霍夫空間。此時笛卡爾坐標系中的直線將表示為霍夫空間中的一個點:
同時也可以從霍夫空間逆變換為笛卡爾空間。
點變為直線
在笛卡爾坐標系中,存在一個點(x0,y0)(x_0,y_0)(x0?,y0?),
通過該點的直線可表示為:y0=kx0+by_0 = kx_0+by0?=kx0?+b 。變換后為b=?kx0+y0b = -kx_0+y_0b=?kx0?+y0?。此時笛卡爾坐標系中的一個點將表示為霍夫空間中的一條直線:
兩點一線的霍夫空間形式
現在在笛卡爾坐標系中,有兩個點:
我們知道,兩點確定一條直線。現在來思考這兩個點在霍夫空間將以什么形式表示這條直線。在霍夫空間中,這兩個點對應不同的直線。那么在霍夫空間中,這兩條直線的交點,就是笛卡爾坐標系中對應的直線。
尋找共線的點
現在我們將點位增多,并開始在這些點中尋找共線的點以及對應的直線。
那么根據霍夫空間交點即笛卡爾空間共線的規則,右圖的交點都說明共線。但是右圖的交點為什么無視了兩個呢?
這是因為霍夫變換后處理的基本方式是:選擇由盡可能多直線匯成的點。通常情況下,我們需要設置一個閾值,當霍夫坐標系內交于某點的曲線達到了閾值,就認為在對應的極坐標系內存在(檢測到)一條直線。
現在逆變換回笛卡爾坐標系,看看這兩個橙色的交點代表的直線:
可以看到我們成功找到了共線的點對應的直線,但此時的霍夫變換還存在問題。
直角坐標系存在的問題
考慮下圖的情況,即共線的直線垂直于x軸,此時直線的斜率k為無窮大,截距b無法取值。因此,下圖的垂線無法映射至霍夫空間。為了解決該問題,我們需要將直角坐標系換位極坐標系。
極坐標參數空間下的霍夫變換
在極坐標中的直線可以表示為:
r=xcosθ+ysinθr = xcos\theta+ysin\theta r=xcosθ+ysinθ
現在將極坐標的點映射至霍夫空間,霍夫空間的參數變為r,θr,\thetar,θ ,對比圖如下:
同樣的規則,交點為共線。
matlab霍夫變換直線檢測示例
現在使用matlab實現的霍夫變換做一個具體的示例。
檢測步驟
對原圖像進行邊緣檢測同時二值化。(關于邊緣檢測的相關內容將在之后的文章中更新)
二值化以后,我們就可以通過找非零點的坐標確定數據點的位置。即將像素圖像變成笛卡爾坐標系的坐標集合。
對二值化后的圖像進行霍夫變換。
在霍夫空間中尋找滿足條件的交點。
在笛卡爾坐標系,將霍夫變換中找到的交點變成直線,再以線段的形式繪制出來。這一步待會兒會特別說明一下
示例以及代碼
原圖
邊緣檢測
clc;clear;close all; I = imread('example3.jpg'); I = rgb2gray(I); % 灰度化 figure();imshow(I);title('原圖'); BW = edge(I,'prewitt'); % 邊緣檢測 figure();imshow(BW);title('邊緣檢測');對二值圖像霍夫變換
matlab中使用hough函數對二值圖像進行霍夫變換。
函數用法:Hough 變換 - MATLAB hough - MathWorks 中國
% 霍夫變換 [H,theta,rho] = hough(BW); figure();imshow(imadjust(mat2gray(H)),[],'XData',theta,'YData',rho,...'InitialMagnification','fit'); xlabel('\theta');ylabel('\rho'); axis on, axis normal, hold on; % 調整圖像比例,不然會很窄 title('霍夫空間映射圖像');邊緣檢測后的二值圖像在霍夫空間上的映射圖像:
尋找霍夫空間中的交點
matlab中使用houghpeaks函數在霍夫空間尋找滿足條件的交點。
函數用法:Identify peaks in Hough transform - MATLAB houghpeaks - MathWorks 中國
% 在Hough矩陣中尋找前30個大于Hough矩陣中最大值0.3的交點(交點即峰值) P = houghpeaks(H,30,'threshold',ceil(0.3*max(H(:)))); x = theta(P(:,2));y = rho(P(:,1)); plot(x,y,'s','color','red');在笛卡爾坐標系繪制線段
matlab中使用houghlines函數將在霍夫空間尋找到的交點提取成笛卡爾坐標系的線段(注意不是直線!)
函數用法:基于 Hough 變換提取線段 - MATLAB houghlines - MathWorks 中國
% 在笛卡爾坐標系中找到這些直線 % 合并距離小于20的線段,丟棄所有長度小于2的線段 lines=houghlines(BW,theta,rho,P,'FillGap',20,'Minlength',2); figure();imshow(BW);hold on;max_len = 0; for k = 1:length(lines) % 依次標出各條直線段xy = [lines(k).point1; lines(k).point2];plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','blue');% 繪制線段的起點和終點plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');% 確定最長線段的端點len = norm(lines(k).point1 - lines(k).point2);% 最長線段的長度if ( len > max_len)max_len = len;xy_long = xy;end end關于houghlines的補充說明
我最開始沒搞清啊,就覺得很奇怪:找到的線明顯比交點多啊,這是為什么?
然后仔細研究才發現它是把直線拆成了很多根線段,現在我們只找一個交點就很容易看清楚了:
可能圖有點小,但是很明顯可以看到它把一條直線拆成了兩個線段。
完整代碼
clc;clear;close all; I = imread('example3.jpg'); figure();imshow(I);title('原圖'); I = rgb2gray(I); % 灰度化 BW = edge(I,'Prewitt'); % 邊緣檢測 figure();imshow(BW);title('邊緣檢測');% 霍夫變換 [H,theta,rho] = hough(BW); figure();imshow(imadjust(mat2gray(H)),[],'XData',theta,'YData',rho,...'InitialMagnification','fit'); xlabel('\theta');ylabel('\rho'); axis on, axis normal, hold on; % 調整圖像比例,不然會很窄 title('霍夫空間映射圖像');% 在Hough矩陣中尋找前30個大于Hough矩陣中最大值0.5峰值 P = houghpeaks(H,30,'threshold',ceil(0.3*max(H(:)))); x = theta(P(:,2));y = rho(P(:,1)); plot(x,y,'s','color','red');% 在笛卡爾坐標系中找到這些直線 % 合并距離小于20的線段,丟棄所有長度小于2的線段 lines=houghlines(BW,theta,rho,P,'FillGap',20,'Minlength',2); figure();imshow(BW);hold on;max_len = 0; for k = 1:length(lines) % 依次標出各條直線段xy = [lines(k).point1; lines(k).point2];plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','blue');% 繪制線段的起點和終點plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');% 確定最長線段的端點len = norm(lines(k).point1 - lines(k).point2);% 最長線段的長度if ( len > max_len)max_len = len;xy_long = xy;end end來個成果集合圖:
到這里霍夫變換直線檢測就寫完了。但是霍夫變換的應用明顯不止這么點,我原本想把圓環檢測也寫了,奈何時間確實不夠,感興趣的話就只能自行拓展啦。
寫完本文已經是晚上1點了,明早還有早課,準備早課補眠嘍~
總結
以上是生活随笔為你收集整理的【matlab图像处理笔记4】【图像变换】(三)图像的霍夫变换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【微服务】如何实现微服务集群的高可靠?
- 下一篇: Android 10.0 进入recov