今天給你們講解一下,如何實現美顏相機中的高級柔焦效果,首先先看下美顏相機中這個功能的效果圖:css
圖1 原圖(圖片來自網絡,若有侵權敬請告知)html
圖2 美顏相機高級柔焦模版git
圖3 馬賽克效果算法
圖4,動感模糊效果網絡
以上圖3和4是兩種柔焦的效果,很不錯,今天我將用C來實現這個算法。ide
這個算法的流程以下:學習
1,前景摳圖(自動摳圖或者手動摳圖)測試
美顏相機使用的是先手動塗抹出前景目標區域,而後使用自動摳圖將該區域準確摳圖;spa
實際上,目前有不少基於深度學習的摳圖算法,效果至關不錯,好比最近比較火的實時視頻摳圖技術等等。這裏,本人仍是給出一些方法的彙總以下:.net
《Interactive graph cuts for optimal boundary and region segmentation of objects in N-D images》
《Shared Sampling for Real-Time Alpha Matting》
《A Closed Form Solution to Natural Image Matting》
《A Bayesian Approach to Digital Matting》
《Learning Based Alpha Matting using Support Vector Regression》
《Natural Image Matting using Deep Convolutional Neural Networks》
《Deep Image Matting》
本文主要介紹方法,這裏給出白百合測試圖前景摳圖的效果:
圖5 白百合前景MASK
2,背景特效你們能夠看到圖3和圖4的效果區別,主要是背景的區別,一個是馬賽克,一個是放射模糊;
所以,咱們須要對背景圖片進行相應的馬賽克和放射模糊處理,本人效果圖以下:
圖6 馬賽克效果
圖7 放射模糊效果
這裏能夠參考本人博客裏的各類濾鏡特效,實際上均可以用來作背景處理,進而得出各類不一樣的效果;
3,圖像融合
有了前景背景以後,咱們能夠根據前景的MASK(區域的二值MASK),對前景和背景進行alpha融合,公式以下:
Output = F*Mask+(255-Mask)*B
其中F表示前景,B表示背景,其中MASK中白色表示前景,黑色表示背景;
最後本人的效果圖以下:
圖8 馬賽克柔焦效果圖
圖9 放射模糊柔焦效果圖
以上三點就是柔焦效果的具體算法實現過程,最後,給出代碼邏輯(我這裏實現了四個柔焦的效果):
int f_Focus(unsigned char* srcData, int width, int height, int stride, unsigned char* mask, int intensity, int mode) { //background effects int ret = 0; int i, j; unsigned char* gaussData = (unsigned char*)malloc(sizeof(unsigned char) * stride * height); int radius = intensity * 20 / 100; switch(mode) { case 0://gauss blur effect ret = f_TFastestGaussFilter(srcData, width, height, stride, gaussData, radius); break; case 1://moscia effect memcpy(gaussData, srcData, sizeof(unsigned char) * stride * height); ret = f_TMosaic(gaussData, width, height, stride, intensity / 2); break; case 2://diffusion effect memcpy(gaussData, srcData, sizeof(unsigned char) * stride * height); ret = f_TDiffusion(gaussData, width, height, stride, intensity / 2); break; case 3://zoom blur effect memcpy(gaussData, srcData, sizeof(unsigned char) * stride * height); ret = f_TZoomBlur(gaussData, width, height, stride, width / 2, height / 2, 10, intensity); break; default: break; } //alpha blend unsigned char* pMask = mask; unsigned char* pSrc = srcData; unsigned char* pGauss = gaussData; int k, nk; for(j = 0; j < height; j++) { for(i = 0; i < width; i++) { k = pMask[0]; nk = 255 - k; pSrc[0] = CLIP3((pSrc[0] * k + pGauss[0] * nk) >> 8, 0, 255); pSrc[1] = CLIP3((pSrc[1] * k + pGauss[1] * nk) >> 8, 0, 255); pSrc[2] = CLIP3((pSrc[2] * k + pGauss[2] * nk) >> 8, 0, 255); pSrc += 4; pGauss += 4; pMask += 4; } } free(gaussData); return ret; }; int f_Test(unsigned char *srcData, int width, int height, int stride, unsigned char* mask, int intensity, int mode) { int ret = 0; //Process ret = f_Focus(srcData, width, height, stride, mask, intensity, mode); return ret; };
本人QQ1358009172,歡迎交流學習!