Android平台Camera实时滤镜实现方法探讨(九)--磨皮算法探讨(一)

转载地址:http://blog.csdn.net/oshunz/article/details/50372968


上一篇开头提到了一些可用于磨皮的去噪算法,下面我们实现这些算法并且观察效果,咱不考虑实时性的问题

本文首先探讨的首先是《基于局部均方差相关信息的图像去噪及其在实时磨皮美容算法中的应用》

该算法利用图像局部统计特性进行滤波处理,例如NXM像素的灰度图,首先计算点(i,j)所在窗口内(大小为(2n+1)(2m+1))的平均值m(i,j)


以及均方差:


得到加性去噪后的结果为:


其中:


1.根据原文提出的优化方法,首先是建立两个积分图,如图所示,点4的积分即为Sum(Ra)+Sum(Rb)+Sum(Rc)+Sum(Rd)。积分图的建立算法可以参考这篇文章进行简单优化,然后即可根据积分图计算公式中的m值和v值。


例如半径为r的窗口的m(i,j)为Integral(i+r,j+r) + Integral(i-r-1,j-r-1)-Integral(i+r,j-r-1)-Integral(i-r-1,j+r)。代码如下,分别求1次方和平方的积分图。

[cpp]  view plain  copy
  1. void MagicBeauty::initIntegral(uint8_t* inputMatrix){  
  2.     LOGE("initIntegral start");  
  3.     if(mIntegralMatrix == NULL)  
  4.         mIntegralMatrix = new uint64_t[mImageWidth * mImageHeight];  
  5.     if(mIntegralMatrixSqr == NULL)  
  6.         mIntegralMatrixSqr = new uint64_t[mImageWidth * mImageHeight];  
  7.   
  8.     uint64_t *columnSum = new uint64_t[mImageWidth];  
  9.     uint64_t *columnSumSqr = new uint64_t[mImageWidth];  
  10.   
  11.     columnSum[0] = inputMatrix[0];  
  12.     columnSumSqr[0] = inputMatrix[0] * inputMatrix[0];  
  13.   
  14.     mIntegralMatrix[0] = columnSum[0];  
  15.     mIntegralMatrixSqr[0] = columnSumSqr[0];  
  16.   
  17.     for(int i = 1;i < mImageWidth;i++){  
  18.   
  19.         columnSum[i] = inputMatrix[i];  
  20.         columnSumSqr[i] = inputMatrix[i] * inputMatrix[i];  
  21.   
  22.         mIntegralMatrix[i] = columnSum[i];  
  23.         mIntegralMatrix[i] += mIntegralMatrix[i-1];  
  24.         mIntegralMatrixSqr[i] = columnSumSqr[i];  
  25.         mIntegralMatrixSqr[i] += mIntegralMatrixSqr[i-1];  
  26.     }  
  27.     for (int i = 1;i < mImageHeight; i++){  
  28.         int offset = i * mImageWidth;  
  29.   
  30.         columnSum[0] += inputMatrix[offset];  
  31.         columnSumSqr[0] += inputMatrix[offset] * inputMatrix[offset];  
  32.   
  33.         mIntegralMatrix[offset] = columnSum[0];  
  34.         mIntegralMatrixSqr[offset] = columnSumSqr[0];  
  35.          // other columns  
  36.         for(int j = 1; j < mImageWidth; j++){  
  37.             columnSum[j] += inputMatrix[offset+j];  
  38.             columnSumSqr[j] += inputMatrix[offset+j] * inputMatrix[offset+j];  
  39.   
  40.             mIntegralMatrix[offset+j] = mIntegralMatrix[offset+j-1] + columnSum[j];  
  41.             mIntegralMatrixSqr[offset+j] = mIntegralMatrixSqr[offset+j-1] + columnSumSqr[j];  
  42.         }  
  43.     }  
  44.     delete[] columnSum;  
  45.     delete[] columnSumSqr;  
  46.     LOGE("initIntegral end");  
  47. }  

2.根据网上抄来的RGB肤色检测计算肤色区域

[cpp]  view plain  copy
  1. void MagicBeauty::initSkinMatrix(){  
  2.     LOGE("start - initSkinMatrix");  
  3.     if(mSkinMatrix == NULL)  
  4.         mSkinMatrix = new uint8_t[mImageWidth * mImageHeight];  
  5.     for(int i = 0; i < mImageHeight; i++){  
  6.         for(int j = 0; j < mImageWidth; j++){  
  7.             int offset = i*mImageWidth+j;  
  8.             ARGB RGB;  
  9.             BitmapOperation::convertIntToArgb(mImageData_rgb[offset],&RGB);  
  10.             if ((RGB.blue>95 && RGB.green>40 && RGB.red>20 &&  
  11.                     RGB.blue-RGB.red>15 && RGB.blue-RGB.green>15)||//uniform illumination  
  12.                     (RGB.blue>200 && RGB.green>210 && RGB.red>170 &&  
  13.                     abs(RGB.blue-RGB.red)<=15 && RGB.blue>RGB.red&& RGB.green>RGB.red))//lateral illumination  
  14.                 mSkinMatrix[offset] = 255;  
  15.             else  
  16.                 mSkinMatrix[offset] = 0;  
  17.         }  
  18.     }  
  19.     LOGE("end - initSkinMatrix");  
  20. }  


3.根据公式对RGB通道或者将RGB通道转化为YCbCr格式单独对Y通道进行滤波

[cpp]  view plain  copy
  1. void MagicBeauty::startLocalStatisticsSmooth(float sigema){  
  2.     if(mIntegralMatrix == NULL || mIntegralMatrixSqr == NULL ||  
  3.             mImageData_yuv_y == NULL || mSkinMatrix == NULL || mImageData_yuv == NULL){  
  4.         LOGE("not init correctly");  
  5.         return;  
  6.     }  
  7.     int radius = mImageWidth > mImageHeight ? mImageWidth * 0.02 : mImageHeight * 0.02;  
  8.   
  9.     LOGE("startSmooth");  
  10.     for(int i = 1; i < mImageHeight; i++){  
  11.         for(int j = 1; j < mImageWidth; j++){  
  12.             int offset = i * mImageWidth + j;  
  13.             if(mSkinMatrix[offset] == 255){  
  14.                 int iMax = i + radius >= mImageHeight-1 ? mImageHeight-1 : i + radius;  
  15.                 int jMax = j + radius >= mImageWidth-1 ? mImageWidth-1 :j + radius;  
  16.                 int iMin = i - radius <= 1 ? 1 : i - radius;  
  17.                 int jMin = j - radius <= 1 ? 1 : j - radius;  
  18.   
  19.                 int squar = (iMax - iMin + 1)*(jMax - jMin + 1);  
  20.                 int i4 = iMax*mImageWidth+jMax;  
  21.                 int i3 = (iMin-1)*mImageWidth+(jMin-1);  
  22.                 int i2 = iMax*mImageWidth+(jMin-1);  
  23.                 int i1 = (iMin-1)*mImageWidth+jMax;  
  24.   
  25.                 float m = (mIntegralMatrix[i4]  
  26.                         + mIntegralMatrix[i3]  
  27.                         - mIntegralMatrix[i2]  
  28.                         - mIntegralMatrix[i1]) / squar;  
  29.   
  30.                 float v = (mIntegralMatrixSqr[i4]  
  31.                         + mIntegralMatrixSqr[i3]  
  32.                         - mIntegralMatrixSqr[i2]  
  33.                         - mIntegralMatrixSqr[i1]) / squar - m*m;  
  34.                 float k = v / (v + sigema);  
  35.                     mImageData_yuv[offset*3] = m - k * m + k * mImageData_yuv_y[offset];</span>  
  36.             }  
  37.         }  
  38.     }  
  39.     endLocalStatisticsSmooth();  
  40. }  

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值