已阅读5页,还剩5页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Delphi图像处理系列以效率为侧重点,一般代码为PASCAL,核心代码采用BASM。 C+图像处理系列以代码清晰,可读性为主,全部使用C+代码。 尽可能保持二者内容一致,可相互对照。本文代码必须包括文章Delphi图像处理 - 数据类型及公用过程中的ImageData.pas单元。 这是Delphi图像处理 - 中值滤波一文的改进版。亦可参见C+图像处理 - 中值滤波。 中值滤波是图像处理中常用的一种噪声滤波方法。传统的图像中值滤波代码采用排序方法实现,处理速度主要取决于排序算法,但无论什么排序算法,总离不开大量 的元素比较、交换或移动,而这些恰好是当前计算机处理的“弱项”(有经验的程序员都知道,计算机数据处理中,比较、转移、交换和频繁的数据移动比直接的算 术运算和逻辑运算耗时多了),再加上没有一种好的排序算法能同时适应不同滤波半径的数据排序速度,所以在传统中值滤波实现代码中多使用选择排序、冒泡排序 或者直接排序等简单排序算法,高级点的如快速排序法用在中值滤波代码中往往会使处理速度更慢。对于半径为1的中值滤波倒是有一种较好的排序算法,我在Delphi图像处理 - 中值滤波一文中实现过,处理速度还是较快的。 既然排序过程是图像中值滤波处理的瓶颈,能不能抛开它,用其它手段实现呢?这就是本文要探讨的问题。有朋友可能会有疑问,不排序怎么获取中间值呢,是否采用网上有些文章介绍的近似值来代替?不,本文介绍的方法决不是近似中间值,而是的的确确的“精确”中间值。 图像中值滤波中的中间值。在统计学中叫做中位数,是平均数指标的一种。平均数指标按统计的复杂程度可分为简单平均数和加权平均数,所谓简单平均数就是对统 计总体的每个个体进行累计计算后求得;而加权平均数则是先对统计总体的所有个体进行分组,然后以各个组的大小作为权数后进行累计计算所得。中位数既然是平 均数指标的一种,当然也存在两种计算方法。加权中位数和加权算术平均数的区别在于后者是对各个分组用权数相乘进行累积后除以总体个数,而前者只需要对各组 权数进行累积后除以2,累积权数大于或等于这个数的组的值就是中位数。传统中值滤波实现代码中采用的排序手段实质就是简单中位平均数统计方法,而本文要介 绍的是采用分组加权的方法来获取中位平均数,即中值滤波的中间值。 采用分组加权统计方法的前提条件是对无限统计总体进行有限的分组,例如,人口年龄统计,就是首先确定各个年龄段,这个年龄段可以是一岁、五岁、十岁等。而 图像像素的R、G、B值在0 - 255之间,正好符合有限分组的前提条件。说到这里,很多人可能已经明白我要表达的意思了: 1、按R、G、B分别定义一个256大小的灰度统计数据; 2、将图像像素总体的每个个体像素的R、G、B值进行归类; 3、确定累积中间值权数的大小; 4、从数组左端或者右端开始权数累计,累积到大于或等于中间值权数的那个灰度组就是中间值! 从前面几个步骤不难看出,前3个步骤就是图像处理中灰度统计的分类方法,第4个累积步骤与灰度统计累积计算有2个不同点,一是灰度统计累积的是权数*灰 度,而这里只累积灰度;二是灰度统计累积需要全部完成,而中值累积只要达到中间值权数那个组就可以终止。在这4个步骤中,前3个步骤是相当快的(实际上只 是第二个步骤),因为其中既无乘除运算,也没有比较转移,更没有元素交换或移动等动作。而制约数据处理速度的瓶颈就在第4步,因为对每个像素都必须分别按 R、G、B通道对一共768个元素大小的数据进行累积,哪怕是每个通道除了2个加法运算和唯一的一次比较判断外,没有其它运算,也不需要每次都必须累积到 位,但仍然是比较耗时的,不过本文在代码实现过程中,尽可能地作了一些弥补。最后结果同排序方法比起来,可算是相当快捷了,而且滤波半径越大,差距越明 显,几十倍的差距绝不是天方夜谭!就算是同我前面所说的半径为1的改进排序算法比较来,大多数情况下,也略有胜出。delphi view plaincopyprint?1. procedureMedianValue(varDest:TImageData;constSource:TImageData;2. MedianGray,Size,Stride:Integer);3. var4. buffer:array0.767ofInteger;5. redAddr,greenAddr,blueAddr,delta:Integer;6. redOff,greenOff,blueOff:Integer;7. width,height,dstOffset,srcOffset:Integer;8. median,rowOffset,sizeOffset,mOffset:Integer;9. asm10. pushesi11. pushedi12. pushebx13. pushecx14. call_SetCopyRegs15. movwidth,ecx16. movheight,edx17. movdstOffset,ebx18. addeax,419. movsrcOffset,eax20. popecx21. moveax,Size22. movedx,Stride23. movebx,edx24. imuledx,eax25. shleax,226. movsizeOffset,eax/sizeOffset=Size*427. subebx,eax28. movrowOffset,ebx/rowOffset=Stride-Size*429. subedx,430. movmOffset,edx/mOffset=Stride*Size-431. moveax,Size32. mulSize33. inceax34. shreax,135. movmedian,eax/median=(size*size+1)/236. movblueAddr,037. movgreenAddr,256*438. movredAddr,512*439. cmpecx,12840. jb141. movblueOff,256*442. movgreenOff,512*443. movredOff,768*444. movdelta,-445. jmp246. 1:47. movblueOff,-448. movgreenOff,256*4-449. movredOff,512*4-450. movdelta,451. 2:52. leaeax,buffer53. addblueAddr,eax54. addgreenAddr,eax55. addredAddr,eax56. addblueOff,eax57. addgreenOff,eax58. addredOff,eax59. yLoop:60. pushwidth61. /RGB灰度统计缓冲区清零62. pushedi63. movedi,blueAddr64. movecx,76865. xoreax,eax66. repstosd67. popedi68. /对每行第一个像素临近区域(Size*Size)的RGB进行灰度统计69. pushesi70. movecx,Size71. statY:72. pushecx73. movecx,Size74. statX:75. movzxeax,esi.TARGBQuad.Blue76. movzxedx,esi.TARGBQuad.Green77. movzxebx,esi.TARGBQuad.Red78. incdwordptrbuffereax*479. incdwordptrbufferedx*4+256*480. incdwordptrbufferebx*4+512*481. addesi,482. loopstatX83. popecx84. addesi,rowOffset85. loopstatY86. popesi87. jmpsetValue88. xLoop:89. /剔除上个坐标点最左边一列像素的RGB的统计值,90. /追加当前像素最右边一列像素RGB的统计值91. movecx,Size92. movebx,sizeOffset93. addebx,esi94. subLoop:95. movzxeax,esi.TARGBQuad.Blue96. movzxedx,esi.TARGBQuad.Green97. decdwordptrbuffereax*498. decdwordptrbufferedx*4+256*499. movzxeax,esi.TARGBQuad.Red100. movzxedx,ebx.TARGBQuad.Blue101. decdwordptrbuffereax*4+512*4102. incdwordptrbufferedx*4103. movzxeax,ebx.TARGBQuad.Green104. movzxedx,ebx.TARGBQuad.Red105. incdwordptrbuffereax*4+256*4106. incdwordptrbufferedx*4+512*4107. addesi,Stride108. addebx,Stride109. loopsubLoop110. subesi,mOffset111. setValue:112. movedx,median113. movecx,delta114. movebx,blueOff115. xoreax,eax116. blueLoop:117. addebx,ecx118. addeax,ebx119. cmpeax,edx120. jbblueLoop121. subebx,blueAddr122. shrebx,2123. movedi.TARGBQuad.Blue,bl124. movebx,greenOff125. xoreax,eax126. greenLoop:127. addebx,ecx128. addeax,ebx129. cmpeax,edx130. jbgreenLoop131. subebx,greenAddr132. shrebx,2133. movedi.TARGBQuad.Green,bl134. movebx,redOff135. xoreax,eax136. redLoop:137. addebx,ecx138. addeax,ebx139. cmpeax,edx140. jbredLoop141. subebx,redAddr142. shrebx,2143. movedi.TARGBQuad.Red,bl144. addedi,4145. decwidth146. jnzxLoop147. xEnd:148. addesi,srcOffset149. addedi,dstOffset150. popwidth151. decheight152. jnzyLoop153. popebx154. popedi155. popesi156. end;157. 158. functionGetMedianGray(constData:TImageData):Integer;159. var160. buffer:array0.255ofInteger;161. asm162. pushesi163. pushedi164. pushebx165. movesi,eax166. leaedi,buffer167. movecx,256168. xoreax,eax169. repstosd170. movecx,esi.TImageData.Width171. movedx,esi.TImageData.Height172. movebx,esi.TImageData.Stride173. movedi,esi.TImageData.Scan0174. shrecx,3175. shredx,3176. salebx,3177. moveax,ecx178. shleax,3+2179. subebx,eax180. leaesi,buffer181. pushebp182. movebp,edx183. moveax,ecx184. mulebp185. leaeax,eax+eax*2186. shreax,1/MedianValue=data.width*data.height*3/2187. pusheax188. yLoop:189. pushecx190. xLoop:191. movzxeax,edi.TARGBQuad.Blue192. movzxedx,edi.TARGBQuad.Green193. incdwordptresi+eax*4194. incdwordptresi+edx*4195. movzxeax,edi.TARGBQuad.Red196. incdwordptresi+eax*4197. addedi,32198. dececx199. jgxLoop200. popecx201. addedi,ebx202. decebp203. jgyLoop204. popedx205. popebp206. movedi,esi207. addedi,256*4208. movecx,-4209. xoreax,eax210. stat:211. addedi,ecx212. addeax,edi213. cmpeax,edx214. jbstat215. moveax,edi216. subeax,esi217. shreax,2218. popebx219. popedi220. popesi221. end;222. 223. procedureImageMedianValue(varData:TImageData;Radius:Integer);224. var225. exp:TImageData;226. begin227. ifRadius=0thenRadius:=1;228. exp:=_GetExpandData(Data,Radius);229. MedianValue(Data,exp,GetMedianGray(Data),(Radiusshl1)+1,exp.Stride);230. FreeImageData(exp);231. end; 实现代码中,在前面所说的4个步骤基础上作了3点完善: 1、并非对图像的所有像素都按4个步骤进行。除了每行行首像素作了完整的分类统计外,其它像素只是从统计数组中剔除前一像素临近值的最左边一列和追加当前像素临近值的最右边一列,这无疑加快了分类统计速度,而且滤波半径越大,效果越明显。 2、在对图像进行滤波处理前,对整个图像像素总体的1/8样本求了一次中间值权数,其作用是确定像素分类后的累积方向,如果这个总体中间值权数小于 128,从灰度统计数据左边(低端)开始累积,否则则从灰度统计数据右边(高端)开始累积。通过这个总体中间值权数就可以大致确定该图像处理速度的快慢, 如果这个值接近两端,处理速度相对就快些,反之如靠近128附近,处理速度则相应会慢些,同样大小的图片,因这个原因,可能造成成倍的差距,但是最坏的情 况下,对灰度统计数组累积时的平均值也不会超过一半。 3、制作滤波备份源图时按滤波半径对图像边缘作了扩充,这样有利于对图像边缘进行滤波处理。有些人在写中值滤波代码时往往对图像边缘略过不作处理,这在小半径滤波范围内还无所谓,但是对于较大半径的滤波处理后,由于未进行滤波处理的边缘较宽。会使得图像很难看。 正式由于
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 广州文化公园招考合同制人员易考易错模拟试题(共500题)试卷后附参考答案
- 广州市海珠区科学技术协会招考合同制工作人员易考易错模拟试题(共500题)试卷后附参考答案
- 入股菜鸟驿合同范本
- 材料价差调整协议书
- 村小组租用合同范本
- 四川省成都市成华区列五中学2024-2025学年高二上学期10月测试历史试题无答案
- 农村合资盖房协议书
- 根据材料写合同范本
- 代理办证费用协议书
- 案款资金代管协议书
- 2026云南云天化石化有限公司校园招聘9人笔试考试参考试题及答案解析
- 安东尼奥高迪简介
- 六种基本绷带包扎法课件
- (2025年)孕产妇及三病培训前试题附答案
- JJF(津) 155-2025 注册计量师计量专业项目考核规范
- 2025杭州师范大学招聘辅导员7人考试笔试参考题库附答案解析
- 2025中国航天科工二院二十五所秋季校园招聘笔试历年常考点试题专练附带答案详解试卷2套
- 华文慕课《刑法学》总论课后作业答案
- 慢病的防治知识
- 热力设备安装调试方案
- 银行贷款项目尽职调查完整报告模板
评论
0/150
提交评论