模糊阈值.docx
- 文档编号:23264068
- 上传时间:2023-05-15
- 格式:DOCX
- 页数:21
- 大小:161.89KB
模糊阈值.docx
《模糊阈值.docx》由会员分享,可在线阅读,更多相关《模糊阈值.docx(21页珍藏版)》请在冰豆网上搜索。
模糊阈值
模糊阈值分割代码
(1)
根据文章《图像的自适应模糊阈值分割法》,写了个简单的代码:
1./*
2.名称:
BlurCure
3.参数:
lpBmp - 图像数据指针
4. lSrcWidth - 图像宽度
5. lSrcHeight - 图像高度
6. dLineBites - 图像单行数据量
7.说明:
获取模糊阈值分割的模糊曲线dBlurData
8.*/
9.void BlurCurve(LPSTR lpBmp, long lSrcWidth, long lSrcHeight, DWORD dLineBites)
10.{
11. if(lpBmp == NULL)
12. return;
13. int i,j;
14. LPSTR lpSrcPtr = NULL;
15. BYTE btTempValue = 0;
16. int nTistogram[256] = {0};
17. for (i = 0;i < lSrcHeight; ++i)
18. {
19. lpSrcPtr = lpBmp + i * dLineBites;
20. for (j = 0;j 21. { 22. btTempValue = (BYTE)*(lpSrcPtr + j); 23. nTistogram[btTempValue]++; 24. } 25. } 26. int nWinWidth = 20;//搜索的窗宽 27. double dBlurData[256]={0}; 28. double dGetMemship = 0; 29. for (int nGrayPos = 0; nGrayPos < 256; ++nGrayPos) 30. { 31. for (j = 0;j <256; ++j) 32. { 33. dGetMemship = MemshipFunc(j,nGrayPos,nWinWidth); 34. if(dGetMemship > 0.5) 35. dGetMemship = 1 - dGetMemship; 36. if(dGetMemship < 0) 37. dGetMemship = 0; 38. dBlurData[nGrayPos] += nTistogram[j]*dGetMemship; 39. } 40. dBlurData[nGrayPos] *= 2.0/(lSrcHeight*lSrcWidth); 41. } 42.} 43./* 44.隶属度函数: MemshipFunc 45.*/ 46.double MemshipFunc(int nGray,const int& nWinCent,const int& nWinWidth) 47.{ 48. int nLeft = nWinCent-nWinWidth; 49. int nRight = nWinCent+nWinWidth; 50. if(nGray >= 0 && nGray <= nLeft) 51. return 0; 52. else if(nGray > nLeft && nGray <= nWinCent) 53. { 54. double dMem = double(nGray - nLeft)/(2*nWinWidth); 55. return 2*dMem*dMem; 56. } 57. else if(nGray > nWinCent && nGray <= nRight) 58. { 59. double dMem = double(nGray - nLeft)/(2*nWinWidth); 60. return 1-2*dMem*dMem; 61. } 62. return 1; 63.} 原始图像: 直方图: 模糊曲线: 从上图可以看出,经过模糊化后,直方图变的平滑了很多,下一步主要进行曲线最小值的搜索。 另外,模糊缺陷的保值性与窗宽nWinWidth有很大的关系,窗宽取的合适,获得的模糊曲线就更容易分割。 而所谓自适应模糊化分割,就是找到合适的nWinWdith,目前,找合适的nWinWdith有很多方法,大部分都是搜索法,然后按照设定的准则停止(比如文中讲到的极点法、还有区间法等)搜索,最后获得合适的nWinWidth。 我将再后续的工作中,尝试不同的搜索方法,并把代码奉上。 模糊阈值分割 (2) 根据模糊阈值分割的原理,本文在“模糊阈值分割代码 (1)"的基础上进行了拓展,主要是利用图像直方图,搜索最佳波谷阈值,实现多阈值分割。 其过程主要如下: 1.获取图像直方图 2.进行直方图平滑,以去毛刺 3.进行波峰搜索。 这部分比较复杂,需要考虑的问题也多。 包括波峰的判定准则、伪峰值的去除、半峰值的判断等等。 一般来说,一个峰值包括起始位置(上坡段)、终止位置(下坡段)和峰值位置。 本文上、下坡段判断是通过连续增长(下降)的数量来判断的,比如连续超过10个增长的就认为是上坡段,而连续10个下降的就是下坡段。 当然了,有些峰值非常小,这个就需要缩小判定阈值。 峰值的位置是在上下坡段的区间内取重心的方式得到的(见函数GetPeaks)。 4.在波峰之间采用S函数的模糊化(MemshipFunc),获得模糊曲线。 我们知道,模糊化的过程窗口的宽度很重要,一般窗宽取峰值距离的0.3~0.8。 由于上一步把峰值取到了,所以这一步就可以根据峰值间的距离设定窗宽,达到自适应的目的。 5.获得模糊率曲线后,搜索不同峰值间的最小值就可以获得分割阈值。 [cpp] viewplaincopy 1.struct Peack 2.{ 3. int nStat; 4. int nEnd; 5. int nValue; 6. Peack(): nStat(0),nEnd(0),nValue(0) 7. {} 8.}; 9./* 10.名称: BlurCure 11.参数: lpBmp - 图像数据指针 12. lSrcWidth - 图像宽度 13. lSrcHeight - 图像高度 14. dLineBites - 图像单行数据量 15.说明: 获取模糊阈值分割的模糊曲线dBlurData 16.*/ 17.void BlurCurve(LPSTR lpBmp, long lSrcWidth, long lSrcHeight, DWORD dLineBites) 18.{ 19. if(lpBmp == NULL) 20. return; 21. int i,j; 22. LPSTR lpSrcPtr = NULL; 23. BYTE btTempValue = 0; 24. int nTistogram[256] = {0}; 25. for (i = 0;i < lSrcHeight; ++i) 26. { 27. lpSrcPtr = lpBmp + i * dLineBites; 28. for (j = 0;j 29. { 30. btTempValue = (BYTE)*(lpSrcPtr + j); 31. nTistogram[btTempValue]++; 32. } 33. } 34. //-----------------直方图平均----------- 35. int nSum = 0, nMaxTtg = 0; 36. const int c_nScop = 5; 37. int arrValue[c_nScop] = {0}; 38. for (j = 0;j <256; ++j) 39. { 40. nSum += nTistogram[j]; 41. if(j < c_nScop) 42. { 43. arrValue[j] = nTistogram[j]; 44. nTistogram[j] = nSum/(j+1); 45. } 46. else 47. { 48. i = j%c_nScop; 49. nSum -= arrValue[i]; 50. arrValue[i] = nTistogram[j]; 51. nTistogram[j] = nSum/c_nScop; 52. } 53. if(nMaxTtg < nTistogram[j]) 54. nMaxTtg = nTistogram[j]; 55. outFile< 56. }//end 57. //--------------------------------------- vector 58. GetPeaks(nTistogram,nMaxTtg/500,vctPeak); 59. int nNum = vctPeak.size(); 60. if(nNum > 1) 61. { 62. int arrThesh[255] = {0}; 63. int nSetScop = 255/(nNum -1); 64. for (i=0; i 65. { 66. int nWinWidth = int(0.3*(vctPeak[i+1].nValue-vctPeak[i].nValue)); 67. double dGetMemship = 0,dMinData = 0xFFFFFFFF; 68. for (int nGrayPos = vctPeak[i].nValue;nGrayPos <= vctPeak[i+1].nValue; ++nGrayPos) 69. { 70. double dOutData = 0; 71. for (j = 0;j <256; ++j) 72. { 73. dGetMemship = MemshipFunc(j,nGrayPos,nWinWidth); 74. if(dGetMemship > 0.5) 75. dGetMemship = 1 - dGetMemship; 76. if(dGetMemship < 0) 77. dGetMemship = 0;//-dGetMemship; 78. dOutData += nTistogram[j]*dGetMemship; 79. } 80. //dOutData *= 2.0/(lSrcHeight*lSrcWidth); 81. if(dMinData > dOutData) 82. { 83. dMinData = dOutData; 84. arrThesh[i] = nGrayPos; 85. } 86. } 87. } 88. //--------- 89. for (i = 0;i < lSrcHeight; ++i) 90. { 91. lpSrcPtr = lpSrcData + i * dLineBites; 92. lpDstPtr = lpDstData + i * dLineBites; 93. for (j = 0;j 94. { 95. btTempValue = (BYTE)*(lpSrcPtr + j); 96. int k; 97. for ( k=0; k 98. { 99. if(btTempValue < arrThesh[k]) 100. { 101. *(lpDstPtr + j)= (BYTE)(k*nSetScop); 102. break; 103. } 104. } 105. if(k == nNum-1) 106. *(lpDstPtr + j) = 255; 107. } 108. }//END FOR 109. } 110. else if(nNum == 1)//单峰,用峰值左侧点为分割点 111. { 112. for (i = 0;i < lSrcHeight; ++i) 113. { 114. lpSrcPtr = lpSrcData + i * dLineBites; 115. lpDstPtr = lpDstData + i * dLineBites; 116. for (j = 0;j 117. { 118. btTempValue = (BYTE)*(lpSrcPtr + j); 119. if(btTempValue < vctPeak[0].nEnd) 120. *(lpDstPtr + j)= 0; 121. else 122. *(lpDstPtr + j) = 255; 123. } 124. } 125. } 126. else 127. { 128. MessageBox(_T("分割失败"),_T("提示"),MB_ICONWARNING); 129. } [cpp] viewplaincopy 1.} [cpp] viewplaincopy 1./* 2.函数: GetPeaks 3.参数: pTistogram - 图像直方图 4. nLowValue - 谷底最小值 5. vctPeak - 返回的峰值列表 6. 7.说明: 函数主要对处理过的直方图查找谷峰 8.*/ 9.void GetPeaks(const int pTistogram[256], const int nLowValue,vector 10.{ 11. int arrPos[2] = {0}; 12. int nSratMin = 0xFFFFFF,nContinueNum=0; 13. int nPreValue = pTistogram[0]; 14. int nSetThres = 8; 15. for (int i=1; i<256; i++) 16. { 17. if(nSratMin > pTistogram[i]) 18. { 19. nSratMin = pTistogram[i]; 20. if(nSratMin <= nLowValue) 21. nSetThres = 5; 22. } 23. //------------------------------- 24. if(arrPos[0] ! = 0) 25. { 26. if(pTistogram[i] < nPreValue) 27. { 28. nContinueNum ++; 29. if(nContinueNum >= nSetThres) 30. arrPos[1] = i; 31. } 32. else// if(nTistogram[i] > nPreValue) 33. { 34. if(arrPos[1] ! = 0)//data out 35. { 36. Peack pk; 37. pk.nStat = arrPos[0]; 38. pk.nEnd = arrPos[1]; 39. vctPeak.push_back(pk); 40. //-------- 41. arrPos[0] = arrPos[1] =0; 42. nSratMin = 0xFFFFFF; 43. nSetThres = 10; 44. } 45. nContinueNum = 0; 46. } 47. } 48. else 49. { 50. if(pTistogram[i] > nPreValue) 51. { 52. nContinueNum ++; 53. if(nContinueNum >= nSetThres) 54. arrPos[0] = i-nSetThres; 55. } 56. else //if(nTistogram[i] < nPreValue) 57. { 58. static int s_nLowNum = 0; 59. if(pTistogram[i] < nPreValue) 60. { 61. s_nLowNum ++; 62. if(s_nLowNum == i && s_nLowNum > 10) 63. arrPos[0] = 1; 64. } 65. else if(nContinueNum > 2) 66.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 模糊 阈值