霍夫变换

霍夫变换是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

下面实例演示

用霍夫变换判断矩形

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

  1. img = imread('a.png');
  2. img_gray = rgb2gray(img);
  3.  
  4. %背景是黑的!!!
  5. threshold =graythresh(img_gray);%取阈值
  6. bw=im2bw(img_gray,threshold);
  7. if length(bw(bw==1))>length(bw(bw==0))
  8. bw=~bw;
  9. end
  10. %填充
  11. bw = imfill(bw,'holes');
  12.  
  13. figure(), imshow(img_gray), title('image');
  14.  
  15. [B,L] = bwboundaries(bw,'noholes');
  16. stats = regionprops(L,'Area','Centroid','image');
  17. boundary = B{1};
  18. delta_sq = diff(boundary).^2;
  19. perimeter = sum(sqrt(sum(delta_sq,2)));
  20. % obtain the area calculation corresponding
  21. area = stats(1).Area;
  22. % compute the roundness metric
  23. metric = 4*pi*area/perimeter^2;
  24. if metric>0.9
  25. disp('yuan')
  26. else
  27.  
  28. % the canny edge of image
  29. BW = edge(bw,'canny');
  30. % Iedge=edge(Ihsv,'sobel'); %边沿检测
  31. %BW = imdilate(BW,ones(3));%图像膨胀
  32. figure(), imshow(BW), title('image edge');
  33. % the theta and rho of transformed space
  34. [H,Theta,Rho] = hough(BW,'RhoResolution',1.2);
  35. figure(), imshow(H,[],'XData',Theta,'YData',Rho,'InitialMagnification','fit'),...
  36. title('rho\_theta space and peaks');
  37. xlabel('\theta'), ylabel('\rho');
  38. axis on, axis normal, hold on;
  39. % label the top 5 intersections
  40. P = houghpeaks(H,4,'threshold',ceil(0.1*max(H(:))),'NHoodSize',[35,11]);
  41. x = Theta(P(:,2));
  42. y = Rho(P(:,1));
  43. plot(x,y,'*','color','r');
  44.  
  45. % find lines and plot them
  46. lines = houghlines(BW,Theta,Rho,P);
  47. figure(), imshow(img),title('final image');
  48. hold on
  49. b_len = ones(1,length(lines));
  50. for k = 1:length(lines)
  51. xy = [lines(k).point1; lines(k).point2];
  52. b_len(1,k)=sqrt((xy(1,1)-xy(2,1))^2+(xy(1,2)-xy(2,2))^2);
  53. plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','r');
  54. hold on
  55. end
  56. if var(b_len)<10
  57. disp('正方形')
  58. else
  59. disp('长方形')
  60. end
  61. 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的原理很简单,可以自己尝试以下。

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

下面上代码

  1. clear all;
  2.  
  3. img = imread('demo1.png');
  4. img_gray = rgb2gray(img);
  5.  
  6. %二值化
  7. threshold =graythresh(img_gray);%取阈值
  8. bw=im2bw(img_gray,threshold);
  9. if length(bw(bw==1))>length(bw(bw==0))
  10. bw=~bw;
  11. end
  12.  
  13. figure(), imshow(bw), title('image');
  14. % %填充
  15. % bw = imfill(bw,'holes');
  16. % %边沿检测
  17. %the canny edge of image
  18. %bw = edge(bw,'canny');
  19.  
  20. bw = imdilate(bw,ones(8)); %图像膨胀(因为直线太细会使误差增大)
  21. %figure(), imshow(bw), title('image ');
  22. %the theta and rho of transformed space
  23. [H,Theta,Rho] = hough1(bw);
  24. figure(), imshow(H,[],'XData',Theta,'YData',Rho,'InitialMagnification','fit'),...
  25. title('rho\_theta space and peaks');
  26. xlabel('\theta'), ylabel('\rho');
  27. axis on, axis normal, hold on;
  28. %label the top 1 intersections
  29. %P = houghpeaks(H,1);
  30. [xx,yy]=find(H==max(max(H)),1);
  31. P=[xx,yy];
  32. x = Theta(P(:,2));
  33. y = Rho(P(:,1));
  34. plot(x,y,'*','color','r');
  35.  
  36. [m,n]=size(bw);
  37. label=zeros(m,n);
  38. xy=[];
  39. for ii=1:length(bw)
  40. jj=ceil((y-ii*cos(x/180*pi))/sin(x/180*pi));
  41. if jj>=1&& jj<=n
  42. label(ii,jj)=1;
  43. if bw(ii,jj)==1
  44. xy=[xy;jj,ii]; %因为plotimshowxy轴是镜像关系!
  45. end
  46. end
  47. end
  48.  
  49. %find lines and plot them
  50. %lines = houghlines(bw,Theta,Rho,P);
  51. figure(), imshow(img),title('final image');
  52. hold on
  53. plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','r');
  54.  
  55. k=-sin(x/180*pi)/cos(x/180*pi);
  56. b=y/cos(x/180*pi);
  57. disp(['斜率是',num2str(k)])
  58. disp(['y轴截距是',num2str(b)])
  59.  
  60. %ezplot('x*cos(-72/180*pi)+y*sin(-72/180*pi)=-31',[0,256])

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

  1. function [h, theta, rho] = hough1(f, dtheta, drho)
  2.  
  3. if nargin < 3
  4. drho = 1;
  5. end
  6. if nargin < 2
  7. dtheta = 1;
  8. end
  9.  
  10. f = double(f);
  11. [M,N] = size(f);
  12. theta = linspace(-90, 0, ceil(90/dtheta) + 1);
  13. theta = [theta -fliplr(theta(2:end - 1))];
  14. ntheta = length(theta);
  15.  
  16. D = sqrt((M - 1)^2 + (N - 1)^2);
  17. q = ceil(D/drho);
  18. nrho = 2*q - 1;
  19. rho = linspace(-q*drho, q*drho, nrho);
  20.  
  21. [x, y, val] = find(f);
  22. x = x - 1; y = y - 1;
  23.  
  24. h = zeros(nrho, length(theta));
  25.  
  26. for k = 1:ceil(length(val)/1000)
  27. first = (k - 1)*1000 + 1;
  28. last = min(first+999, length(x));
  29.  
  30. x_matrix = repmat(x(first:last), 1, ntheta);
  31. y_matrix = repmat(y(first:last), 1, ntheta);
  32. val_matrix = repmat(val(first:last), 1, ntheta);
  33. theta_matrix = repmat(theta, size(x_matrix, 1), 1)*pi/180;
  34.  
  35. rho_matrix = x_matrix.*cos(theta_matrix) + ...
  36. y_matrix.*sin(theta_matrix);
  37. slope = (nrho - 1)/(rho(end) - rho(1));
  38. rho_bin_index = round(slope*(rho_matrix - rho(1)) + 1);
  39.  
  40. theta_bin_index = repmat(1:ntheta, size(x_matrix, 1), 1);
  41.  
  42. h = h + full(sparse(rho_bin_index(:), theta_bin_index(:), ...
  43. val_matrix(:), nrho, ntheta));
  44. 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. Django 数据迁移

    在1.6之前, Django只支持添加新的model到数据库, 而无法编辑或修改已经存在的model. 在当时, 这些Django缺失的功能可以通过South实现. 1. 新的命令 Django 1. ...

  2. hdu 1394 逆序对(nlgn+o(n) )

    Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s) ...

  3. python3+qqBot+图灵机器人实现qq聊天机器人

    原理: 通过Python3的qqBot开源库,基于腾讯的smartQQ协议登录个人QQ,实现监控.收集QQ消息,进而通过图灵机器人API接入方式实现自动聊天. 零.前期准备: 1.Python3 2. ...

  4. 软件可维护性的影响因素&如何提升

    影响因素: 1.可理解性 2.可测试性 3.可修改性 4.可移植性 5.可重用性 如何提升: 1.建立明确的软件质量目标2.使用先进的软件开发技术和工具3.建立明确的质量保证4.选择可维护的语言5.改 ...

  5. JDBC-Oracle连接教程

    前言 本文通过一个在Eclipse平台中搭建的小项目,在项目中使用一条静态命令来查询Oracle数据库测试用户“scott”下emp表中的几个字段,来学习JDBC连接数据库的方法.看完之后读者可以基本 ...

  6. JAVA结对编程--阶段总结

    一.需求分析 1.基本需求 随机生成n道题目 支持整数.分数,支持多运算符 能判断正误,错误时给出正确答案 能计算出正确率 2.扩展需求 处理生成题目并输出到文件 完成题目后从文件读入并判题 支持多语 ...

  7. Python importlib(动态导入模块)

    使用 Python importlib(动态导入模块) 可以将字符串型的模块名导入 示例: import importlib module = 'module name' # 字符串型模块名 test ...

  8. Cent os6.5 安装python3.2

    1.CentOS6.5 安装Python 的依赖包 yum groupinstall "Development tools" yum install zlib-devel bzip ...

  9. ss - linux网络工具

    用以替代netstat 参看 http://www.cnblogs.com/peida/archive/2013/03/11/2953420.html 常用命令: ss -ptl | grep 991 ...

  10. net use远程重启服务器

      在命令行工具中分别输入如下3条命令 net use \\10.10.1.100\ipc$ Password /user:Username shutdown -f -r -m \\10.10.1.1 ...