查看: 932|回复: 10|关注: 0

[我分享] 离散广义霍夫变换。

[复制链接]

论坛优秀回答者

入门

356 麦片

财富积分


50500


10

主题

763

帖子

71

最佳答案
  • 关注者: 16
发表于 2017-10-24 11:52:51 | 显示全部楼层 |阅读模式
本帖最后由 zhangqinghao 于 2017-10-27 10:28 编辑

一般来讲广义霍夫变换是指把坐标空间的图像映射到参数空间,需要先确定转换到参数空间的函数关系式,这种转换是连续的,但是对于任意图形而言这种关系式往往很难确定,而且我们处理的图像本身就是离散的,不需要连续变换。对于有限长的曲线而言,只要确定对应每一个坐标对应的参数空间的映射表就能画出参数空间的离散曲线。之后根据累加值就可以识别任意曲线。代码实现如下:
  1. clearvars;
  2. close all;
  3. target = imread('target.jpg');
  4. pic = imread('test.jpg');
  5. target = rgb2gray(target);
  6. pic = rgb2gray(pic);
  7. target = target<50;
  8. pic = pic<50;
  9. figure;imshow(target);
  10. figure;imshow(pic);
  11. [y,x] = find(target);
  12. cx = round(mean(x));
  13. cy = round(mean(y));
  14. x_map = cx-x;
  15. y_map = cy-y;
  16. [W,L] = size(pic);
  17. [ys,xs] = find(pic);
  18. h_space = zeros(W,L);
  19. for flag = [ys,xs]'
  20.     ycs = y_map + flag(1);
  21.     xcs = x_map + flag(2);
  22.     r_ind = ycs>0&ycs<=W&xcs>0&xcs<=L;
  23.     h_space = h_space + accumarray([ycs(r_ind),xcs(r_ind)],1,[W,L]);
  24. end
  25. figure;
  26. imshow(h_space,[]);
  27. [yt,xt] = find(h_space == max(h_space(:)));
  28. pic_thunder = zeros(W,L);
  29. for ii = 1:length(yt)
  30.     pic_thunder = pic_thunder + accumarray([yt(ii)-y_map,xt(ii)-x_map],1,[W,L]);
  31. end
  32. pic_thunder = double(cat(3,ones(W,L),~pic_thunder,~pic));
  33. figure;
  34. imshow(pic_thunder);
复制代码


图像及效果:




回复主题 已获打赏: 0 积分

举报

论坛优秀回答者

入门

356 麦片

财富积分


50500


10

主题

763

帖子

71

最佳答案
  • 关注者: 16
 楼主| 发表于 2017-10-24 11:55:10 | 显示全部楼层
本帖最后由 zhangqinghao 于 2017-10-24 17:58 编辑

目标图像:

目标图像

目标图像

测试图像:

测试图像

测试图像

参数空间:

参数空间

参数空间

结果:

结果

结果



回复此楼 已获打赏: 0 积分

举报

论坛优秀回答者

入门

356 麦片

财富积分


50500


10

主题

763

帖子

71

最佳答案
  • 关注者: 16
 楼主| 发表于 2017-10-24 11:56:14 | 显示全部楼层
@laohu_tiger
这样详细说明你应该能理解了。
回复此楼 已获打赏: 0 积分

举报

论坛优秀回答者

入门

356 麦片

财富积分


50500


10

主题

763

帖子

71

最佳答案
  • 关注者: 16
 楼主| 发表于 2017-10-25 10:19:46 | 显示全部楼层
zhangqinghao 发表于 2017-10-24 11:56
@laohu_tiger
这样详细说明你应该能理解了。

今天突然发现,这样子相当于卷积求模板匹配,只不过过程有点差别。。。话说我用的是单机版吗。。。怎么每次发帖都没人回。。。
回复此楼 已获打赏: 0 积分

举报

论坛优秀回答者

高级

1840 麦片

财富积分


15002000


6

主题

1146

帖子

225

最佳答案
  • 关注者: 17
发表于 2017-10-26 16:04:02 | 显示全部楼层
不是单机,多谢分享
回复此楼 已获打赏: 0 积分

举报

论坛优秀回答者

入门

356 麦片

财富积分


50500


10

主题

763

帖子

71

最佳答案
  • 关注者: 16
 楼主| 发表于 2017-10-27 09:30:34 | 显示全部楼层
cxvista 发表于 2017-10-26 16:04
不是单机,多谢分享

哈哈,多谢,这个虽然结果跟模板匹配是一样的,但是计算时只计算了线条部分,计算量应该是比卷积实现模板匹配要少一些的,只不过我的代码多次使用accumarray导致速率比较慢,而且MATLAB应该对卷积进行了优化,所以实际上比用MATLAB的卷积要慢上很多。所以没有什么实际价值,不过对于帮助理解霍夫变换应该有一些帮助。每次accumarray得到的图像就是该像素点对应的所有可能的中心点的坐标,把所有像素点可能的中心点坐标加起来,累加值最高的就是目标图像的中心点坐标了。
回复此楼 已获打赏: 0 积分

举报

论坛优秀回答者

入门

356 麦片

财富积分


50500


10

主题

763

帖子

71

最佳答案
  • 关注者: 16
 楼主| 发表于 2017-10-27 13:19:12 | 显示全部楼层
cxvista 发表于 2017-10-26 16:04
不是单机,多谢分享

呃。。。怎么一直是未读,是不是出bug了?
回复此楼 已获打赏: 0 积分

举报

论坛优秀回答者

高级

1840 麦片

财富积分


15002000


6

主题

1146

帖子

225

最佳答案
  • 关注者: 17
发表于 2017-10-27 19:23:01 | 显示全部楼层
zhangqinghao 发表于 2017-10-27 13:19
呃。。。怎么一直是未读,是不是出bug了?

有可能,最近论坛改版  难免bug
回复此楼 已获打赏: 0 积分

举报

入门

60 麦片

财富积分


50500


18

主题

221

帖子

11

最佳答案
QQ
  • 关注者: 1
发表于 2017-10-31 20:12:34 | 显示全部楼层
  1. clearvars;
  2. close all;

  3. target = imread('target.jpg');%
  4. pic = imread('test.jpg');
  5. target = rgb2gray(target);
  6. pic = rgb2gray(pic);

  7. target = target<50;     %取阈值小于50的像素(目标的边缘)
  8. pic = pic<50;           %测试图像中的边缘
  9. figure;imshow(target);
  10. figure;imshow(pic);

  11. [y,x] = find(target);   %找目标中的非零像素(边缘)的位置
  12. cx = round(mean(x));    %取参考点(相对的目标中心)
  13. cy = round(mean(y));

  14. x_map = cx-x;           %相对位移(偏移)
  15. y_map = cy-y;

  16. [W,L] = size(pic);      %测试图像的大小

  17. [ys,xs] = find(pic);    %测试图像中边缘的位置
  18. h_space = zeros(W,L);   %霍夫空间,用来累积投票

  19. for flag = [ys,xs]'
  20.     ycs = y_map + flag(1);%假设当前的flag(1),flag(2)为目标中心,那么ycs和xcs则为这样的目标轮廓(边缘)的位置
  21.     xcs = x_map + flag(2);
  22.     r_ind = ycs>0 & ycs<=W & xcs>0 & xcs<=L; % 显然,位置必须在图像的范围之内
  23.     h_space = h_space + accumarray([ycs(r_ind),xcs(r_ind)],1,[W,L]); %这个是霍夫空间的累计值(累积的是目标中心的可能性,越大说明越可能是中心)
  24. end

  25. figure;
  26. imshow(h_space,[]);

  27. [yt,xt] = find(h_space == max(h_space(:))); %找到霍夫空间的极大值,这个就是投票(累加)得到的中心, 注意:有可能有多个!

  28. pic_thunder = zeros(W,L); %

  29. for ii = 1:length(yt)
  30.     pic_thunder = pic_thunder + accumarray([yt(ii)-y_map,xt(ii)-x_map],1,[W,L]);%那么,对每一个中心,都有一个目标轮廓(每个轮廓像素对中心都有一个相对位置)
  31. end
  32. pic_thunder = double(cat(3,ones(W,L),~pic_thunder,~pic)); %将图像扩展为彩色,把检测结果绘制在原图像上

  33. figure;
  34. imshow(pic_thunder);

  35. %感觉确实有点像模板匹配,是不是广义霍夫变换都是找到和目标形状一模一样的?
复制代码


将大牛 @zhangqinghao 的这段脚本注释了一下,获益匪浅,良师益友
回复此楼 已获打赏: 0 积分

举报

论坛优秀回答者

入门

356 麦片

财富积分


50500


10

主题

763

帖子

71

最佳答案
  • 关注者: 16
 楼主| 发表于 2017-11-1 09:21:51 | 显示全部楼层
laohu_tiger 发表于 2017-10-31 20:12
将大牛 @zhangqinghao 的这段脚本注释了一下,获益匪浅,良师益友

是要找到和目标形状一样的,如果加入其它变量,比如圆的半径,那么参数空间需要拓展到三维,计算量也随之增大,霍夫直线检测直线之所以这么流行是因为它把直线的参数用ρ和θ表示,能够在等大的空间内表示无限长的直线。霍夫圆也是因为有所改进,否则如果用原本的方法,那么霍夫圆检测在离散空间跟把所有可能的半径的圆做一遍模板匹配也没什么区别。
回复此楼 已获打赏: 0 积分

举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐上一条 /5 下一条

快速回复 返回顶部 返回列表