霍夫变换——转载于“疯狂奔跑”

本文详细介绍了霍夫变换的基本原理,它用于在图像中检测直线。通过将笛卡尔坐标系中的直线映射到霍夫空间中的点,共线的点在霍夫空间中对应相交的直线。文章还展示了如何将坐标系转换为极坐标以解决无穷斜率的问题,并提供了简单的霍夫变换算法步骤和MATLAB代码示例。最后,通过图像处理展示了霍夫变换在实际直线检测中的应用。
摘要由CSDN通过智能技术生成

转载链接:
https://www.cnblogs.com/php-rearch/p/6760683.html;

基本原理

在笛卡尔坐标系中,一条直线可以由两个点来确定,如下图所示:
在这里插入图片描述
另外一方面,y= kx + q 也可以写成关于(k,q)的函数表达式(霍夫空间):
在这里插入图片描述
对应的变换可以通过图形直观的表示出来:
在这里插入图片描述
变换后的空间成为霍夫变换。即:笛卡尔坐标系中的一条直线,对应霍夫空间中的一个点。
反过来同样是成立的,即霍夫空间的一条直线,对应笛卡尔坐标系中的一个点:
在这里插入图片描述
再来看看A,B两个点,对应于霍夫空间的情形:
在这里插入图片描述
再看一下笛卡尔空间三个点共线的情况,在霍夫空间中对应的情形:
在这里插入图片描述
可以看出,如果在笛卡尔坐标系中共线的点,在霍夫空间中对应的直线就会相交于一点:这也是必然的,因为共线只有一种可能
那如果在笛卡尔坐标系中的点不止共线于一条直线呢?,我们来看看多个点的情况:
在这里插入图片描述
我们从霍夫空间可以看到,5条直线汇交了许多交点,有些交点是由三条直线汇交的(如A,B),有些交点是由两条直线汇交的(在图中未使用红点标出,望见谅)。霍夫变换的处理方式就是,在霍夫空间中,选择尽可能多的直线汇成的点。
霍夫空间:选择由三条交汇直线确定的点(中间图),对应的笛卡尔坐标系的直线(右图):
在这里插入图片描述
到这里问题似乎是已经解决了,已经完成了霍夫变换的求解,但是如果出现下图这种情况呢?
在这里插入图片描述
k=∞是不方便求解的,而且q该怎么取值呢?这样不是办法。因此将笛卡尔坐标系转换为:极坐标表示
在这里插入图片描述
在极坐标系下,其实是一样的:极坐标的点,霍夫空间中的直线,只不过霍夫空间不再是[k,q]的参数,而是[ρ,θ]的参数,给出的对比图如下所示:
在这里插入图片描述
是不是就一目了然了呢?
给出霍夫变换的算法步骤:
在这里插入图片描述
对应的code:

function [ Hough, theta_range, rho_range ] = naiveHough(I)
%NAIVEHOUGH Peforms the Hough transform in a straightforward way.
%
[rows, cols] = size(I);
 
theta_maximum = 90;
rho_maximum = floor(sqrt(rows^2 + cols^2)) - 1;
theta_range = -theta_maximum:theta_maximum - 1;
rho_range = -rho_maximum:rho_maximum;
 
Hough = zeros(length(rho_range), length(theta_range));
for row = 1:rows
    for col = 1:cols
        if I(row, col) > 0 %only find: pixel > 0
            x = col - 1;
            y = row - 1;
            for theta = theta_range
                rho = round((x * cosd(theta)) + (y * sind(theta)));  %approximate
                rho_index = rho + rho_maximum + 1;
                theta_index = theta + theta_maximum + 1;
                Hough(rho_index, theta_index) = Hough(rho_index, theta_index) + 1;
            end
        end
    end
end

其实,本质上就是:
在这里插入图片描述
交点怎么求解呢?细化成坐标形式,取整后将交点对应的坐标进行累加,最后找到数值最大的点就是求解的[ρ,θ],也就求解了直线。

应用

这里给出MATLAB自带的一个应用,主要是对一幅图像进行直线检验,原图像为:

在这里插入图片描述
首先是对其进行边缘检测:
在这里插入图片描述
边缘检测后并进行二值化,就可以通过找非零点的坐标确定数据点。从而对数据点进行霍夫变换。对应映射到霍夫空间的结果为:
在这里插入图片描述
找出其中数值较大的一些点,通常可以给定一个阈值,Threshold一下。
这就完成了霍夫变换的整个过程,这个时候求解出来了其实就是多条直线的斜率k以及截距q,通常会根据直线的特性进一步进行判断,从而将直线变为线段:
在这里插入图片描述
不过这一步更类似于后处理,其实已经不是霍夫变换本身的特性了。
给出对应的代码:

clc;clear all;close all;
I  = imread('circuit.tif');
rotI = imrotate(I,40,'crop');
subplot 221
fig1 = imshow(rotI);
BW = edge(rotI,'canny');
title('原图像');
subplot 222
imshow(BW);
[H,theta,rho] = hough(BW);
title('图像边缘检测');
subplot 223
imshow(imadjust(mat2gray(H)),[],'XData',theta,'YData',rho,...
        'InitialMagnification','fit');
xlabel('\theta (degrees)'), ylabel('\rho');
axis on, axis normal, hold on;
colormap(hot)
P = houghpeaks(H,5,'threshold',ceil(0.7*max(H(:))));
x = theta(P(:,2));
y = rho(P(:,1));
plot(x,y,'s','color','black');
lines = houghlines(BW,theta,rho,P,'FillGap',5,'MinLength',7);
title('Hough空间');
subplot 224, imshow(rotI), 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','green');
 
   % Plot beginnings and ends of lines
   plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
   plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
 
   % Determine the endpoints of the longest line segment
   len = norm(lines(k).point1 - lines(k).point2);
   if ( len > max_len)
      max_len = len;
      xy_long = xy;
   end
end
 
% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','red');
title('直线检测');

在这里插入图片描述
效果还是比较接近的。
看到Stackoverflow上的一个答案,觉得很好,收藏一下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值