At the beginning of the previous article, we mentioned some denoising algorithms which can be used for grinding skin. The following we implement these algorithms and observe the effect, we do not consider the real-time problem
First of all, This paper discusses image denoising based on local mean-variance-related information and its application in real-time skin beauty algorithm.
This algorithm uses the image local statistic characteristic to carry on the filtering processing, for example NXM pixel gray-scale graph, first calculates the point (i,j) in the window body (the size is (2n+1) (2m+1)) The average value m (i,j)
and mean variance:
The results obtained after the addition of noise are:
Of
1. According to the original text proposed optimization method, first of all, the establishment of two integral map, see. The points for Point 4 are Sum (Ra) +sum (Rb) +sum (Rc) +sum (Rd). the algorithm of the integral graph can be used for the simple optimization of this paper. The M and V values in the formula can then be calculated based on the integration graph.
For example, the M (i,j) of a form with a radius of R is Integral (i+r,j+r) + Integral (i-r-1,j-r-1)-integral (i+r,j-r-1)-integral (i-r-1,j+r). Code such as the following. The integral diagram of the 1-time square and the peace square were obtained.
void Magicbeauty::initintegral (uint8_t* inputmatrix) {LOGE ("initintegral start"); if (Mintegralmatrix = = NULL) Mintegralmatrix = new Uint64_t[mimagewidth * MIMAGEHEIGHT];IF (MINTEGRALMATRIXSQR = = NULL) Mintegralmatrixsqr = new UInt64 _t[mimagewidth * mimageheight];uint64_t *columnsum = new uint64_t[mimagewidth];uint64_t *COLUMNSUMSQR = new uint64_t[ Mimagewidth];columnsum[0] = inputmatrix[0];columnsumsqr[0] = inputmatrix[0] * Inputmatrix[0];mintegralmatrix[0] = Columnsum[0];mintegralmatrixsqr[0] = columnsumsqr[0]; for (int i = 1;i < mimagewidth;i++) {Columnsum[i] = Inputmatrix[i]; Columnsumsqr[i] = inputmatrix[i] * Inputmatrix[i]; Mintegralmatrix[i] = Columnsum[i]; Mintegralmatrix[i] + = mintegralmatrix[i-1]; Mintegralmatrixsqr[i] = Columnsumsqr[i]; Mintegralmatrixsqr[i] + = mintegralmatrixsqr[i-1]; } for (int i = 1;i < Mimageheight; i++) {int offset = i * mimagewidth; Columnsum[0] + = Inputmatrix[offset]; Columnsumsqr[0] + = Inputmatrix[offset] * Inputmatrix[offset]; Mintegralmatrix[offset] = columnsum[0]; Mintegralmatrixsqr[offset] = columnsumsqr[0]; Other columns for (int j = 1; j < Mimagewidth; J + +) {Columnsum[j] + inputmatrix[offset+j]; COLUMNSUMSQR[J] + = inputmatrix[offset+j] * Inputmatrix[offset+j]; MINTEGRALMATRIX[OFFSET+J] = Mintegralmatrix[offset+j-1] + columnsum[j]; MINTEGRALMATRIXSQR[OFFSET+J] = Mintegralmatrixsqr[offset+j-1] + columnsumsqr[j]; }} delete[] columnsum; Delete[] COLUMNSUMSQR; LOGE ("Initintegral End");}
2. Calculate the skin tone area based on the RGB skin color detected online
void Magicbeauty::initskinmatrix () {LOGE ("Start-initskinmatrix"); if (Mskinmatrix = = NULL) Mskinmatrix = new uint8_t[ Mimagewidth * mimageheight];for (int i = 0; i < mimageheight; i++) {for (int j = 0; J < Mimagewidth; J + +) {int offset = I*mimagewidth+j; ARGB RGB; Bitmapoperation::convertinttoargb (MIMAGEDATA_RGB[OFFSET],&RGB); if (rgb.blue>95 && RGB.green>40 && rgb.red>20 &&rgb.blue-rgb.red>15 && rgb.blue-rgb.green>15) | | Uniform illumination (rgb.blue>200 && rgb.green>210 && rgb.red>170 &&abs ( rgb.blue-rgb.red) <=15 && rgb.blue>rgb.red&& rgb.green>rgb.red))//lateral Illuminationmskinmatrix[offset] = 255;elsemskinmatrix[offset] = 0;}} LOGE ("End-initskinmatrix");}
3. Filter the Y channel separately according to the formula on the RGB channel or convert the RGB channel to YCBCR format
void Magicbeauty::startlocalstatisticssmooth (float sigema) {if (Mintegralmatrix = = NULL | | mintegralmatrixsqr = = NULL | | mimagedata_yuv_y = = NULL | | Mskinmatrix = = NULL | | MIMAGEDATA_YUV = = NULL) {LOGE ("not init correctly"); return;} int radius = mimagewidth > mimageheight?Mimagewidth * 0.02:mimageheight * 0.02; LOGE ("Startsmooth"); for (int i = 1, i < mimageheight; i++) {for (int j = 1; j < Mimagewidth; J + +) {int offset = i * Mima Gewidth + j;if (mskinmatrix[offset] = = 255) {int IMax = i + radius >= mImageHeight-1? mImageHeight-1: i + radius;int JM Ax = j + radius >= mImageWidth-1? MImageWidth-1: j + radius;int imin = I-radius <= 1? 1:I-Radius;int jmin = J-radius <= 1?
1:j-Radius;int Squar = (imax-imin + 1) * (jmax-jmin + 1); int i4 = Imax*mimagewidth+jmax;int i3 = (iMin-1) *mimagewidt H + (jMin-1); int i2 = imax*mimagewidth+ (jMin-1); int i1 = (iMin-1) *mimagewidth+jmax;float m = (mintegralmatrix[i4]+ mintegralmatrix[i3]-mintegralmatrix[i2]-Mintegralmatrix[i1])/squar;float v = (mintegralmatrixsqr[i4]+ mintegralmatrixsqr[i3]-mintegralmatrixsqr[i2]-Mintegralmatrixsqr[i1])/squar-m*m;float k = v/(v + sigema); MIMAGEDATA_YUV[OFFSET*3] = m-k * m + k * Mimagedata_yuv_y[offset];</span>}}}endlocalstatisticssmooth ();}
: Grinding strength is max.
Watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqv/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/dissolve/70/gravity /southeast ">
An approach to the implementation of camera real-time filter in Android platform (ix)--discussion on the algorithm of grinding skin (I.)