




已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
图像处理之霍夫变换圆检测算法一:霍夫变换检测圆的数学原理根据极坐标,圆上任意一点的坐标可以表示为如上形式, 所以对于任意一个圆, 假设中心像素点p(x0, y0)像素点已知, 圆半径已知,则旋转360由极坐标方程可以得到每个点上得坐标同样,如果只是知道图像上像素点, 圆半径,旋转360则中心点处的坐标值必定最强.这正是霍夫变换检测圆的数学原理.二:算法流程该算法大致可以分为以下几个步骤三:运行效果图像从空间坐标变换到极坐标效果, 最亮一点为圆心.图像从极坐标变换回到空间坐标,检测结果显示:四:关键代码解析个人觉得这次注释已经是非常的详细啦,而且我写的还是中文注释javaview plaincopy1. /*2. *霍夫变换处理-检测半径大小符合的圆的个数3. *1.将图像像素从2D空间坐标转换到极坐标空间4. *2.在极坐标空间中归一化各个点强度,使之在0255之间5. *3.根据极坐标的R值与输入参数(圆的半径)相等,寻找2D空间的像素点6. *4.对找出的空间像素点赋予结果颜色(红色)7. *5.返回结果2D空间像素集合8. *returnint9. */10. publicintprocess()11. 12. /对于圆的极坐标变换来说,我们需要360度的空间梯度叠加值13. acc=newintwidth*height;14. for(inty=0;yheight;y+)15. for(intx=0;xwidth;x+)16. accy*width+x=0;17. 18. 19. intx0,y0;20. doublet;21. for(intx=0;xwidth;x+)22. for(inty=0;yheight;y+)23. 24. if(inputy*width+x&0xff)=255)25. 26. for(inttheta=0;theta360;theta+)27. t=(theta*3.14159265)/180;/角度值02*PI28. x0=(int)Math.round(x-r*Math.cos(t);29. y0=(int)Math.round(y-r*Math.sin(t);30. if(x00&y00)31. accx0+(y0*width)+=1;32. 33. 34. 35. 36. 37. 38. /nownormaliseto255andputinformatforapixelarray39. intmax=0;40. 41. /Findmaxaccvalue42. for(intx=0;xwidth;x+)43. for(inty=0;ymax)46. max=accx+(y*width);47. 48. 49. 50. 51. /根据最大值,实现极坐标空间的灰度值归一化处理52. intvalue;53. for(intx=0;xwidth;x+)54. for(inty=0;yheight;y+)55. value=(int)(double)accx+(y*width)/(double)max)*255.0);56. accx+(y*width)=0xff000000|(value16|value8|value);57. 58. 59. 60. /绘制发现的圆61. findMaxima();62. System.out.println(done);63. returnoutput;64. 完整的算法源代码, 已经全部的加上注释javaview plaincopy1. packagecom.gloomyfish.image.transform.hough;2. /*3. *4. *传入的图像为二值图像,背景为黑色,目标前景颜色为为白色5. *authorgloomyfish6. *7. */8. publicclassCircleHough9. 10. privateintinput;11. privateintoutput;12. privateintwidth;13. privateintheight;14. privateintacc;15. privateintaccSize=1;16. privateintresults;17. privateintr;/圆周的半径大小18. 19. publicCircleHough()20. System.out.println(HoughCircleDetection.);21. 22. 23. publicvoidinit(intinputIn,intwidthIn,intheightIn,intradius)24. r=radius;25. width=widthIn;26. height=heightIn;27. input=newintwidth*height;28. output=newintwidth*height;29. input=inputIn;30. for(inty=0;yheight;y+)31. for(intx=0;xwidth;x+)32. outputx+(width*y)=0xff000000;/默认图像背景颜色为黑色33. 34. 35. 36. 37. publicvoidsetCircles(intcircles)38. accSize=circles;/检测的个数39. 40. 41. /*42. *霍夫变换处理-检测半径大小符合的圆的个数43. *1.将图像像素从2D空间坐标转换到极坐标空间44. *2.在极坐标空间中归一化各个点强度,使之在0255之间45. *3.根据极坐标的R值与输入参数(圆的半径)相等,寻找2D空间的像素点46. *4.对找出的空间像素点赋予结果颜色(红色)47. *5.返回结果2D空间像素集合48. *returnint49. */50. publicintprocess()51. 52. /对于圆的极坐标变换来说,我们需要360度的空间梯度叠加值53. acc=newintwidth*height;54. for(inty=0;yheight;y+)55. for(intx=0;xwidth;x+)56. accy*width+x=0;57. 58. 59. intx0,y0;60. doublet;61. for(intx=0;xwidth;x+)62. for(inty=0;yheight;y+)63. 64. if(inputy*width+x&0xff)=255)65. 66. for(inttheta=0;theta360;theta+)67. t=(theta*3.14159265)/180;/角度值02*PI68. x0=(int)Math.round(x-r*Math.cos(t);69. y0=(int)Math.round(y-r*Math.sin(t);70. if(x00&y00)71. accx0+(y0*width)+=1;72. 73. 74. 75. 76. 77. 78. /nownormaliseto255andputinformatforapixelarray79. intmax=0;80. 81. /Findmaxaccvalue82. for(intx=0;xwidth;x+)83. for(inty=0;ymax)86. max=accx+(y*width);87. 88. 89. 90. 91. /根据最大值,实现极坐标空间的灰度值归一化处理92. intvalue;93. for(intx=0;xwidth;x+)94. for(inty=0;yheight;y+)95. value=(int)(double)accx+(y*width)/(double)max)*255.0);96. accx+(y*width)=0xff000000|(value16|value8|value);97. 98. 99. 100. /绘制发现的圆101. findMaxima();102. System.out.println(done);103. returnoutput;104. 105. 106. privateintfindMaxima()107. results=newintaccSize*3;108. intoutput=newintwidth*height;109. 110. /获取最大的前accSize个值111. for(intx=0;xwidth;x+)112. for(inty=0;yresults(accSize-1)*3)117. 118. /addtobottomofarray119. results(accSize-1)*3=value;/像素值120. results(accSize-1)*3+1=x;/坐标X121. results(accSize-1)*3+2=y;/坐标Y122. 123. /shiftupuntilitsinrightplace124. inti=(accSize-2)*3;125. while(i=0)&(resultsi+3resultsi)126. for(intj=0;j3;j+)127. inttemp=resultsi+j;128. resultsi+j=resultsi+3+j;129. resultsi+3+j=temp;130. 131. i=i-3;132. if(i=0;i-)142. drawCircle(resultsi*3,resultsi*3+1,resultsi*3+2);143. 144. returnoutput;145. 146. 147. privatevoidsetPixel(intvalue,intxPos,intyPos)148. /output(yPos*width)+xPos=0xff000000|(value16|value8|value);149. output(yPos*width)+xPos=0xffff0000;150. 151. 152. /drawcircleatxy153. privatevoiddrawCircle(intpix,intxCenter,intyCenter)154. pix=250;/颜色值,默认为白色155. 156. intx,y,r2;157. intradius=r;158. r2=r*r;159. 160. /绘制圆的上下左右四个点161. setPixel(pix,xCenter,yCenter+radius);162. setPixel(pix,xCenter,yCenter-radius);163. setPixel(pix,xCenter+radius,yCenter);164. setPixel(pix,xCenter-radius,yCenter);165. 166. y=radius;167. x=1;168. y=(int)(Math.sqrt(r2-1)+0.5);169. 170. /边缘填充算法,其实可以直接对循环所有像素,计算到做中心点距离来做171. /这个方法是别人写的,发现超赞,超好!172. while(xy)173. setPixel(pix,xCenter+x,yCenter+y);174. setPixel(pix,xCenter+x,yCenter-y);175. setPixel(pix,xCenter-x,yCenter+y);176. setPixel(pix,xCenter-x,yCenter-y);177. setPixel(pix,xCenter+y,yCenter+x);178. setPixel(pix,xCenter+y,yCenter-x);179. setPixel(pix,xCenter-y,yCenter+x);180. setPixel(pix,xCenter-y,yCenter-x);181. x+=1;182. y=(int)(Math.sqrt(r2-x*x)+0.5);183. 184. if(x=y)185. setPixel(pix,xCenter+x,yCenter+y);186. setPixel(pix,xCenter+x,yCenter-y);187. setPixel(pix,xCenter-x,yCenter+y);188. setPixel(pix,xCenter-x,yCenter-y);189. 190. 191. 192. publicintgetAcc()193. returnacc;194. 195. 196. 测试的UI类:javaview plaincopy1. packagecom.gloomyfish.image.transform.hough;2. 3. importjava.awt.BorderLayout;4. importjava.awt.Color;5. importjava.awt.Dimension;6. importjava.awt.FlowLayout;7. importjava.awt.Graphics;8. importjava.awt.Graphics2D;9. importjava.awt.GridLayout;10. importjava.awt.event.ActionEvent;11. importjava.awt.event.ActionListener;12. importjava.awt.image.BufferedImage;13. importjava.io.File;14. 15. importjavax.imageio.ImageIO;16. importjavax.swing.BorderFactory;17. importjavax.swing.JButton;18. importjavax.swing.JFrame;19. importjavax.swing.JPanel;20. importjavax.swing.JSlider;21. importjavax.swing.event.ChangeEvent;22. importjavax.swing.event.ChangeListener;23. 24. publicclassHoughUIextendsJFrameimplementsActionListener,ChangeListener25. /*26. *27. */28. publicstaticfinalStringCMD_LINE=LineDetection;29. publicstaticfinalStringCMD_CIRCLE=CircleDetection;30. privatestaticfinallongserialVersionUID=1L;31. privateBufferedImagesourceImage;32. /privateBufferedImagehoughImage;33. privateBufferedImageresultImage;34. privateJButtonlineBtn;35. privateJButtoncircleBtn;36. privateJSliderradiusSlider;37. privateJSlidernumberSlider;38. publicHoughUI(StringimagePath)39. 40. super(GloomyFish-ImageProcessDemo);41. try42. Filefile=newFile(imagePath);43. sourceImage=ImageIO.read(file);44. catch(Exceptione)45. e.printStackTrace();46. 47. initComponent();48. 49. 50. privatevoidinitComponent()51. intRADIUS_MIN=1;52. intRADIUS_INIT=1;53. intRADIUS_MAX=51;54. lineBtn=newJButton(CMD_LINE);55. circleBtn=newJButton(CMD_CIRCLE);56. radiusSlider=newJSlider(JSlider.HORIZONTAL,RADIUS_MIN,RADIUS_MAX,RADIUS_INIT);57. radiusSlider.setMajorTickSpacing(10);58. radiusSlider.setMinorTickSpacing(1);59. radiusSlider.setPaintTicks(true);60. radiusSlider.setPaintLabels(true);61. numberSlider=newJSlider(JSlider.HORIZONTAL,RADIUS_MIN,RADIUS_MAX,RADIUS_INIT);62. numberSlider.setMajorTickSpacing(10);63. numberSlider.setMinorTickSpacing(1);64. numberSlider.setPaintTicks(true);65. numberSlider.setPaintLabels(true);66. 67. JPanelsliderPanel=newJPanel();68. sliderPanel.setLayout(newGridLayout(1,2);69. sliderPanel.setBorder(BorderFactory.createTitledBorder(Settings:);70. sliderPanel.add(radiusSlider);71. sliderPanel.add(numberSlider);72. JPanelbtnPanel=newJPanel();73. btnPanel.setLayout(newFlowLayout(FlowLayout.RIGHT);74. btnPanel.add(lineBtn);75. btnPanel.add(circleBtn);76. 77. 78. JPanelimagePanel=newJPanel()79. 80. privatestaticfinallongserialVersionUID=1L;81. 82. protectedvoidpaintComponent(Graphicsg)83. if(sourceImage!=null)84. 85. Graphics2Dg2=(Graphics2D)g;86. g2.drawImage(sourceImage,10,10,sourceImage.getWidth(),sourceImage.getHeight(),null);87. g2.setPaint(Color.BLUE);88. g2.drawString(原图,10,sourceImage.getHeight()+30);89. if(resultImage!=null)90. 91. g2.drawImage(resultImage,resultImage.getWidth()+20,10,resultImage.getWidth(),resultImage.getHeight(),null);92. g2.drawString(最终结果,红色是检测结果,resultImage.getWidth()+40,sourceImage.getHeight()+30);93. 94. 95. 96. 97. ;98. this.getContentPane().setLayout(newBorderLayout();99. this.getContentPane().add(sliderPanel,BorderLayout.NORTH);100. this.getContentPane().add(btnPanel,BorderLayout.SOUTH);101. this.getContentPane().add(imagePanel,BorderLayout.CENTER);102. 103. /setuplistener104. this.lineBtn.addActionListener(this);105. this.circleBtn.addActionListener(this);106. this.numberSlider.addChangeListener(this);107. this.radiusSlider.addChangeListener(this);108. 109. 110. publicstaticvoidmain(Stringargs)111. 112. StringfilePath=System.getProperty(user.home)+/Desktop/+zhigang/hough-test.png
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 司法专业素质考试题及答案
- 2021届贵州省毕节市高三三模语文试题
- 培训岗位专业笔试题目及答案
- 2025至2030中国酯交换脂肪行业项目调研及市场前景预测评估报告
- 2025至2030中国帽子行业项目调研及市场前景预测评估报告
- 酒店集团空调系统统一保养与维修服务协议
- 离婚谈判策略分析-三招击中对方心理软肋合同
- 通信企业客户信息保密及通信服务合同
- 离婚协议书财产分割与子女抚养权确定协议样本
- 离婚纠纷调解协议书及财产分配执行保证书
- 年产62万吨甲醇制烯烃(MTO)项目初步设计说明书
- 联通创新人才认证(解决方案)考试题库(附答案)
- 全成本管理探索与实践
- 电烙铁焊接技术培训
- ICU患者的早期活动
- 出纳课件 转账支票pptx
- TSZUAVIA 009.11-2019 多旋翼无人机系统实验室环境试验方法 第11部分:淋雨试验
- ps6000自动化系统用户操作及问题处理培训
- 商务礼仪情景剧剧本范文(通用5篇)
- 2021年东台市城市建设投资发展集团有限公司校园招聘笔试试题及答案解析
- 某县干部周转宿舍工程可行性研究报告
评论
0/150
提交评论