局部均值滤波算法是基于均值改进的一种具有一定保边能力的滤波器,参考论文为Lee filter Digital image enhancement and noise filtering by using local statistics,具体算法如下:
本人C实现效果如下:
主要代码如下:
int LSNFilterOneChannel(unsigned char* srcData, int width ,int height, int radius, int delta)
{
int len = sizeof(unsigned long) * width * height;
unsigned char* dstData = (unsigned char*)malloc(len);
unsigned long* meanData = (unsigned long*) malloc(len);
unsigned long* covData = (unsigned long*) malloc(len);
memset(meanData, 0, len);
memset(covData, 0, len);
MeanCovMapCalculate(srcData, width, height, width, meanData, covData, radius);
float mean = 0, cov = 0, K = 0;
int i, j, num = 2 * radius + 1;
num = num * num;
int gray = 0;
for(j = 0; j < height; j++ )
{
for(i = 0; i < width; i++)
{
len = i + j * width;
mean = (float)meanData[len];
cov = (float)covData[len];
cov = cov - mean * mean;
K = cov / (cov + delta);
gray = (int)((1.0 - K) * mean + K * (float)srcData[len]);
dstData[len] = CLIP3(gray, 0, 255);
}
}
memcpy(srcData, dstData, len);
free(meanData);
free(covData);
free(dstData);
return 0;
};
void f_LSNFilter(unsigned char* srcData, int nWidth, int nHeight, int nStride, int radius, int delta)
{
if (srcData == NULL)
{
return;
}
unsigned char* rData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight);
unsigned char* gData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight);
unsigned char* bData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight);
unsigned char* pSrc = srcData;
unsigned char* pR = rData;
unsigned char* pG = gData;
unsigned char* pB = bData;
for(int j = 0; j < nHeight; j++)
{
for(int i = 0; i < nWidth; i++)
{
*pR = pSrc[2];
*pG = pSrc[1];
*pB = pSrc[0];
pR++;
pG++;
pB++;
pSrc += 4;
}
}
#pragma omp parallel sections num_threads(omp_get_num_procs())
{
#pragma omp section
LSNFilterOneChannel(rData, nWidth, nHeight, radius, delta);
#pragma omp section
LSNFilterOneChannel(gData, nWidth, nHeight, radius, delta);
#pragma omp section
LSNFilterOneChannel(bData, nWidth, nHeight, radius, delta);
}
pSrc = srcData;
pR = rData;
pG = gData;
pB = bData;
int R, G, B;
for(int j = 0; j < nHeight; j++)
{
for(int i = 0; i < nWidth; i++)
{
pSrc[0] = *pB;
pSrc[1] = *pG;
pSrc[2] = *pR;
pR++;
pG++;
pB++;
pSrc += 4;
}
}
free(rData);
free(gData);
free(bData);
}
void f_LSNFilterOneChannel(unsigned char* srcData, int nWidth, int nHeight, int nStride, int radius, int delta)
{
if (srcData == NULL)
{
return;
}
unsigned char* yData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight);
unsigned char* cbData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight);
unsigned char* crData = (unsigned char*)malloc(sizeof(unsigned char) * nWidth * nHeight);
unsigned char* pSrc = srcData;
int Y, CB, CR;
unsigned char* pY = yData;
unsigned char* pCb = cbData;
unsigned char* pCr = crData;
for(int j = 0; j < nHeight; j++)
{
for(int i = 0; i < nWidth; i++)
{
RGBToYCbCr(pSrc[2],pSrc[1],pSrc[0],&Y,&CB,&CR);
*pY = Y;
*pCb = CB;
*pCr = CR;
pY++;
pCb++;
pCr++;
pSrc += 4;
}
}
LSNFilterOneChannel(yData, nWidth, nHeight, radius, delta);
pSrc = srcData;
pY = yData;
pCb = cbData;
pCr = crData;
int R, G, B;
for(int j = 0; j < nHeight; j++)
{
for(int i = 0; i < nWidth; i++)
{
YCbCrToRGB(*pY, *pCb, *pCr, &R, &G, &B);
pSrc[0] = B;
pSrc[1] = G;
pSrc[2] = R;
pY++;
pCb++;
pCr++;
pSrc += 4;
}
}free(yData);free(cbData);free(crData);
}
最后给出完整的DEMO:点击打开链接
本人QQ : 1358009172