图像处理之霍夫变换.docx
- 文档编号:7501386
- 上传时间:2023-01-24
- 格式:DOCX
- 页数:15
- 大小:140.43KB
图像处理之霍夫变换.docx
《图像处理之霍夫变换.docx》由会员分享,可在线阅读,更多相关《图像处理之霍夫变换.docx(15页珍藏版)》请在冰豆网上搜索。
图像处理之霍夫变换
图像处理之霍夫变换(直线检测算法)
霍夫变换是图像变换中的经典手段之一,主要用来从图像中分离出具有某种相同特征的几何
形状(如,直线,圆等)。
霍夫变换寻找直线与圆的方法相比与其它方法可以更好的减少噪
声干扰。
经典的霍夫变换常用来检测直线,圆,椭圆等。
霍夫变换算法思想:
以直线检测为例,每个像素坐标点经过变换都变成都直线特质有贡献的统一度量,一个简单
的例子如下:
一条直线在图像中是一系列离散点的集合,通过一个直线的离散极坐标公式,
可以表达出直线的离散点几何等式如下:
X*cos(theta)+y*sin(theta) =r其中角度theta指r与X轴之间的夹角,r为到直线几何垂
直距离。
任何在直线上点,x,y都可以表达,其中r,theta是常量。
该公式图形表示如下:
然而在实现的图像处理领域,图像的像素坐标P(x,y)是已知的,而r,theta则是我们要寻找
的变量。
如果我们能绘制每个(r,theta)值根据像素点坐标P(x,y)值的话,那么就从图像笛卡
尔坐标系统转换到极坐标霍夫空间系统,这种从点到曲线的变换称为直线的霍夫变换。
变换
通过量化霍夫参数空间为有限个值间隔等分或者累加格子。
当霍夫变换算法开始,每个像素
坐标点P(x,y)被转换到(r,theta)的曲线点上面,累加到对应的格子数据点,当一个波峰出现
时候,说明有直线存在。
同样的原理,我们可以用来检测圆,只是对于圆的参数方程变为如
下等式:
(x–a)^2+(y-b)^2=r^2其中(a,b)为圆的中心点坐标,r圆的半径。
这样霍夫的参数空间就
变成一个三维参数空间。
给定圆半径转为二维霍夫参数空间,变换相对简单,也比较常用。
编程思路解析:
1. 读取一幅带处理二值图像,最好背景为黑色。
2. 取得源像素数据
3. 根据直线的霍夫变换公式完成霍夫变换,预览霍夫空间结果
4. 寻找最大霍夫值,设置阈值,反变换到图像RGB值空间(程序难点之一)
5. 越界处理,显示霍夫变换处理以后的图像
关键代码解析:
直线的变换角度为[0~PI]之间,设置等份为500为PI/500,同时根据参数直线参数方程的取值
范围为[-r,r]有如下霍夫参数定义:
[java] viewplaincopy
1.// prepare for hough transform
2.int centerX = width / 2;
3.int centerY = height / 2;
4.double hough_interval = PI_VALUE/(double)hough_space;
5.
6.int max = Math.max(width, height);
7.int max_length = (int)(Math.sqrt(2.0D) * max);
8.hough_1d = new int[2 * hough_space * max_length];
实现从像素RGB空间到霍夫空间变换的代码为:
[java] viewplaincopy
1.// start hough transform now....
2.int[][] image_2d = convert1Dto2D(inPixels);
3.for (int row = 0; row < height; row++) {
4. for (int col = 0; col < width; col++) {
5. int p = image_2d[row][col] & 0xff;
6. if(p == 0) continue; // which means background color
7.
8. // since we does not know the theta angle and r value,
9. // we have to calculate all hough space for each pixel point
10. // then we got the max possible theta and r pair.
11. // r = x * cos(theta) + y * sin(theta)
12. for(int cell=0; cell < hough_space; cell++ ) {
13. max = (int)((col - centerX) * Math.cos(cell * hough_interval) + (row - centerY) * Math.sin(cell * hough_interval));
14. max += max_length; // start from zero, not (-max_length)
15. if (max < 0 || (max >= 2 * max_length)) {// make sure r did not out of scope[0, 2*max_lenght]
16. continue;
17. }
18. hough_2d[cell][max] +=1;
19. }
20. }
21.}
寻找最大霍夫值计算霍夫阈值的代码如下:
[java] viewplaincopy
1.// find the max hough value
2.int max_hough = 0;
3.for(int i=0; i 4. for(int j=0; j<2*max_length; j++) { 5. hough_1d[(i + j * hough_space)] = hough_2d[i][j]; 6. if(hough_2d[i][j] > max_hough) { 7. max_hough = hough_2d[i][j]; 8. } 9. } 10.} 11.System.out.println("MAX HOUGH VALUE = " + max_hough); 12. 13.// transfer back to image pixels space from hough parameter space 14.int hough_threshold = (int)(threshold * max_hough); 从霍夫空间反变换回像素数据空间代码如下: [java] viewplaincopy 1.// transfer back to image pixels space from hough parameter space 2.int hough_threshold = (int)(threshold * max_hough); 3.for(int row = 0; row < hough_space; row++) { 4. for(int col = 0; col < 2*max_length; col++) { 5. if(hough_2d[row][col] < hough_threshold) // discard it 6. continue; 7. int hough_value = hough_2d[row][col]; 8. boolean isLine = true; 9. for(int i=-1; i<2; i++) { 10. for(int j=-1; j<2; j++) { 11. if(i ! = 0 || j ! = 0) { 12. int yf = row + i; 13. int xf = col + j; 14. if(xf < 0) continue; 15. if(xf < 2*max_length) { 16. if (yf < 0) { 17. yf += hough_space; 18. } 19. if (yf >= hough_space) { 20. yf -= hough_space; 21. } 22. if(hough_2d[yf][xf] <= hough_value) { 23. continue; 24. } 25. isLine = false; 26. break; 27. } 28. } 29. } 30. } 31. if(! isLine) continue; 32. 33. // transform back to pixel data now... 34. double dy = Math.sin(row * hough_interval); 35. double dx = Math.cos(row * hough_interval); 36. if ((row <= hough_space / 4) || (row >= 3 * hough_space / 4)) { 37. for (int subrow = 0; subrow < height; ++subrow) { 38. int subcol = (int)((col - max_length - ((subrow - centerY) * dy)) / dx) + centerX; 39. if ((subcol < width) && (subcol >= 0)) { 40. image_2d[subrow][subcol] = -16776961; 41. } 42. } 43. } else { 44. for (int subcol = 0; subcol < width; ++subcol) { 45. int subrow = (int)((col - max_length - ((subcol - centerX) * dx)) / dy) + centerY; 46. if ((subrow < height) && (subrow >= 0)) { 47. image_2d[subrow][subcol] = -16776961; 48. } 49. } 50. } 51. } 52.} 霍夫变换源图如下: 霍夫变换以后,在霍夫空间显示如下: (白色表示已经找到直线信号) 最终反变换回到像素空间效果如下: 一个更好的运行监测直线的结果(输入为二值图像): 完整的霍夫变换源代码如下: [java] viewplaincopy 1.package com.gloomyfish.image.transform; 2. 3.import java.awt.image.BufferedImage; 4. 5.import com.process.blur.study.AbstractBufferedImageOp; 6. 7.public class HoughLineFilter extends AbstractBufferedImageOp { 8. public final static double PI_VALUE = Math.PI; 9. private int hough_space = 500; 10. private int[] hough_1d; 11. private int[][] hough_2d; 12. private int width; 13. private int height; 14. 15. private float threshold; 16. private float scale; 17. private float offset; 18. 19. public HoughLineFilter() { 20. // default hough transform parameters 21. // scale = 1.0f; 22. // offset = 0.0f; 23. threshold = 0.5f; 24. scale = 1.0f; 25. offset = 0.0f; 26. } 27. 28. public void setHoughSpace(int space) { 29. this.hough_space = space; 30. } 31. 32. public float getThreshold() { 33. return threshold; 34. } 35. 36. public void setThreshold(float threshold) { 37. this.threshold = threshold; 38. } 39. 40. public float getScale() { 41. return scale; 42. } 43. 44. public void setScale(float scale) { 45. this.scale = scale; 46. } 47. 48. public float getOffset() { 49. return offset; 50. } 51. 52. public void setOffset(float offset) { 53. this.offset = offset; 54. } 55. 56. @Override 57. public BufferedImage filter(BufferedImage src, BufferedImage dest) { 58. width = src.getWidth(); 59. height = src.getHeight(); 60. 61. if ( dest == null ) 62. dest = createCompatibleDestImage( src, null ); 63. 64. int[] inPixels = new int[width*height]; 65. int[] outPixels = new int[width*height]; 66. getRGB( src, 0, 0, width, height, inPixels ); 67. houghTransform(inPixels, outPixels); 68. setRGB( dest, 0, 0, width, height, outPixels ); 69. return dest; 70. } 71. 72. private void houghTransform(int[] inPixels, int[] outPixels) { 73. // prepare for hough transform 74. int centerX = width / 2; 75. int centerY = height / 2; 76. double hough_interval = PI_VALUE/(double)hough_space; 77. 78. int max = Math.max(width, height); 79. int max_length = (int)(Math.sqrt(2.0D) * max); 80. hough_1d = new int[2 * hough_space * max_length]; 81. 82. // define temp hough 2D array and initialize the hough 2D 83. hough_2d = new int[hough_space][2*max_length]; 84. for(int i=0; i 85. for(int j=0; j<2*max_length; j++) { 86. hough_2d[i][j] = 0; 87. } 88. } 89. 90. // start hough transform now.... 91. int[][] image_2d = convert1Dto2D(inPixels); 92. for (int row = 0; row < height; row++) { 93. for (int col = 0; col < width; col++) { 94. int p = image_2d[row][col] & 0xff; 95. if(p == 0) continue; // which means background color 96. 97. // since we does not know the theta angle and r value, 98. // we have to calculate all hough space for each pixel point 99. // then we got the max possible theta and r pair. 100. // r = x * cos(theta) + y * sin(theta) 101. for(int cell=0; cell < hough_space; cell++ ) { 102. max = (int)((col - centerX) * Math.cos(cell * hough_interval) + (row - centerY) * Math.sin(cell * hough_interval)); 103. max += max_length; // start from zero, not (-max_length) 104. if (max < 0 || (max >= 2 * max_length)) {// make sure r did not out of scope[0, 2*max_lenght] 105. continue; 106. } 107. hough_2d[cell][max] +=1; 108. } 109. } 110. } 111. 112.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 图像 处理 变换