霍夫变换

霍夫变换是1972年提出来的,最开始就是用来在图像中过检测直线,后来扩展能检测圆、曲线等。

直线的霍夫变换就是 把xy空间的直线 换成成 另一空间的点。就是直线和点的互换。

我们在初中数学中了解到,一条直线可以用如下的方程来表示:y=kx+b,k是直线的斜率,b是截距。

我们转换下变成:b=-kx+y。我们是不是也可以把(k,b)看作另外一个空间中的点?这就是k-b参数空间。 这样,我们就把一条x-y直线用一个(k,b)的点表示出来了。

我们看到,在x-y图像空间中的一个点,变成了k-b参数空间中的一条直线,而x-y图像空间中的2点连成的直线,变成了k-b参数空间中的一个交点。

如果x-y图像空间中有很多点在k-b空间中相交于一点,那么这个交点就是我们要检测的直线。这就是霍夫变换检测直线的基本原理。

当然,有一个问题需要注意,图像空间中如果一条直线是垂直的,那么斜率k是没有定义的(或者说无穷大)。为了避免这个问题,霍夫变换采用了另一个参数空间:距离-角度参数空间。也就是极坐标。

我们在中学中学过,平面上的一个点也可以用距离-角度来定义,也就是极坐标。那么在图像中,每一个点都可以用距离和角度来表达:

但是,使用距离-角度后,点(x,y)与距离,角度的关系变成了:

ρ=xcosθ+ysinθ

于是,在新的距离-角度参数空间中,图像中的一个点变成了一个正弦曲线,而不是k-b参数空间中的直线了。这些正弦曲线的交点就是图像空间中我们要检测的直线了。

Matlab霍夫变换的函数详解

[H, theta, rho] = hough(BW,ParameterName, ParameterValue)

BW:二值图

ParameterName:'RhoResolution'或'Theta'

RhoResolution-指定在累计数组中(检测极值)的检测间隔?默认为1

Theta-指定检测的角度范围(不超过-90~90度)以及间隔,例如-90:0.5:89.5,默认-90:1:89

H:累计数组

Theta:H对应的θ,实际上H的大小就是Rho×Theta

Rho:H对应的ρ

这两个参数值的注意,RhoResolution太大覆盖不到极值点,检测到一些不对应直线的次极值,

峰值提取

peaks = houghpeaks(H,numpeaks)

peaks = houghpeaks(...,param1, val1, param2, val2)

H:累计数组;

Numpeaks:指定需要检测的峰值个数;

Param1:可以是'Threshold'或'NHoodSize'

'Threshold'-指定峰值的域值,默认是0.5*max(H(:))

'NHoodSize'-是个二维向量[m,n],检测到一个峰值后,将峰值周围[m,n]内元素置零。

画直线段

lines = houghlines(BW,theta, rho, peaks)

lines = houghlines(...,param1, val1, param2, val2)

BW:二值图

Theta、rho、peaks:分别来自函数hough和houghpeaks

Lines:结构数组,大小等于检测到的直线段数,每个单元包含

Point1、point2:线段的端点

Theta、rho:线段的theta和rho

下面实例演示

用霍夫变换判断矩形

所用图形是我用画图工具制作的,图片很干净,所以不需要滤波等措施。以下是图案。

img  = imread('a.png');
img_gray = rgb2gray(img); %背景是黑的!!!
threshold =graythresh(img_gray);%取阈值
bw=im2bw(img_gray,threshold);
if length(bw(bw==1))>length(bw(bw==0))
bw=~bw;
end
%填充
bw = imfill(bw,'holes'); figure(), imshow(img_gray), title('image'); [B,L] = bwboundaries(bw,'noholes');
stats = regionprops(L,'Area','Centroid','image');
boundary = B{1};
delta_sq = diff(boundary).^2;
perimeter = sum(sqrt(sum(delta_sq,2)));
% obtain the area calculation corresponding
area = stats(1).Area;
% compute the roundness metric
metric = 4*pi*area/perimeter^2;
if metric>0.9
disp('yuan')
else % the canny edge of image
BW = edge(bw,'canny');
% Iedge=edge(Ihsv,'sobel'); %边沿检测
%BW = imdilate(BW,ones(3));%图像膨胀
figure(), imshow(BW), title('image edge');
% the theta and rho of transformed space
[H,Theta,Rho] = hough(BW,'RhoResolution',1.2);
figure(), imshow(H,[],'XData',Theta,'YData',Rho,'InitialMagnification','fit'),...
title('rho\_theta space and peaks');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
% label the top 5 intersections
P = houghpeaks(H,4,'threshold',ceil(0.1*max(H(:))),'NHoodSize',[35,11]);
x = Theta(P(:,2));
y = Rho(P(:,1));
plot(x,y,'*','color','r'); % find lines and plot them
lines = houghlines(BW,Theta,Rho,P);
figure(), imshow(img),title('final image');
hold on
b_len = ones(1,length(lines));
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
b_len(1,k)=sqrt((xy(1,1)-xy(2,1))^2+(xy(1,2)-xy(2,2))^2);
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','r');
hold on
end
if var(b_len)<10
disp('正方形')
else
disp('长方形')
end
end

 然后得到结果

变换参数域图像(很完美,4个点)

结果图像

基本包含在原图形上,测试成功!

参考文献:

[1] http://blog.sina.com.cn/s/blog_ac7218750101giyf.html

[2] https://blog.csdn.net/saltriver/article/details/80547245

[3] https://ww2.mathworks.cn/help/images/ref/hough.html

盘外篇

自己写个Hough变换? hough的原理很简单,可以自己尝试以下。

那么我们检测一下 直线的斜率。

下面上代码

clear all;

img  = imread('demo1.png');
img_gray = rgb2gray(img); %二值化
threshold =graythresh(img_gray);%取阈值
bw=im2bw(img_gray,threshold);
if length(bw(bw==1))>length(bw(bw==0))
bw=~bw;
end figure(), imshow(bw), title('image');
% %填充
% bw = imfill(bw,'holes');
% %边沿检测
%the canny edge of image
%bw = edge(bw,'canny'); bw = imdilate(bw,ones(8)); %图像膨胀(因为直线太细会使误差增大)
%figure(), imshow(bw), title('image ');
%the theta and rho of transformed space
[H,Theta,Rho] = hough1(bw);
figure(), imshow(H,[],'XData',Theta,'YData',Rho,'InitialMagnification','fit'),...
title('rho\_theta space and peaks');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
%label the top 1 intersections
%P = houghpeaks(H,1);
[xx,yy]=find(H==max(max(H)),1);
P=[xx,yy];
x = Theta(P(:,2));
y = Rho(P(:,1));
plot(x,y,'*','color','r'); [m,n]=size(bw);
label=zeros(m,n);
xy=[];
for ii=1:length(bw)
jj=ceil((y-ii*cos(x/180*pi))/sin(x/180*pi));
if jj>=1&& jj<=n
label(ii,jj)=1;
if bw(ii,jj)==1
xy=[xy;jj,ii]; %因为plot和imshow的xy轴是镜像关系!
end
end
end %find lines and plot them
%lines = houghlines(bw,Theta,Rho,P);
figure(), imshow(img),title('final image');
hold on
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','r'); k=-sin(x/180*pi)/cos(x/180*pi);
b=y/cos(x/180*pi);
disp(['斜率是',num2str(k)])
disp(['y轴截距是',num2str(b)]) %ezplot('x*cos(-72/180*pi)+y*sin(-72/180*pi)=-31',[0,256])

  下面就是自己写的hough变换函数了

function [h, theta, rho] = hough1(f, dtheta, drho)

if  nargin < 3
drho = 1;
end
if nargin < 2
dtheta = 1;
end f = double(f);
[M,N] = size(f);
theta = linspace(-90, 0, ceil(90/dtheta) + 1);
theta = [theta -fliplr(theta(2:end - 1))];
ntheta = length(theta); D = sqrt((M - 1)^2 + (N - 1)^2);
q = ceil(D/drho);
nrho = 2*q - 1;
rho = linspace(-q*drho, q*drho, nrho); [x, y, val] = find(f);
x = x - 1; y = y - 1; h = zeros(nrho, length(theta)); for k = 1:ceil(length(val)/1000)
first = (k - 1)*1000 + 1;
last = min(first+999, length(x)); x_matrix = repmat(x(first:last), 1, ntheta);
y_matrix = repmat(y(first:last), 1, ntheta);
val_matrix = repmat(val(first:last), 1, ntheta);
theta_matrix = repmat(theta, size(x_matrix, 1), 1)*pi/180; rho_matrix = x_matrix.*cos(theta_matrix) + ...
y_matrix.*sin(theta_matrix);
slope = (nrho - 1)/(rho(end) - rho(1));
rho_bin_index = round(slope*(rho_matrix - rho(1)) + 1); theta_bin_index = repmat(1:ntheta, size(x_matrix, 1), 1); h = h + full(sparse(rho_bin_index(:), theta_bin_index(:), ...
val_matrix(:), nrho, ntheta));
end

  结果还不错

matlab-霍夫变换详解(判断正方形长方形)的更多相关文章

  1. 【转】小波与小波包、小波包分解与信号重构、小波包能量特征提取 暨 小波包分解后实现按频率大小分布重新排列(Matlab 程序详解)

    转:https://blog.csdn.net/cqfdcw/article/details/84995904 小波与小波包.小波包分解与信号重构.小波包能量特征提取   (Matlab 程序详解) ...

  2. Matlab绘图详解

    Matlab绘图 强大的绘图功能是Matlab的特点之一,Matlab提供了一系列的绘图函数,用户不需要过多的考虑绘图的细节,只需要给出一些基本参数就能得到所需图形,这类函数称为高层绘图函数.此外,M ...

  3. SVM matlab 代码详解说明

    x=[0 1 0 1 2 -1];y=[0 0 1 1 2 -1];z=[-1 1 1 -1 1 1]; %其中,(x,y)代表二维的数据点,z 表示相应点的类型属性. data=[1,0;0,1;2 ...

  4. 混淆矩阵-MATLAB代码详解

    一.混淆矩阵 (一).简介 在人工智能中,混淆矩阵(confusion matrix)是可视化工具,特别用于监督学习,在无监督学习一般叫做匹配矩阵.在图像精度评价中,主要用于比较分类结果和实际测得值, ...

  5. VC 与Matlab混合编程之引擎操作详解

    Visual C++ 是当前主流的应用程序开发环境之一,开发环境强大,开发的程序执行速度快.但在科学计算方面函数库显得不够丰富.读取.显示数据图形不方便. Matlab 是一款将数值分析.矩阵计算.信 ...

  6. Swift流程控制之循环语句和判断语句详解

    Swift提供了所有c类语言的控制流结构.包括for和while循环来执行一个任务多次:if和switch语句来执行确定的条件下不同的分支的代码:break和continue关键字能将运行流程转到你代 ...

  7. 算法进阶面试题01——KMP算法详解、输出含两次原子串的最短串、判断T1是否包含T2子树、Manacher算法详解、使字符串成为最短回文串

    1.KMP算法详解与应用 子序列:可以连续可以不连续. 子数组/串:要连续 暴力方法:逐个位置比对. KMP:让前面的,指导后面. 概念建设: d的最长前缀与最长后缀的匹配长度为3.(前缀不能到最后一 ...

  8. PCA (主成分分析)详解 (写给初学者) 结合matlab(转载)

    一.简介 PCA(Principal Components Analysis)即主成分分析,是图像处理中经常用到的降维方法,大家知道,我们在处理有关数字图像处理方面的问题时,比如经常用的图像的查询问题 ...

  9. Jquery 选择器 详解 js 判断字符串是否包含另外一个字符串

    Jquery 选择器 详解   在线文档地址:http://tool.oschina.net/apidocs/apidoc?api=jquery 各种在线工具地址:http://www.ostools ...

随机推荐

  1. 使用VMWare虚拟机打开MFC报错:不支持16位系统

    可能这个问题的比较小众,但还是提供一下自己的思路. 笔者使用的是VMWare Fusion11的版本,采用windows7sp1的虚拟机. 在打开Mac系统共享过来的VC++的MFC文件运行时报错:不 ...

  2. dll被设置为用记事本打开的解决方法

    dll被设置为用记事本打开的解决方法: 打开注册表编辑器 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Fi ...

  3. Jquery的动态切换图片

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. 交换排序-C#实现

    交换排序包括:冒泡排序和快速排序 具体代码如下: 冒泡排序: /// <summary> /// 冒泡排序 /// 稳定性:稳定 /// 时间复杂度:O(n2) /// </summ ...

  5. skimage

    它是由python语言编写的,   子模块名称 主要实现功能 io 读取.保存和显示图片或视频 data 提供一些测试图片和样本数据 color 颜色空间变换 filters 图像增强.边缘检测.排序 ...

  6. Nginx failing to load CSS and JS files (MIME type error)

    Nginx failing to load CSS and JS files (MIME type error) Nginx加载静态文件失败的解决方法(MIME type错误) 上线新的页面,需要在n ...

  7. Docker系列(三)Dockerfile 离线构建镜像

    一.Dockfile介绍: Dockfile是一种被Docker程序解释的脚本,Dockerfile由一条一条的指令组成,每条指令对应Linux下面的一条命令.Docker程序将这些Dockerfil ...

  8. 剑指offer 7. 递归和循环 斐波那契数列

    题目描述 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0). n<=39 简简单单 废话不多说,直接上代码: public class Sol ...

  9. 用openssl为WEB服务器生成证书(自签名CA证书,服务器证书)

    用openssl为WEB服务器生成证书(自签名CA证书,服务器证书) 来源: https://www.cnblogs.com/osnosn/p/10608455.html 来自osnosn的博客 写于 ...

  10. 一个HTTP打趴80%面试者

    面试多年,每当我问起面试者对HTTP的了解时,个个回答令我瞠目结舌,这些开发者都有3-5年的经验.请不要让我叫你野生程序员,是时候了解HTTP了,让我们当个正规军. 起因 面试官:请问你了解HTTP协 ...