292 lines
8.3 KiB
C++
292 lines
8.3 KiB
C++
#include "stdafx.h"
|
||
#include "NLmeans.h"
|
||
#include <stdlib.h>
|
||
|
||
//全局变量
|
||
int g_nSigma = 50; // 高斯曲线参数sigma
|
||
int g_nSWBlocX = 9; // 搜索窗口,行方向
|
||
int g_nSWBlocY = 9; // 搜索窗口,列方向
|
||
int g_nPWBloc = 1; // 匹配窗口大小
|
||
|
||
// 高斯滤波不同权值拟合直线k、b,10组数据分别表示滤波参数sigma=10:10:100的拟合结果
|
||
int g_nGaussK[10] = {-159, -80, -53, -40, -32, -27, -23, -20, -18, -16};
|
||
int g_nGaussB[10] = {4100, 4114, 4118, 4120, 4121, 4122, 4123, 4123, 4123, 4124};
|
||
|
||
|
||
/***************************************************************************
|
||
* NlMeansDenoiseCenter()
|
||
* 功能描述:NL-MEANS 图像去噪算法函数 一次只更新中心像素
|
||
* 输入参数:
|
||
* unsigned char bitWitdth 输入数据位宽8位/16位
|
||
* unsigned short pSrc16 16位输入数据
|
||
* unsigned char pSrc8 8位输入数据
|
||
* int nHeight 图像高度
|
||
* int nWidth 图像宽度
|
||
* 输出参数:unsigned short pSrc16 16位输出数据 输入是16位数据,输出也为16位数据
|
||
* unsigned char pSrc8 8位输出数据 输入是8位数据,输出也为8位数据
|
||
* 返 回 值:
|
||
* 调用关系
|
||
* 调用函数:图像边缘扩展ImageExpandINT()
|
||
图像边缘切割ImageExpandInverseINT()
|
||
* 被调函数:ArithProcessFunc()
|
||
***************************************************************************/
|
||
void NlMeansDenoiseCenter(unsigned char bitWitdth,
|
||
unsigned short *pSrc16,
|
||
unsigned char* pSrc8,
|
||
int nWidth, int nHeight)
|
||
{
|
||
//搜索窗口大小
|
||
int nSWBlocX = g_nSWBlocX;
|
||
int nSWBlocY = g_nSWBlocY;
|
||
//int nSWBlocX = 8;
|
||
//int nSWBlocY = 8;
|
||
|
||
//高斯滤波标准差
|
||
int nSigma = g_nSigma;
|
||
|
||
//匹配窗口参数设置
|
||
int nPWBloc = g_nPWBloc; //nPWBloc = 1
|
||
|
||
//高斯线性拟合K、B
|
||
int k = g_nGaussK[nSigma/10 - 1];
|
||
int b = g_nGaussB[nSigma/10 - 1];
|
||
|
||
|
||
//分配空间及初始化-->change into 16bit datablock
|
||
int nLen = nWidth * nHeight;
|
||
unsigned short *pImgTemp= new unsigned short[nLen];
|
||
memset(pImgTemp,0,sizeof(unsigned short) * nLen);
|
||
|
||
|
||
if(bitWitdth == 8)
|
||
{
|
||
for(int i = 0;i < nLen;i++)
|
||
{
|
||
pImgTemp[i] = pSrc8[i];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
memcpy(pImgTemp,pSrc16,sizeof(unsigned short) * nLen);
|
||
}
|
||
|
||
|
||
// 距离、权重相关的变量
|
||
int nWeight = 0;
|
||
int nMaxWeight = 0;
|
||
int nSumWeight = 0;
|
||
int nDif = 0;
|
||
int nSumDif = 0;
|
||
double nDstValue = 0;
|
||
|
||
|
||
// 图像扩展 将原始图像进行扩展
|
||
int nWidthNew = nWidth + 2 * (nSWBlocX + nPWBloc);
|
||
int nHeightNew = nHeight + 2 * (nSWBlocY + nPWBloc);
|
||
int nLenNew = nWidthNew * nHeightNew;
|
||
|
||
//分配扩展后图像空间并初始化
|
||
unsigned short *pImgExpand = new unsigned short[nLenNew];
|
||
memset(pImgExpand,0,sizeof(unsigned short) * nLenNew);
|
||
|
||
//存放降噪结果的数组
|
||
unsigned short *pImgOut = new unsigned short[nLenNew];
|
||
memset(pImgOut,0,sizeof(unsigned short) * nLenNew);
|
||
|
||
//图像边缘扩展
|
||
ImageExpandINT(pImgTemp,nWidth,nHeight,pImgExpand,nWidthNew,nHeightNew);
|
||
|
||
|
||
////////////////////////////////////// PROCESS STARTS//////////////////////////////////////////////////
|
||
// 针对每个像素进行去噪处理
|
||
int nSpos = 0;
|
||
int nPpos = 0;
|
||
for ( int y = nSWBlocY + nPWBloc; y < nHeightNew - nSWBlocY - nPWBloc; y++) //第一个去噪待处理点y坐标 原始图像的第一个点 pImgTemp(0,0)
|
||
{
|
||
for ( int x = nSWBlocX + nPWBloc ; x < nWidthNew - nSWBlocX - nPWBloc; x++)//第一个去噪待处理点x坐标
|
||
{
|
||
nWeight = 0;
|
||
nMaxWeight = 0;
|
||
nSumWeight = 0;
|
||
nDstValue = 0;
|
||
|
||
//单元区域内处理,结果存放到WinsDenoised
|
||
for (int j = y - nSWBlocY;j <= y + nSWBlocY;j++)
|
||
{
|
||
for ( int i = x - nSWBlocX ; i <= x + nSWBlocX; i++)
|
||
{
|
||
nDif = 0;
|
||
nSumDif = 0;
|
||
for (int s = -nPWBloc; s <= nPWBloc; s++)
|
||
{
|
||
nSpos = (j + s) * nWidthNew + i; //搜索窗口内的其他窗口
|
||
nPpos = (y + s ) * nWidthNew + x ;//待处理像素窗口
|
||
|
||
for (int r = -nPWBloc; r <= nPWBloc; r++)
|
||
{
|
||
nDif = pImgExpand[nSpos + r] - pImgExpand[nPpos + r];
|
||
nSumDif += abs(nDif);
|
||
}
|
||
}
|
||
|
||
//通过拟合直线计算高斯权值 , k,b在拟合时已放大4096倍
|
||
if (nSumDif >= 3*nSigma)
|
||
{
|
||
nWeight = 0;
|
||
}
|
||
else
|
||
{
|
||
nWeight = (b - k * nSumDif);
|
||
}
|
||
|
||
if (nWeight < 0)
|
||
{
|
||
nWeight = 0;
|
||
}
|
||
else if (nWeight > 4096)
|
||
{
|
||
nWeight = 4096;
|
||
}
|
||
|
||
|
||
//记录最大权重fmaxWeight和总权重fTotalWeight
|
||
nMaxWeight = __max(nMaxWeight , nWeight);
|
||
nSumWeight += nWeight;
|
||
|
||
nDstValue += nWeight*pImgExpand[j*nWidthNew+i];
|
||
|
||
}
|
||
}
|
||
|
||
|
||
//如果总权重为正数,则计算该单元区域中心点的估计值
|
||
if (nSumWeight > 0)
|
||
{
|
||
pImgOut[y * nWidthNew + x] = (unsigned short)(nDstValue / nSumWeight);
|
||
}
|
||
else
|
||
{
|
||
pImgOut[y * nWidthNew + x] = pImgExpand[y * nWidthNew + x];
|
||
}
|
||
}//y
|
||
}//x
|
||
|
||
//截取去噪后图像
|
||
ImageExpandInverseINT(pImgOut,nWidth,nHeight,pImgOut,nWidthNew,nHeightNew);
|
||
|
||
|
||
if(bitWitdth == 8)
|
||
{
|
||
for(int i = 0;i < nLen;i++)
|
||
{
|
||
pSrc8[i] =(unsigned char)pImgOut[i];
|
||
}
|
||
}
|
||
else
|
||
{
|
||
memcpy(pSrc16,pImgOut,sizeof(unsigned short) * nLen);
|
||
}
|
||
|
||
|
||
//释放内存
|
||
delete [] pImgTemp;
|
||
delete [] pImgExpand;
|
||
delete [] pImgOut;
|
||
|
||
}
|
||
|
||
|
||
/***************************************************************************
|
||
* ImageExpandINT()
|
||
* 功能描述:图像边缘扩展函数,将原图像向周围扩展边缘
|
||
* 输入参数:
|
||
* unsigned short* pSrc 输入数据
|
||
* int nHeight 输入图像高度
|
||
* int nWidth 输入图像宽度
|
||
* int NewWidth 边缘扩展后图像宽度
|
||
* int NewHeight 边缘扩展后图像高度
|
||
*
|
||
* 输出参数:unsigned short *pDst 输出边缘扩展后数据
|
||
* 返 回 值:无
|
||
* 调用关系
|
||
* 调用函数:无
|
||
* 被调函数:NLM去噪算法NlMeansDenoiseCenter()
|
||
***************************************************************************/
|
||
void ImageExpandINT(unsigned short* pSrc,int nWidth,int nHeight,unsigned short *pDst,int NewWidth,int NewHeight)
|
||
{
|
||
|
||
int nstepW= (int)((NewWidth - nWidth) / 2);
|
||
int nstepH = (int)((NewHeight - nHeight) / 2);
|
||
int i = 0;
|
||
int j = 0;
|
||
|
||
for (i = nstepH;i < nstepH + nHeight;i++)
|
||
{
|
||
for(j = 0;j < nstepW;j++)
|
||
{
|
||
pDst[i * NewWidth+j] = pSrc[(i - nstepH) * nWidth + 0];
|
||
}
|
||
for(j = nstepW;j < nstepW + nWidth;j++)
|
||
{
|
||
pDst[i * NewWidth + j] = pSrc[(i - nstepH) * nWidth + (j - nstepW)];
|
||
}
|
||
for(j = nstepW + nWidth;j < NewWidth;j++)
|
||
{
|
||
pDst[i * NewWidth + j] = pSrc[(i - nstepH) * nWidth + nWidth - 1];
|
||
}
|
||
}
|
||
|
||
for(i = 0;i < nstepH;i++)
|
||
{
|
||
for( j = 0;j < NewWidth;j++)
|
||
{
|
||
pDst[i * NewWidth + j] = pDst[nstepH * NewWidth + j];
|
||
}
|
||
|
||
}
|
||
|
||
for(i = nstepH + nHeight;i < NewHeight;i++)
|
||
{
|
||
for(j = 0;j < NewWidth;j++)
|
||
{
|
||
pDst[i * NewWidth + j] = pDst[(nstepH + nHeight - 1) * NewWidth + j];
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
/***************************************************************************
|
||
* ImageExpandInverseINT()
|
||
* 功能描述:图像边缘切割, 将图像扩展的边缘去掉,获取与原图像相同大小和位置的数据
|
||
* 输入参数:
|
||
* unsigned short* pSrc 输入数据
|
||
* int nHeight 输入图像高度
|
||
* int nWidth 输入图像宽度
|
||
* int NewWidth 边缘扩展后图像宽度
|
||
* int NewHeight 边缘扩展后图像高度
|
||
*
|
||
* 输出参数:unsigned short *pDst 输出边缘扩展后数据
|
||
* 返 回 值:无
|
||
* 调用关系
|
||
* 调用函数:无
|
||
* 被调函数:NLM去噪算法NlMeansDenoiseCenter()
|
||
***************************************************************************/
|
||
void ImageExpandInverseINT(unsigned short* pSrc,int nWidth,int nHeight,unsigned short *pDst,int NewWidth,int NewHeight)
|
||
{
|
||
|
||
int nstepW = (int)((NewWidth - nWidth) / 2);
|
||
int nstepH = (int)((NewHeight - nHeight) / 2);
|
||
|
||
unsigned short * pos = NULL;
|
||
|
||
pos = pDst + nstepH * NewWidth + nstepW;
|
||
for (int i = 0;i < nHeight;i++)
|
||
{
|
||
memcpy(pSrc + i * nWidth, pos,sizeof(unsigned short) * nWidth);
|
||
pos = pos + NewWidth;
|
||
}
|
||
}
|
||
|
||
|