Enhance.cpp
上传用户:panpan8800
上传日期:2013-06-29
资源大小:274k
文件大小:26k
源码类别:

图形图像处理

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "cdib.h"
  3. #include "math.h"
  4. #include <direct.h>
  5. #include <complex>
  6. using namespace std;
  7. #include "GlobalApi.h"
  8. /*************************************************************************
  9.  *
  10.  * 函数名称:
  11.  *   HistogramEqualize()
  12.  *
  13.  * 输入参数:
  14.  *   CDib * pDib - 指向CDib类的指针,含有原始图象信息
  15.  *
  16.  * 返回值:
  17.  *   BOOL - 成功则返回TRUE,否则返回FALSE
  18.  *
  19.  * 说明:
  20.  *   该函数对指定的图象进行直方图均衡化处理
  21.  *
  22.  *************************************************************************
  23.  */
  24.  BOOL HistogramEqualize(CDib* pDib)
  25.  {
  26.  // 指向源图像的指针
  27. unsigned char* lpSrc;
  28. // 临时变量
  29. int nTemp;
  30. // 循环变量
  31. int i,j;
  32. // 累积直方图,即灰度映射表
  33. BYTE byMap[256];
  34. // 直方图
  35. int nCount[256];
  36. // 图象的高度和宽度
  37. CSize sizeImage;
  38. sizeImage = pDib->GetDimensions();
  39. // 获得图象数据存储的高度和宽度
  40. CSize SizeSaveImage;
  41. SizeSaveImage = pDib->GetDibSaveDim();
  42. // 重置计数为0
  43. for (i = 0; i < 256; i ++)
  44. {
  45. // 清零
  46. nCount[i] = 0;
  47. }
  48. // 计算各个灰度值的计数,即得到直方图
  49. for (i = 0; i < sizeImage.cy; i ++)
  50. {
  51. for (j = 0; j < sizeImage.cx; j ++)
  52. {
  53. lpSrc = (unsigned char *)pDib->m_lpImage + SizeSaveImage.cx * i + j;
  54. // 计数加1
  55. nCount[*(lpSrc)]++;
  56. }
  57. }
  58. // 计算累积直方图
  59. for (i = 0; i < 256; i++)
  60. {
  61. // 初始为0
  62. nTemp = 0;
  63. for (j = 0; j <= i ; j++)
  64. {
  65. nTemp += nCount[j];
  66. }
  67. // 计算对应的新灰度值
  68. byMap[i] = (BYTE) (nTemp * 255 / sizeImage.cy / sizeImage.cx);
  69. }
  70. // 每行
  71. for(i = 0; i < sizeImage.cy; i++)
  72. {
  73. // 每列
  74. for(j = 0; j < sizeImage.cx; j++)
  75. {
  76. // 指向DIB第i行,第j个象素的指针
  77. lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i,j);
  78. // 计算新的灰度值
  79. *lpSrc = byMap[*lpSrc];
  80. }
  81. }
  82. // 返回
  83. return TRUE;
  84.  }
  85. /*************************************************************************
  86.  *
  87.  * 函数名称:
  88.  *   GraySegLinTrans()
  89.  *
  90.  * 输入参数:
  91.  *   CDib* pDib - 指向CDib类的指针,含有原始图象信息
  92.  *   int   nX1 - 分段线性灰度变换第一个拐点的X坐标
  93.  *   int   nY1 - 分段线性灰度变换第一个拐点的Y坐标
  94.  *   int   nX2 - 分段线性灰度变换第二个拐点的X坐标
  95.  *   int   nY2 - 分段线性灰度变换第二个拐点的Y坐标
  96.  *
  97.  * 返回值:
  98.  *   BOOL               - 成功返回TRUE,否则返回FALSE。
  99.  *
  100.  * 说明:
  101.  *   该函数用来对图像进行分段线性灰度变换,输入参数中包含了两个拐点的坐标
  102.  *
  103.  *************************************************************************
  104.  */
  105. BOOL GraySegLinTrans(CDib* pDib, int nX1, int nY1, int nX2, int nY2)
  106. {
  107. // 指向源图像的指针
  108. unsigned char* lpSrc;
  109. // 循环变量
  110. int i,j;
  111. // 灰度映射表
  112. BYTE byMap[256];
  113. // 图像每行的字节数
  114. //LONG lLineBytes;
  115. // 图象的高度和宽度
  116. CSize sizeImage;
  117. sizeImage = pDib->GetDimensions();
  118. // 获得图象数据存储的高度和宽度
  119. CSize SizeSaveImage;
  120. SizeSaveImage = pDib->GetDibSaveDim();
  121. // 计算图像每行的字节数
  122. //lLineBytes = WIDTHBYTES(sizeImage.cx * 8);
  123. // 计算灰度映射表
  124. for (i = 0; i <= nX1; i++)
  125. {
  126. // 判断nX1是否大于0(防止分母为0)
  127. if (nX1 > 0)
  128. {
  129. // 线性变换
  130. byMap[i] = (BYTE) nY1 * i / nX1;
  131. }
  132. else
  133. {
  134. // 直接赋值为0
  135. byMap[i] = 0;
  136. }
  137. }
  138. for (; i <= nX2; i++)
  139. {
  140. // 判断nX1是否等于nX2(防止分母为0)
  141. if (nX2 != nX1)
  142. {
  143. // 线性变换
  144. byMap[i] = nY1 + (BYTE) ((nY2 - nY1) * (i - nX1) / (nX2 - nX1));
  145. }
  146. else
  147. {
  148. // 直接赋值为nY1
  149. byMap[i] = nY1;
  150. }
  151. }
  152. for (; i < 256; i++)
  153. {
  154. // 判断nX2是否等于255(防止分母为0)
  155. if (nX2 != 255)
  156. {
  157. // 线性变换
  158. byMap[i] = nY2 + (BYTE) ((255 - nY2) * (i - nX2) / (255 - nX2));
  159. }
  160. else
  161. {
  162. // 直接赋值为255
  163. byMap[i] = 255;
  164. }
  165. }
  166. // 对图象的象素值进行变换
  167. // 每行
  168. for(i = 0; i < sizeImage.cy; i++)
  169. {
  170. // 每列
  171. for(j = 0; j < sizeImage.cx; j++)
  172. {
  173. // 指向DIB第i行,第j个象素的指针
  174. lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i,j);
  175. // 计算新的灰度值
  176. *lpSrc = byMap[*lpSrc];
  177. }
  178. }
  179. // 返回
  180. return TRUE;
  181. }
  182. /*************************************************************************
  183.  *
  184.  * 函数名称:
  185.  *   GeneralTemplate()
  186.  *
  187.  * 输入参数:
  188.  *   CDib * pDib - 指向CDib类的指针,含有原始图象信息
  189.  *   int nTempWidth - 模板的宽度
  190.  *   int nTempHeight - 模板的高度
  191.  *   int nTempCenX - 模板中心的X坐标(相对于模板)
  192.  *   int nTempCenY - 模板中心的Y坐标(相对于模板)
  193.  *   double* pdbTemp - 模板数组的指针
  194.  *   double* dbCoef - 模板的系数
  195.  *
  196.  * 返回值:
  197.  *   BOOL - 成功则返回TRUE,否则返回FALSE
  198.  *
  199.  * 说明:
  200.  *   该函数用指定的模板对pDib指向的图象进行模板操作。模板的定义了宽度,高度,
  201.  *    中心坐标和系数,模板的数据存放在pdbTemp中。对图象进行模板操作后,仍
  202.  *    然存放在pDib指向的CDib对象中。需要注意的是,该函数只能处理8位的图象,
  203.  *   否则,指向的数据将出错。
  204.  *
  205.  *************************************************************************
  206.  */
  207. BOOL  GeneralTemplate(CDib* pDib,  int nTempWidth, int nTempHeight, 
  208.  int nTempCenX, int nTempCenY,
  209.  double* pdbTemp, double dbCoef)
  210. {
  211. // 临时存放图像数据的指针
  212. LPBYTE lpImage;
  213. // 循环变量
  214. int i,j,k,l;
  215. // 指向源图像的指针
  216. unsigned char* lpSrc;
  217. // 指向要复制区域的指针
  218. unsigned char* lpDst;
  219. // 计算结果
  220. double dbResult;
  221. // 图象的高度和宽度
  222. CSize sizeImage;
  223. sizeImage = pDib->GetDimensions();
  224. // 获得图象数据存储的尺寸
  225. int nSizeImage;
  226. nSizeImage = pDib->GetSizeImage();
  227. // 给临时存放数据分配内存
  228. lpImage = (LPBYTE) new char[nSizeImage];
  229. // 判断是否内存分配失败
  230. if (lpImage == NULL)
  231. {
  232. // 分配内存失败
  233. return FALSE;
  234. }
  235. // 将原始图像的数据拷贝到临时存放内存中
  236. memcpy(lpImage, pDib->m_lpImage, nSizeImage);
  237. // 进行模板操作
  238. // 行(除去边缘几行)
  239. for(i = nTempCenY ; i < sizeImage.cy - nTempHeight + nTempCenY + 1; i++)
  240. {
  241. // 列(除去边缘几列)
  242. for(j = nTempCenX; j < sizeImage.cx - nTempWidth + nTempCenX + 1; j++)
  243. {
  244. // 指向新DIB第i行,第j个象素的指针
  245. lpDst = (unsigned char*)lpImage + pDib->GetPixelOffset(i,j);
  246. dbResult = 0;
  247. // 计算
  248. for (k = 0; k < nTempHeight; k++)
  249. {
  250. for (l = 0; l < nTempWidth; l++)
  251. {
  252. // 指向DIB第i - nTempCenY + k行,第j - nTempCenX + l个象素的指针
  253. lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i-nTempCenY+k, j-nTempCenX+l);
  254. // 保存象素值
  255. dbResult += (* lpSrc) * pdbTemp[k * nTempWidth + l];
  256. }
  257. }
  258. // 乘上系数
  259. dbResult *= dbCoef;
  260. // 取绝对值
  261. dbResult = (double ) fabs(dbResult);
  262. // 判断是否超过255
  263. if(dbResult > 255)
  264. {
  265. // 直接赋值为255
  266. * lpDst = 255;
  267. }
  268. else
  269. {
  270. // 赋值
  271. * lpDst = (unsigned char) (dbResult + 0.5);
  272. }
  273. }
  274. }
  275. // 复制变换后的图像
  276. memcpy(pDib->m_lpImage, lpImage, nSizeImage);
  277. // 释放内存
  278. delete[]lpImage;
  279. // 返回
  280. return TRUE;
  281. }
  282. /*************************************************************************
  283.  *
  284.  * 函数名称:
  285.  *   MedianFilter()
  286.  *
  287.  * 输入参数:
  288.  *   CDib * pDib - 指向CDib类的指针,含有原始图象信息
  289.  *   int nTempWidth - 模板的宽度
  290.  *   int nTempHeight - 模板的高度
  291.  *   int nTempCenX - 模板中心的X坐标(相对于模板)
  292.  *   int nTempCenY - 模板中心的Y坐标(相对于模板)
  293.  *
  294.  * 返回值:
  295.  *   BOOL - 成功则返回TRUE,否则返回FALSE
  296.  *
  297.  * 说明:
  298.  *   该函数对指定的DIB图像进行中值滤波。
  299.  *
  300.  ************************************************************************/
  301. BOOL MedianFilter(CDib* pDib,  int nTempWidth, int nTempHeight, 
  302.  int nTempCenX, int nTempCenY)
  303. {
  304. // 临时存放图像数据的指针
  305. LPBYTE lpImage;
  306. // 循环变量
  307. int i,j,k,l;
  308. // 指向源图像的指针
  309. unsigned char* lpSrc;
  310. // 指向要复制区域的指针
  311. unsigned char* lpDst;
  312. // 图象的高度和宽度
  313. CSize sizeImage;
  314. sizeImage = pDib->GetDimensions();
  315. // 获得图象数据存储的尺寸
  316. int nSizeImage;
  317. nSizeImage = pDib->GetSizeImage();
  318. // 指向滤波器数组的指针
  319. unsigned char* pUnchFltValue;
  320. // 给临时存放数据分配内存
  321. lpImage = (LPBYTE) new char[nSizeImage];
  322. // 判断是否内存分配失败
  323. if (lpImage == NULL)
  324. {
  325. // 返回
  326. return FALSE;
  327. }
  328. // 将原始图像的数据拷贝到临时存放内存中
  329. memcpy(lpImage, pDib->m_lpImage, nSizeImage);
  330. // 暂时分配内存,以保存滤波器数组
  331. pUnchFltValue = new unsigned char[nTempHeight * nTempWidth];
  332. // 判断是否内存分配失败
  333. if (pUnchFltValue == NULL)
  334. {
  335. // 释放已分配内存
  336. delete[]lpImage;
  337. // 返回
  338. return FALSE;
  339. }
  340. // 开始中值滤波
  341. // 行(除去边缘几行)
  342. for(i = nTempCenY; i < sizeImage.cy - nTempHeight + nTempCenY + 1; i++)
  343. {
  344. // 列(除去边缘几列)
  345. for(j = nTempCenX; j < sizeImage.cx - nTempWidth + nTempCenX + 1; j++)
  346. {
  347. // 指向新DIB第i行,第j个象素的指针
  348. lpDst = (unsigned char*)lpImage + pDib->GetPixelOffset(i,j);
  349. //lpDst = (unsigned char*)lpImage + sizeImage.cx * (sizeImage.cy - 1 - i) + j;
  350. // 读取滤波器数组
  351. for (k = 0; k < nTempHeight; k++)
  352. {
  353. for (l = 0; l < nTempWidth; l++)
  354. {
  355. // 指向DIB第i - nTempCenY + k行,第j - nTempCenX + l个象素的指针
  356. lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i-nTempCenY+k, j-nTempCenX+l);
  357. //lpSrc = (unsigned char*)pDib->m_lpImage + sizeImage.cx * (sizeImage.cy - 1 - i + nTempCenY - k) + j - nTempCenX + l;
  358. // 保存象素值
  359. pUnchFltValue[k * nTempWidth + l] = *lpSrc;
  360. }
  361. }
  362. // 获取中值
  363. //* lpDst = GetMedianValue(pUnchFltValue, nTempHeight * nTempWidth);
  364. }
  365. }
  366. // 复制变换后的图像
  367. memcpy(pDib->m_lpImage, lpImage, nSizeImage);
  368. // 释放内存
  369. delete[]lpImage;
  370. delete[]pUnchFltValue;
  371. // 返回
  372. return TRUE;
  373. }
  374. /*************************************************************************
  375.  *
  376.  * 函数名称:
  377.  *   GetMedianValue()
  378.  *
  379.  * 参数:
  380.  *   unsigned char * pUnchFltValue - 指向要获取中值的数组指针
  381.  *   int   iFilterLen - 数组长度
  382.  *
  383.  * 返回值:
  384.  *   unsigned char - 返回指定数组的中值。
  385.  *
  386.  * 说明:
  387.  *   该函数用冒泡法对一维数组进行排序,并返回数组元素的中值。
  388.  *
  389.  ************************************************************************/
  390. unsigned char  GetMedianValue(unsigned char * pUnchFltValue, int iFilterLen)
  391. {
  392. // 循环变量
  393. int i;
  394. int j;
  395. // 中间变量
  396. unsigned char bTemp;
  397. // 用冒泡法对数组进行排序
  398. for (j = 0; j < iFilterLen - 1; j ++)
  399. {
  400. for (i = 0; i < iFilterLen - j - 1; i ++)
  401. {
  402. if (pUnchFltValue[i] > pUnchFltValue[i + 1])
  403. {
  404. // 互换
  405. bTemp = pUnchFltValue[i];
  406. pUnchFltValue[i] = pUnchFltValue[i + 1];
  407. pUnchFltValue[i + 1] = bTemp;
  408. }
  409. }
  410. }
  411. // 计算中值
  412. if ((iFilterLen & 1) > 0)
  413. {
  414. // 数组有奇数个元素,返回中间一个元素
  415. bTemp = pUnchFltValue[(iFilterLen + 1) / 2];
  416. }
  417. else
  418. {
  419. // 数组有偶数个元素,返回中间两个元素平均值
  420. bTemp = (pUnchFltValue[iFilterLen / 2] + pUnchFltValue[iFilterLen / 2 + 1]) / 2;
  421. }
  422. // 返回中值
  423. return bTemp;
  424. }
  425. /*************************************************************************
  426.  *
  427.  * 函数名称:
  428.  *   LinearSharpen()
  429.  *
  430.  * 输入参数:
  431.  *   LPBYTE lpImage - 指向图象数据得指针
  432.  *   int nWidth - 图象数据宽度
  433.  *   int nHeight - 图象数据高度
  434.  *
  435.  * 返回值:
  436.  *   无
  437.  *
  438.  * 说明:
  439.  *   线性锐化图象增强
  440.  *   本函数采用拉普拉斯算子对图象进行线性锐化
  441.  *   在原来图象上加上拉普拉斯算子锐化的信息
  442.  *
  443.  *************************************************************************
  444.  */
  445. void LinearSharpen (LPBYTE lpImage, int nWidth, int nHeight)
  446. {
  447. // 遍历图象的纵坐标
  448. int y;
  449. // 遍历图象的横坐标
  450. int x;
  451. double * pdGrad ;
  452. pdGrad = new double[nWidth*nHeight];
  453. // 初始化为0
  454. memset(pdGrad, 0, nWidth*nHeight*sizeof(double)) ;
  455. // 设置模板系数
  456. static int nWeight[3][3] ;
  457. nWeight[0][0] = -1 ;   
  458. nWeight[0][1] = -1 ;   
  459. nWeight[0][2] = -1 ;   
  460. nWeight[1][0] = -1 ;   
  461. nWeight[1][1] =  8 ;   
  462. nWeight[1][2] = -1 ;   
  463. nWeight[2][0] = -1 ;   
  464. nWeight[2][1] = -1 ;   
  465. nWeight[2][2] = -1 ;   
  466. //这个变量用来表示Laplacian算子象素值
  467. int nTmp[3][3];
  468. // 临时变量
  469. double dGrad;
  470. // 模板循环控制变量
  471. int yy ;
  472. int xx ;
  473. for(y=1; y<nHeight-1 ; y++ )
  474.  for(x=1 ; x<nWidth-1 ; x++ )
  475.  {
  476.  dGrad = 0 ; 
  477.  // Laplacian算子需要的各点象素值
  478.  
  479.  // 模板第一行
  480.  nTmp[0][0] = lpImage[(y-1)*nWidth + x - 1 ] ; 
  481.  nTmp[0][1] = lpImage[(y-1)*nWidth + x     ] ; 
  482.  nTmp[0][2] = lpImage[(y-1)*nWidth + x + 1 ] ; 
  483.  
  484.  // 模板第二行
  485.  nTmp[1][0] = lpImage[y*nWidth + x - 1 ] ; 
  486.  nTmp[1][1] = lpImage[y*nWidth + x     ] ; 
  487.  nTmp[1][2] = lpImage[y*nWidth + x + 1 ] ; 
  488.  
  489.  // 模板第三行
  490.  nTmp[2][0] = lpImage[(y+1)*nWidth + x - 1 ] ; 
  491.  nTmp[2][1] = lpImage[(y+1)*nWidth + x     ] ; 
  492.  nTmp[2][2] = lpImage[(y+1)*nWidth + x + 1 ] ; 
  493.  
  494.  // 计算梯度
  495.  for(yy=0; yy<3; yy++)
  496.  for(xx=0; xx<3; xx++)
  497.  {
  498.  dGrad += nTmp[yy][xx] * nWeight[yy][xx] ;
  499.  }
  500.  
  501.  // 梯度值写入内存
  502.  *(pdGrad+y*nWidth+x)=dGrad;
  503.  }
  504. for(y=0; y<nHeight ; y++ )
  505. {
  506. for(x=0 ; x<nWidth ; x++ )
  507. {
  508. lpImage[y*nWidth+x] = (unsigned char)max(0,min(255,(lpImage[y*nWidth+x] + (int)pdGrad[y*nWidth+x]) ));
  509. }
  510. }
  511.   delete []pdGrad ;
  512. pdGrad = NULL   ;
  513. }
  514. /*************************************************************************
  515.  *
  516.  * 函数名称:
  517.  *   ReplaceDIBColorTable()
  518.  *
  519.  * 参数:
  520.  *   CDib * pDib - 指向CDib类的指针,含有原始图象信息
  521.  *   LPBYTE pColorsTable - 伪彩色编码表
  522.  *
  523.  * 返回值:
  524.  *   BOOL - 成功返回TRUE,否则返回FALSE。
  525.  *
  526.  * 说明:
  527.  *   该函数用指定的伪彩色编码表来替换指定的DIB图像的颜色表,参数pColorsTable
  528.  *   指向要替换的伪彩色编码表。
  529.  *
  530.  ************************************************************************/
  531. BOOL  ReplaceDIBColorTable(CDib* pDib, LPBYTE  pColorsTable)
  532. {
  533. // 循环变量
  534. int i;
  535. // 颜色表的表项数
  536. int nColorEntries;
  537. // 临时变量
  538. LPRGBQUAD pDibQuad;
  539. // 指向DIB的颜色表
  540. pDibQuad = (LPRGBQUAD) pDib->m_lpvColorTable;
  541. // 获取DIB中颜色表中的表项数
  542. nColorEntries = pDib->m_nColorTableEntries;
  543. // 判断颜色数目是否是256色
  544. if (nColorEntries == 256)
  545. {
  546. // 读取伪彩色编码,更新DIB颜色表
  547. for (i = 0; i < nColorEntries; i++)
  548. {
  549. // 更新DIB调色板红色分量
  550. pDibQuad->rgbRed = pColorsTable[i * 4];
  551. // 更新DIB调色板绿色分量
  552. pDibQuad->rgbGreen = pColorsTable[i * 4 + 1];
  553. // 更新DIB调色板蓝色分量
  554. pDibQuad->rgbBlue = pColorsTable[i * 4 + 2];
  555. // 更新DIB调色板保留位
  556. pDibQuad->rgbReserved = 0;
  557. pDibQuad++;
  558. }
  559. }
  560. // 如果不是256色的DIB,则不进行处理
  561. else
  562. return FALSE;
  563. // 返回
  564. return TRUE;
  565. }
  566. /*************************************************************************
  567.  *
  568.  * 函数名称:
  569.  *   LowPassFilterEnhance()
  570.  *
  571.  * 输入参数:
  572.  *   LPBYTE lpImage - 指向需要增强得图象数据
  573.  *   int nWidth - 数据宽度
  574.  *   int nHeight - 数据高度
  575.  *   int nRadius            - 低通滤波的滤波半径
  576.  *
  577.  * 返回值:
  578.  *   无
  579.  *
  580.  * 说明:
  581.  *   lpImage 是指向需要增强的数据指针。注意,这个指针指向的数据区不能是CDib指向的数据区
  582.  *  因为CDib指向的数据区的每一行是DWORD对齐的。
  583.  *   经过低通滤波的数据存储在lpImage当中。
  584.  *
  585.  *************************************************************************
  586.  */
  587. void LowPassFilterEnhance(LPBYTE lpImage, int nWidth, int nHeight, int nRadius)
  588. {
  589. // 循环控制变量
  590. int y ;
  591. int x ;
  592. double dTmpOne ;
  593. double dTmpTwo ;
  594. // 傅立叶变换的宽度和高度(2的整数次幂)
  595. int nTransWidth ;
  596. int nTransHeight;
  597. // 图象象素值
  598. unsigned char unchValue;
  599. // 指向时域数据的指针
  600. complex<double> * pCTData ;
  601. // 指向频域数据的指针
  602. complex<double> * pCFData ;
  603. // 计算进行傅立叶变换的点数 (2的整数次幂)
  604. dTmpOne = log(nWidth)/log(2);
  605. dTmpTwo = ceil(dTmpOne)    ;
  606. dTmpTwo = pow(2,dTmpTwo)    ;
  607. nTransWidth = (int) dTmpTwo    ;
  608. // 计算进行傅立叶变换的点数 (2的整数次幂)
  609. dTmpOne = log(nHeight)/log(2);
  610. dTmpTwo = ceil(dTmpOne)    ;
  611. dTmpTwo = pow(2,dTmpTwo)    ;
  612. nTransHeight = (int) dTmpTwo   ;
  613. // 傅立叶变换的实部和虚部
  614. double dReal;
  615. double dImag;
  616. // 低通滤波的半径不能超过频域的最大半径
  617. if(nRadius>nTransWidth-1 || nRadius>nTransHeight-1)
  618. {
  619. return ;
  620. }
  621. // 分配内存
  622. pCTData=new complex<double>[nTransWidth * nTransHeight];
  623. pCFData=new complex<double>[nTransWidth * nTransHeight];
  624. // 初始化
  625. // 图像数据的宽和高不一定是2的整数次幂,所以pCTData
  626. // 有一部分数据需要补0
  627. for(y=0; y<nTransHeight; y++)
  628. {
  629. for(x=0; x<nTransWidth; x++)
  630. {
  631. pCTData[y*nTransWidth + x]=complex<double>(0,0);
  632. }
  633. }
  634. // 把图像数据传给pCTData
  635. for(y=0; y<nHeight; y++)
  636. {
  637. for(x=0; x<nWidth; x++)
  638. {
  639. unchValue = lpImage[y*nWidth +x];
  640. pCTData[y*nTransWidth + x]=complex<double>(unchValue,0);
  641. }
  642. }
  643. // 傅立叶正变换
  644. DIBFFT_2D(pCTData, nWidth, nHeight, pCFData) ;
  645. // 下面开始实施低通滤波,把所有大于nRadius的高频分量设置为0
  646. //  注意这里高频分量采用的范数不是欧式距离,而是无穷大范数
  647. //  || (u,v)-(0,0) || = max(|u|,|v|) 
  648. for(y=nRadius; y<nTransHeight; y++)
  649. {
  650. for(x=nRadius; x<nTransWidth; x++)
  651. {
  652. pCFData[y*nTransWidth + x]=complex<double>(0,0);
  653. }
  654. }
  655. // 经过低通滤波的图象进行反变换
  656. IFFT_2D(pCFData, pCTData, nWidth, nHeight);
  657. // 反变换的数据传给lpImage
  658. for(y=0; y<nHeight; y++)
  659. {
  660. for(x=0; x<nWidth; x++)
  661. {
  662. dReal = pCTData[y*nTransWidth + x].real() ;
  663. dImag = pCTData[y*nTransWidth + x].imag() ;
  664. unchValue = (unsigned char)max(0,min(255,sqrt(dReal*dReal+dImag*dImag) ));
  665. lpImage[y*nWidth + x] = unchValue ;
  666. }
  667. }
  668. // 释放内存
  669. delete pCTData;
  670. delete pCFData;
  671. pCTData = NULL;
  672. pCFData = NULL;
  673. }
  674. /*************************************************************************
  675.  *
  676.  * 函数名称:
  677.  *   HighPassFilterEnhance()
  678.  *
  679.  * 输入参数:
  680.  *   LPBYTE lpImage - 指向需要增强得图象数据
  681.  *   int nWidth - 数据宽度
  682.  *   int nHeight - 数据高度
  683.  *   int nRadius            - 高通滤波的滤波半径
  684.  *
  685.  * 返回值:
  686.  *   无
  687.  *
  688.  * 说明:
  689.  *   lpImage 是指向需要增强的数据指针。注意,这个指针指向的数据区不能是CDib指向的数据区
  690.  *  因为CDib指向的数据区的每一行是DWORD对齐的。
  691.  *   经过高通滤波的数据存储在lpImage当中。
  692.  *
  693.  *************************************************************************
  694.  */
  695. void HighPassFilterEnhance(LPBYTE lpImage, int nWidth, int nHeight, int nRadius)
  696. {
  697. // 循环控制变量
  698. int y ;
  699. int x ;
  700. double dTmpOne ;
  701. double dTmpTwo ;
  702. // 傅立叶变换的宽度和高度(2的整数次幂)
  703. int nTransWidth ;
  704. int nTransHeight;
  705. // 图象象素值
  706. unsigned char unchValue;
  707. // 指向时域数据的指针
  708. complex<double> * pCTData ;
  709. // 指向频域数据的指针
  710. complex<double> * pCFData ;
  711. double dReal;
  712. double dImag;
  713. // 计算进行傅立叶变换的点数 (2的整数次幂)
  714. dTmpOne = log(nWidth)/log(2);
  715. dTmpTwo = ceil(dTmpOne)    ;
  716. dTmpTwo = pow(2,dTmpTwo)    ;
  717. nTransWidth = (int) dTmpTwo    ;
  718. // 计算进行傅立叶变换的点数 (2的整数次幂)
  719. dTmpOne = log(nHeight)/log(2);
  720. dTmpTwo = ceil(dTmpOne)    ;
  721. dTmpTwo = pow(2,dTmpTwo)    ;
  722. nTransHeight = (int) dTmpTwo   ;
  723. // 滤波的半径不能超过频域的最大半径
  724. if(nRadius>nTransWidth-1 || nRadius>nTransHeight-1)
  725. {
  726. return ;
  727. }
  728. // 分配内存
  729. pCTData=new complex<double>[nTransWidth * nTransHeight];
  730. pCFData=new complex<double>[nTransWidth * nTransHeight];
  731. // 初始化
  732. // 图像数据的宽和高不一定是2的整数次幂,所以pCTData
  733. // 有一部分数据需要补0
  734. for(y=0; y<nTransHeight; y++)
  735. {
  736. for(x=0; x<nTransWidth; x++)
  737. {
  738. pCTData[y*nTransWidth + x]=complex<double>(0,0);
  739. }
  740. }
  741. // 把图像数据传给pCTData
  742. for(y=0; y<nHeight; y++)
  743. {
  744. for(x=0; x<nWidth; x++)
  745. {
  746. unchValue = lpImage[y*nWidth +x];
  747. pCTData[y*nTransWidth + x]=complex<double>(unchValue,0);
  748. }
  749. }
  750. // 傅立叶正变换
  751. DIBFFT_2D(pCTData, nWidth, nHeight, pCFData) ;
  752. // 下面开始滤波,把所有小于nRadius的低频分量设置为0
  753. // 采用的范数不是欧式距离,而是无穷大范数
  754. //  || (u,v)-(0,0) || = max(|u|,|v|) 
  755. for(y=0; y<nRadius; y++)
  756. {
  757. for(x=0; x<nRadius; x++)
  758. {
  759. pCFData[y*nTransWidth + x]=complex<double>(0,0);
  760. }
  761. }
  762. // 经过滤波的图象进行反变换
  763. IFFT_2D(pCFData, pCTData, nWidth, nHeight);
  764. // 反变换的数据传给lpImage
  765. for(y=0; y<nHeight; y++)
  766. {
  767. for(x=0; x<nWidth; x++)
  768. {
  769.   // 因为高通滤波器会把低频成分去掉,所以图象看起来会比较暗,为了解决这个问题
  770. // 在经过增强后的图象加上一个常数,使图象变得亮起来。严格来讲这种处理相当于
  771. // 增加了一些低频分量(在频率(0,0))。不过如果不加一个常数,高通效果在观看
  772. // 上就不是很方便。
  773. dReal = pCTData[y*nTransWidth + x].real() ;
  774. dImag = pCTData[y*nTransWidth + x].imag() ;
  775. unchValue = (unsigned char)max(0,min(255,(sqrt(dReal*dReal+dImag*dImag)+100 )));
  776. lpImage[y*nWidth + x] = unchValue ;
  777. }
  778. }
  779. // 释放内存
  780. delete pCTData;
  781. delete pCFData;
  782. pCTData = NULL;
  783. pCFData = NULL;
  784. }
  785. /*************************************************************************
  786.  *
  787.  * 函数名称:
  788.  *   ButterWorthLowPass()
  789.  *
  790.  * 输入参数:
  791.  *   LPBYTE lpImage - 指向需要增强得图象数据
  792.  *   int nWidth - 数据宽度
  793.  *   int nHeight - 数据高度
  794.  *   int nRadius            - ButterWorth低通滤波的“半功率”点
  795.  *
  796.  * 返回值:
  797.  *   无
  798.  *
  799.  * 说明:
  800.  *   lpImage 是指向需要增强的数据指针。注意,这个指针指向的数据区不能是CDib指向的数据区
  801.  *  因为CDib指向的数据区的每一行是DWORD对齐的。
  802.  *   经过ButterWorth低通滤波的数据存储在lpImage当中。
  803.  *
  804.  *************************************************************************
  805.  */
  806. void ButterWorthLowPass(LPBYTE lpImage, int nWidth, int nHeight, int nRadius)
  807. {
  808. // 循环控制变量
  809. int y ;
  810. int x ;
  811. double dTmpOne ;
  812. double dTmpTwo ;
  813. // ButterWorth 滤波系数
  814. double H       ;
  815. // 傅立叶变换的宽度和高度(2的整数次幂)
  816. int nTransWidth ;
  817. int nTransHeight;
  818. double dReal    ;
  819. double dImag    ;
  820. // 图象象素值
  821. unsigned char unchValue;
  822. // 指向时域数据的指针
  823. complex<double> * pCTData ;
  824. // 指向频域数据的指针
  825. complex<double> * pCFData ;
  826. // 计算进行傅立叶变换的点数 (2的整数次幂)
  827. dTmpOne = log(nWidth)/log(2);
  828. dTmpTwo = ceil(dTmpOne)    ;
  829. dTmpTwo = pow(2,dTmpTwo)    ;
  830. nTransWidth = (int) dTmpTwo    ;
  831. // 计算进行傅立叶变换的点数 (2的整数次幂)
  832. dTmpOne = log(nHeight)/log(2);
  833. dTmpTwo = ceil(dTmpOne)    ;
  834. dTmpTwo = pow(2,dTmpTwo)    ;
  835. nTransHeight = (int) dTmpTwo   ;
  836. // 分配内存
  837. pCTData=new complex<double>[nTransWidth * nTransHeight];
  838. pCFData=new complex<double>[nTransWidth * nTransHeight];
  839. // 初始化
  840. // 图像数据的宽和高不一定是2的整数次幂,所以pCTData
  841. // 有一部分数据需要补0
  842. for(y=0; y<nTransHeight; y++)
  843. {
  844. for(x=0; x<nTransWidth; x++)
  845. {
  846. pCTData[y*nTransWidth + x]=complex<double>(0,0);
  847. }
  848. }
  849. // 把图像数据传给pCTData
  850. for(y=0; y<nHeight; y++)
  851. {
  852. for(x=0; x<nWidth; x++)
  853. {
  854. unchValue = lpImage[y*nWidth +x];
  855. pCTData[y*nTransWidth + x]=complex<double>(unchValue,0);
  856. }
  857. }
  858. // 傅立叶正变换
  859. DIBFFT_2D(pCTData, nWidth, nHeight, pCFData) ;
  860. // 下面开始实施ButterWorth低通滤波
  861. for(y=0; y<nTransHeight; y++)
  862. {
  863. for(x=0; x<nTransWidth; x++)
  864. {
  865. H = (double)(y*y+x*x) ; 
  866. H = H / (nRadius * nRadius); 
  867. H = 1/(1+H)            ;
  868. pCFData[y*nTransWidth + x]=complex<double>(pCFData[y*nTransWidth + x].real()*H,
  869.  pCFData[y*nTransWidth + x].imag()*H);
  870. }
  871. }
  872. // 经过ButterWorth低通滤波的图象进行反变换
  873. IFFT_2D(pCFData, pCTData, nWidth, nHeight);
  874. // 反变换的数据传给lpImage
  875. for(y=0; y<nHeight; y++)
  876. {
  877. for(x=0; x<nWidth; x++)
  878. {
  879. dReal = pCTData[y*nTransWidth + x].real() ;
  880. dImag = pCTData[y*nTransWidth + x].imag() ;
  881. unchValue = (unsigned char)max(0,min(255,sqrt(dReal*dReal+dImag*dImag) ));
  882. lpImage[y*nWidth + x] = unchValue ;
  883. }
  884. }
  885. // 释放内存
  886. delete pCTData;
  887. delete pCFData;
  888. pCTData = NULL;
  889. pCFData = NULL;
  890. }
  891. /*************************************************************************
  892.  *
  893.  * 函数名称:
  894.  *   ButterWorthHighPass()
  895.  *
  896.  * 输入参数:
  897.  *   LPBYTE lpImage - 指向需要增强得图象数据
  898.  *   int nWidth - 数据宽度
  899.  *   int nHeight - 数据高度
  900.  *   int nRadius            - ButterWorth高通滤波的“半功率”点
  901.  *
  902.  * 返回值:
  903.  *   无
  904.  *
  905.  * 说明:
  906.  *   lpImage 是指向需要增强的数据指针。注意,这个指针指向的数据区不能是
  907.  *  CDib指向的数据区, 因为CDib指向的数据区的每一行是DWORD对齐的。
  908.  *   经过ButterWorth高通滤波的数据存储在lpImage当中。
  909.  *
  910.  *************************************************************************
  911.  */
  912. void ButterWorthHighPass(LPBYTE lpImage, int nWidth, int nHeight, int nRadius)
  913. {
  914. // 循环控制变量
  915. int y ;
  916. int x ;
  917. double dTmpOne ;
  918. double dTmpTwo ;
  919. // ButterWorth 滤波系数
  920. double H       ;
  921. // 傅立叶变换的宽度和高度(2的整数次幂)
  922. int nTransWidth ;
  923. int nTransHeight;
  924. double dReal    ;
  925. double dImag    ;
  926. // 图象象素值
  927. unsigned char unchValue;
  928. // 指向时域数据的指针
  929. complex<double> * pCTData ;
  930. // 指向频域数据的指针
  931. complex<double> * pCFData ;
  932. // 计算进行傅立叶变换的点数 (2的整数次幂)
  933. dTmpOne = log(nWidth)/log(2);
  934. dTmpTwo = ceil(dTmpOne)    ;
  935. dTmpTwo = pow(2,dTmpTwo)    ;
  936. nTransWidth = (int) dTmpTwo    ;
  937. // 计算进行傅立叶变换的点数 (2的整数次幂)
  938. dTmpOne = log(nHeight)/log(2);
  939. dTmpTwo = ceil(dTmpOne)    ;
  940. dTmpTwo = pow(2,dTmpTwo)    ;
  941. nTransHeight = (int) dTmpTwo   ;
  942. // 分配内存
  943. pCTData=new complex<double>[nTransWidth * nTransHeight];
  944. pCFData=new complex<double>[nTransWidth * nTransHeight];
  945. // 初始化
  946. // 图像数据的宽和高不一定是2的整数次幂,所以pCTData
  947. // 有一部分数据需要补0
  948. for(y=0; y<nTransHeight; y++)
  949. {
  950. for(x=0; x<nTransWidth; x++)
  951. {
  952. pCTData[y*nTransWidth + x]=complex<double>(0,0);
  953. }
  954. }
  955. // 把图像数据传给pCTData
  956. for(y=0; y<nHeight; y++)
  957. {
  958. for(x=0; x<nWidth; x++)
  959. {
  960. unchValue = lpImage[y*nWidth +x];
  961. pCTData[y*nTransWidth + x]=complex<double>(unchValue,0);
  962. }
  963. }
  964. // 傅立叶正变换
  965. DIBFFT_2D(pCTData, nWidth, nHeight, pCFData) ;
  966. // 下面开始实施ButterWorth高通滤波
  967. for(y=0; y<nTransHeight; y++)
  968. {
  969. for(x=0; x<nTransWidth; x++)
  970. {
  971. H = (double)(y*y+x*x) ; 
  972. H = (nRadius * nRadius) / H ; 
  973. H = 1/(1+H)            ;
  974. pCFData[y*nTransWidth + x]=complex<double>(H*(pCFData[y*nTransWidth + x].real()),
  975.  H*(pCFData[y*nTransWidth + x].imag())  );
  976. }
  977. }
  978. // 经过ButterWorth高通滤波的图象进行反变换
  979. IFFT_2D(pCFData, pCTData, nWidth, nHeight);
  980. // 反变换的数据传给lpImage
  981. for(y=0; y<nHeight; y++)
  982. {
  983. for(x=0; x<nWidth; x++)
  984. {
  985. dReal = pCTData[y*nTransWidth + x].real() ;
  986. dImag = pCTData[y*nTransWidth + x].imag() ;
  987. unchValue = (unsigned char)max(0,min(255,sqrt(dReal*dReal+dImag*dImag)+100 ));
  988. lpImage[y*nWidth + x] = unchValue ;
  989. }
  990. }
  991. // 释放内存
  992. delete pCTData;
  993. delete pCFData;
  994. pCTData = NULL;
  995. pCFData = NULL;
  996. }