本文讲解导向滤波的算法与实现;
导向滤波是何凯明在2010年提出的一种滤波器,论文名称Guided Image filter,算法如下所示:
整体而言是基于均值和方差的一种保边滤波器,效果如下图所示:
代码实现如下:
int GuidedFilter(unsigned char* srcData, int width ,int height, int radius, float delta) { float *data = (float*)malloc(sizeof(float) * width * height); float *meanIP = (float*)malloc(sizeof(float) * width * height); float *corrIP = (float*)malloc(sizeof(float) * width * height); float *varIP = (float*)malloc(sizeof(float) * width * height); float *a = (float*)malloc(sizeof(float) * width * height); float *b = (float*)malloc(sizeof(float) * width * height); for(int i = 0; i < width * height; i++) { data[i] = (float)srcData[i] / 255.0; } //mean and cov compute MeanCovMapCalculate(data, width, height, meanIP, radius); for(int i = 0; i < width * height; i++) { data[i] *= data[i]; } //mean and cov compute MeanCovMapCalculate(data, width, height, corrIP, radius); for(int i = 0; i < width * height; i++) { varIP[i] = corrIP[i] - meanIP[i] * meanIP[i]; } for(int i = 0; i < width * height; i++) { a[i] = varIP[i] / (varIP[i] + delta); b[i] = meanIP[i] - a[i] * meanIP[i]; } //mean and cov compute MeanCovMapCalculate(a, width, height, meanIP, radius); MeanCovMapCalculate(b, width, height, corrIP, radius); for(int i = 0; i < width * height; i++) { srcData[i] = (unsigned char)(CLIP3((meanIP[i] * srcData[i]/255.0f + corrIP[i])*255.0f, 0, 255)); } free(data); free(meanIP); free(corrIP); free(varIP); free(a); free(b); return 0; }; void f_GuidedFilter(unsigned char* srcData, int nWidth, int nHeight, int nStride, int radius, float 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; int Y, CB, CR; 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 GuidedFilter(rData, nWidth, nHeight, radius, delta); #pragma omp section GuidedFilter(gData, nWidth, nHeight, radius, delta); #pragma omp section GuidedFilter(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_GuidedFilterOneChannel(unsigned char* srcData, int nWidth, int nHeight, int nStride, int radius, float 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; } } GuidedFilter(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; } } }
最后给出DEMO链接:点击打开链接
本人QQ: 1358009172